pothosware / SoapySDR

Vendor and platform neutral SDR support library.
https://github.com/pothosware/SoapySDR/wiki
Boost Software License 1.0
1.11k stars 177 forks source link

Enhancement request: SoapySDR module for Red Pitaya #55

Closed dc1rdb closed 8 years ago

dc1rdb commented 8 years ago

Red Pitaya is a credit-card sized measuring device that runs Linux and has Ethernet and USB. It has two RF inputs and two RF outputs (50 MHz, 125 MSPS, 14 bit), all connected to an Xilinx SoC that includes an FPGA. It was originally designed to be used as an oscilloscope, spectrum analyzer, function generator etc., but the RF properties would make it a good SDR platform with transmit and receive functionalities.

pavel-demin commented 8 years ago

Since Pothosware/SoapySDR works with gr-osmosdr and gr-osmosdr works with Red Pitaya SDR transceiver, it should be possible to use Red Pitaya SDR transceiver with Pothosware/SoapySDR via the gr-osmosdr interface: https://github.com/pothosware/SoapyOsmo/wiki

You can download gr-osmosdr with support for the Red Pitaya SDR transceiver from my fork of the gr-osmosdr repository: https://github.com/pavel-demin/gr-osmosdr

Then you can build gr-osmosdr following the instructions from: http://sdr.osmocom.org/trac/wiki/GrOsmoSDR

dc1rdb commented 8 years ago

Thank you - I will try this approach as soon as I get my Red Pitaya 2.0!

guruofquality commented 8 years ago

Note that SoapyOsmo has a copy of gr-osmosdr in it with some "shims" to register the source/sink into a soapy device and to integrate with the streaming api:

GrOsmoSDR can use soapy devices through its lib/soapy source/sink stream wrapper. But there isnt a convenient way in the other direction. You pretty much will have to copy your Red Pitaya GrOsmoSDR fork into SoapyOsmo and put an entry into the top level CMakeLists.

It looks like a pretty small wrapper around a socket application: https://github.com/pavel-demin/gr-osmosdr/tree/master/lib/red_pitaya In any case I would be happy to mentor a SoapyRedPitaya wrapper if there is a volunteer.

pavel-demin commented 8 years ago

Not many volunteers so far...

I've just had a quick look at other Soapy* drivers and found thousands lines of code. At the moment, I'm not sure that I'm ready for such an effort.

Would it be possible to do something similar to what I did with GNU Radio and to wrap an existing block or module that would do all the I/O?

guruofquality commented 8 years ago

Not many volunteers so far...

If there is a Red Pitaya forum to ask, that might help. Theres not that many subscribers to this issue channel, and I bet most if not all don't have the device.

I've just had a quick look at other Soapy* drivers and found thousands lines of code. At the moment, I'm not sure that I'm ready for such an effort.

Its probably on the same order of magnitude compared to gr-osmosdr. Comparing to projects that just wrap another interface, probably about 1500-2000 lines. A good portion of that is boiler plate. And given that the Red Pitaya has way less available controls, it would probably be smaller.

There are plenty of projects that do quite a bit more than wrap a simple device driver and that might be confusing as an example. So, I think the following are good examples of wrapping a single device, if it helps:

Would it be possible to do something similar to what I did with GNU Radio and to wrap an existing block or module that would do all the I/O?

Wrapping an audio card into SoapySDR comes up a lot as well. Even though its basically just streaming and sample rate controls. SoapySDR is overkill for this, but for some, the idea is just that there is value in a common wrapper or interface.

Its certainly feasible to wrap the Red Pitaya network interface directly into a block, forgoing all of the SDR abstraction. I guess that the advantage with a SoapySDR wrapper is that it potentially brings the device into multiple SDR environments for the same effort.

pavel-demin commented 8 years ago

Thanks for the links. I somehow missed SoapyBladeRF. I'd say that it's cleaner and shorter than the other drivers. It looks like a perfect starting point.

Is it OK to call the blocking recv() and send() functions from readStream() and writeStream()? If it's OK, then readStream() could be as simple as return recv(_rxSocket, buffs[0], 8 * numElems, MSG_WAITALL) / 8;.

guruofquality commented 8 years ago

Is it OK to call the blocking recv() and send() functions from readStream() and writeStream()?

Yes to blocking, but I recommend implementing the timeout as well. Example snippet for rx if that helps:

    struct timeval tv;
    tv.tv_sec = timeoutUs / 1000000;
    tv.tv_usec = timeoutUs % 1000000;

    fd_set readfds;
    FD_ZERO(&readfds);
    FD_SET(_sock, &readfds);

    int ret = ::select(_sock+1, &readfds, NULL, NULL, &tv);
    //not ready? return SOAPY_SDR_TIMEOUT;
pavel-demin commented 8 years ago

For information. The gr-osmosdr blocks for Red Pitaya SDR transceiver are now in the main gr-osmosdr repository: http://cgit.osmocom.org/gr-osmosdr/commit/?id=3582ba17e0d7a5237c6393a1c5849533692018f7

guruofquality commented 8 years ago

@pavel-demin I tried to get the gr-osmosdr redpitaya support to build for SoapyOsmo, but it looks likes the redpitaya is different than the the other gr-osmosdr blocks. The redpitaya blocks are hierarchical and use the file descriptor source and sink blocks from gnuradio. Basically the SoapyOsmo doesn't depend on gnuradio, and it doesnt have any concept of hierarchical blocks or file descriptor blocks. It just knows how to interface with the gr::syncblock classes.

Anyway, it SoapyOsmo doesn't compile for redpitaya as-is. But one of the following things could be done to address it:

1) change redpitaya source/sink implementation to be syncblock and implement a work function that read/writes the socket.

or 2)

pavel-demin commented 8 years ago

Thanks for your quick test. I didn't know that SoapyOsmo doesn't depend on GNU Radio.

Looks like a standalone SoapyRedPitaya wrapper would be indeed the most straightforward solution.

.. it looks likes the redpitaya is different than the the other gr-osmosdr blocks. The redpitaya blocks are hierarchical and use the file descriptor source and sink blocks from gnuradio.

Actually, the Red Pitaya blocks are based on the gr-osmosdr/lib/file block: https://github.com/pothosware/SoapyOsmo/blob/master/gr-osmosdr/lib/file/file_source_c.h

The file block is also hierarchical and depends on GNU Radio.

dc1rdb commented 8 years ago

@guruofquality, @pavel-demin , really appreciate you analyzing this issue. I should be getting my RedPitaya hardware on Monday and will be available for any testing to help solve the issue. Thanks very much!

pavel-demin commented 8 years ago

I've put together a preliminary version of a plug-in for Red Pitaya SDR transceiver: https://github.com/pavel-demin/red-pitaya-notes/blob/develop/projects/sdr_transceiver/SoapyRedPitaya/

I'm trying to test it under Ubuntu 14.04. I installed the pre-built packages following the instructions that I found at https://github.com/pothosware/pothos/wiki/Downloads

I can build and install the plug-in but I have some problems with PothosGui:

guruofquality commented 8 years ago

Sorry about that im in the process of uploading new packages to the PPA for the latest release. The packages are all out of sync at the moment.

dc1rdb commented 8 years ago

Building the plugin fails on my machine. Am I missing something?

imac:~ rduering$ cd SoapyRedPitaya
imac:SoapyRedPitaya rduering$ mkdir build
imac:SoapyRedPitaya rduering$ cd build
imac:build rduering$ cmake ../ -DCMAKE_BUILD_TYPE=Release
-- The CXX compiler identification is AppleClang 6.0.0.6000057
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/rduering/SoapyRedPitaya/build
imac:build rduering$ make
Scanning dependencies of target RedPitaya
[ 50%] Building CXX object CMakeFiles/RedPitaya.dir/SoapyRedPitaya.cpp.o
/Users/rduering/SoapyRedPitaya/SoapyRedPitaya.cpp:175:5: warning: control may
      reach end of non-void function [-Wreturn-type]
    }
    ^
/Users/rduering/SoapyRedPitaya/SoapyRedPitaya.cpp:258:60: error: use of
      undeclared identifier 'MSG_NOSIGNAL'
        return ::send(_sockets[1], buffs[0], 8 * numElems, MSG_NOSIGNAL) / 8;
                                                           ^
/Users/rduering/SoapyRedPitaya/SoapyRedPitaya.cpp:361:58: error: use of
      undeclared identifier 'MSG_NOSIGNAL'
        size = ::send(socket, &command, sizeof(command), MSG_NOSIGNAL);
                                                         ^
1 warning and 2 errors generated.
make[2]: *** [CMakeFiles/RedPitaya.dir/SoapyRedPitaya.cpp.o] Error 1
make[1]: *** [CMakeFiles/RedPitaya.dir/all] Error 2
make: *** [all] Error 2
pavel-demin commented 8 years ago

Thanks for the test.

MSG_NOSIGNAL is not defined on MacOSX. I've just added a workaround with the following commit: https://github.com/pavel-demin/red-pitaya-notes/commit/3cf61ff0a1ffa4104017ba4fdeff2cd3fc3e28a2

pavel-demin commented 8 years ago

Red Pitaya source seems to work: pothos-gui

pavel-demin commented 8 years ago

I'm trying to build a simple AM/SSB transceiver configuration but can't find how to implement abs(cf32) and real(cf32). Any hints?

dc1rdb commented 8 years ago

Thanks for the quick fix! Latest commit https://github.com/pavel-demin/red-pitaya-notes/commit/dc5a7aab4e5cdc5b6fe1f3b54b021422d93d4d62 builds ok now under Mac OS X - just one warning:

imac:build rduering$ make
Scanning dependencies of target RedPitaya
[ 50%] Building CXX object CMakeFiles/RedPitaya.dir/SoapyRedPitaya.cpp.o
/Users/rduering/SoapyRedPitaya/SoapyRedPitaya.cpp:181:5: warning: control may
      reach end of non-void function [-Wreturn-type]
    }
    ^
1 warning generated.
[100%] Linking CXX shared module libRedPitaya.so
[100%] Built target RedPitaya
imac:build rduering$ sudo make install
Password:
[100%] Built target RedPitaya
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/lib/SoapySDR/modules/libRedPitaya.so

Going to test with real hardware tomorrow!

guruofquality commented 8 years ago

Cool, glad to hear that it works!

I'm trying to build a simple AM/SSB transceiver configuration but can't find how to implement abs(cf32) and real(cf32). Any hints?

Theres the gnuradio support which brings in quite a number of blocks. Though I don't have binaries yet, so its going to be a source install, and its 3 steps: https://github.com/pothosware/gnuradio/wiki

I am happy to add generally useful blocks to the pothos-comms toolkit: https://github.com/pothosware/pothos-comms/issues Feel free to make suggestions on the issue tracker or have a try at making some blocks. I am thinking that a templated complex operations math block would be useful (real, imag, mag, angle, conj).

guruofquality commented 8 years ago

As a note, you may want to connect the sockets in the constructor:

1) an API user may set the frequency before configuring streaming. (uses socket[0]) 2) it looks like setupStream() would re-connect the same sockets without close if called once for SOAPY_SDR_RX and once for SOAPY_SDR_TX

dc1rdb commented 8 years ago

Latest commit a7b2e44 fails to build under MacOS X:

[ 50%] Building CXX object CMakeFiles/RedPitaya.dir/SoapyRedPitaya.cpp.o
/Users/rduering/SoapyRedPitaya/SoapyRedPitaya.cpp:336:49: error: arithmetic on a
      pointer to void
            size = ::send(_sockets[3], buffs[0] + n, total - n, MSG_NOSIGNAL);
                                       ~~~~~~~~ ^
1 error generated.
make[2]: *** [CMakeFiles/RedPitaya.dir/SoapyRedPitaya.cpp.o] Error 1
make[1]: *** [CMakeFiles/RedPitaya.dir/all] Error 2
make: *** [all] Error 2
effeerre75 commented 8 years ago

Try to add (char*) just before buffs[0] at line 336 of SoapyRedPitaya.cpp Didn't try it but should works.

size = ::send(_sockets[3], (char*)buffs[0] + n, total - n, MSG_NOSIGNAL);

dc1rdb commented 8 years ago

@effeerre75 thanks - that did the trick!

pavel-demin commented 8 years ago

There is a new version of the gr-osmosdr blocks for Red Pitaya SDR transceiver with the blocks implemented as sync blocks: http://cgit.osmocom.org/gr-osmosdr/commit/?id=810a981d0c2975825a72c9c6c9db2700719928c3

I've just tested it with the latest version of the SoapyOsmo driver. Both source and sink blocks work: pothos-gui-2

guruofquality commented 8 years ago

SoapyOsmo

I updated gr-osmosdr for SoapyOsmo and added the RedPitaya build. Like many of the other osmo modules that also have dedicated soapy plugins, the RedPitaya is disabled by default in favor of the Soapy one: https://github.com/pothosware/SoapyOsmo/commit/def5921eeb3bf32fa5347b68bdcb5a6b8f8dec98 When the code stabilizes I will also put a new version tag on SoapyOsmo repo.

Socket close issue

I see a lot of code that sets the socket to -1 and then closes it. I think you want this reversed. first close the socket, then set its file descriptor to -1.

        _sockets[0] = -1;
        _sockets[2] = -1;

        #if defined(_WIN32) || defined (__CYGWIN__)
        ::closesocket(_sockets[0]);
        ::closesocket(_sockets[2]);
        #else
        ::close(_sockets[0]);
        ::close(_sockets[2]);
        #endif

SoapyRedPitaya

Is this the long-term location for this code? https://github.com/pavel-demin/red-pitaya-notes/tree/develop/projects/sdr_transceiver/SoapyRedPitaya

If you are interested, I can host a SoapyRedPitaya repo on this github organization. Whatever is most convenient. At the end of the day, I just to be able to make some links that wont change. So, eventually when the dust settles and this stabilizes, I would like to...

I hope that sounds alright

pavel-demin commented 8 years ago

Finally, I have a version of SoapyRedPitaya that works.

Is this the long-term location for this code?

No, it's just a temporary location. It would be great if you could host SoapyRedPitaya. I agree with all your suggestions.

pavel-demin commented 8 years ago

I've just noticed that setupStream(SOAPY_SDR_TX, ...) is called when PothosGUI starts and opens my .pth file. setupStream(SOAPY_SDR_RX, ...) is called when I click on 'Activate topology'. Is it a feature or a bug? I'd expect them both to be called in the same time when I click on 'Activate topology'. I tried to set 'Auto Activate' to 'Manual' but it didn't help.

I've also noticed that closeStream is only called when I close my .pth file. I'd expect it to be called when topology is deactivated.

The problem that I'm trying to solve is that I can't have two .pth files using SoapyRedPitaya open in PothosGUI and switch from one to another by activating and deactivating them.

guruofquality commented 8 years ago

SoapyRedPitaya repo: Here is an empty repo, you should have an invite for access: https://github.com/pothosware/SoapyRedPitaya

other comments below...

I've just noticed that setupStream(SOAPY_SDR_TX, ...) is called when PothosGUI starts and opens my .pth file. setupStream(SOAPY_SDR_RX, ...) is called when I click on 'Activate topology'. Is it a feature or a bug? I'd expect them both to be called in the same time when I click on 'Activate topology'. I tried to set 'Auto Activate' to 'Manual' but it didn't help. I've also noticed that closeStream is only called when I close my .pth file. I'd expect it to be called when topology is deactivated.

setup race: The reason that setupStream(rx vs tx) is getting called at different times is that there is a race. If the device is still being setup in the background when setting calls are made (including setupStream), those calls are saved for later and applied forcibly when the block is activated.

You are probably right that this is a bug. I definitely wrote the code like this, but thinking about it more, its not the intended behaviour. I want the setting calls applied ASAP when the device setup completes. Activating the topology will still force the calls to be made if they weren’t, but that would only happen when you mouse clicking is faster than the underlying code to open and initialize the device.

setup/close vs activate/deactivate: To explain the setup/close vs activate/deactivate: The way the SDR source and sink blocks are currently implemented, the stream is setup at block construction time, and the stream is closed at block destruction time. When the topology is activated/deactivated, the activate() and deactivate() hooks on the block call the corresponding SoapySDR activate/deactivate stream API calls.

The idea was that the setupStream() calls does the "heavy lifting" (like allocation, setup socket, setup routing), where activateStream() does the minimum needed to enable streaming (like write a register to start the flow). The SDR source/sink block are trying to reflect this idea by doing the "heavy lifting" at block construction time and before activation.

The problem that I'm trying to solve is that I can't have two .pth files using SoapyRedPitaya open in PothosGUI and switch from one to another by activating and deactivating them.

I see what you mean. Because the GUI actually opens and configures the device, the same device referenced in multiple tabs will "step all over each other". Even if setupStream() was called at activate time, the other settings on the device like frequency would still conflict between the two tabs. I need to think about this... For now, disabling a SDR source/sink block in another tab when its not in use may be helpful.

dc1rdb commented 8 years ago

Still struggling to get the module to work on OS X. Here is my setup: red_pitaya_OS_v0.94-RC21_2-Dec-2015 sdr_transceiver-0.94-742

SoapyRedPitaya d5f0113 builds and installs fine and the module is being recognized by soapysdrutil::

imac:~ rduering$ soapysdrutil --info
######################################################
## Soapy SDR -- the SDR abstraction library
######################################################

API Version: v0.4.0-g2f313f34
ABI Version: v0.4-2
Install root: /usr/local
Module found: /usr/local/lib/SoapySDR/modules/libHackRFSupport.so
Module found: /usr/local/lib/SoapySDR/modules/libRedPitaya.so
Module found: /usr/local/lib/SoapySDR/modules/librtlsdrSupport.so
Module found: /usr/local/lib/SoapySDR/modules/libsdrPlaySupport.so
Loading modules... done
Available factories...hackrf, null, redpitaya, rtlsdr, sdrplay, 

However, after starting the transceiver in the Red Pitaya browser window, running soapysdrutil --find results in "no devices found". CubicSDR device selection does not detect any devices, either.

On the other hand, sdr_transceiver_hpsdr-0.94-742 with openHDSR (v1.31 Android) runs perfectly on the same local network. Any ideas?

pavel-demin commented 8 years ago

running soapysdrutil --find results in "no devices found"

Discovery is not implemented in the Red Pityaya driver. The board's IP address should be specified in the device arguments as shown on the first screenshot: https://github.com/pothosware/SoapySDR/issues/55#issuecomment-166112878

guruofquality commented 8 years ago

Just curious, if someone had to discover the Red Pityaya on the network, is there any kind of discovery protocol server running on the Red Pityaya? Like UPnP, SSDP, zeroconf, Avahi, etc...

pavel-demin commented 8 years ago

There is a very simple discovery system.

At boot, the following script sends the board's IP address to the Red Pitaya discovery server: https://github.com/RedPitaya/RedPitaya/blob/master/OS/tools/discovery.sh

Then the board's IP address can be found by typing its MAC address in the following form: http://discovery.redpitaya.com/

Then the browser is redirected to the web server running on the Red Pitaya board. This web server is used to install and run all the Red Pitaya applications including SDR.

pavel-demin commented 8 years ago

Thanks for creating the SoapyRedPitaya repository and for explaining the difference between setup/close and activate/deactivate.

I moved the code opening and closing the sockets to activateStream/deactivateStream and it solved my problem with two .pth files. I can now activate and deactivate them without any problem.

I've just committed the latest version of the code to the new repository and removed it from my repository

pavel-demin commented 8 years ago

After a few fixes, SoapyRedPitaya now works under Windows: pothos-gui-3

guruofquality commented 8 years ago

After a few fixes, SoapyRedPitaya now works under Windows:

Cool, I added this to the windows build, it will be in the next installer

PS made a homebrew recipe as well

guruofquality commented 8 years ago

We have an issue tracker here now for this project: https://github.com/pothosware/SoapyRedPitaya/issues

Closing this now, thanks for all the good work!