xmikos / soapy_power

Obtain power spectrum from SoapySDR devices (RTL-SDR, Airspy, SDRplay, HackRF, bladeRF, USRP, LimeSDR, etc.)
MIT License
169 stars 36 forks source link

Include recording settings in binary format #10

Open alexnask opened 6 years ago

alexnask commented 6 years ago

A new magic string, b'SDRFFX' is used to specify that we are using the new format.
All arguments passed to the SoapyDevice are captured, as well as the arguments to SoapyPower.sweep()

A device info string from detect_devices is also recorded (which includes all available information, like the label, the serial and the driver of the device).

Test recording:
image

Test read script:

import soapypower.writer

formatter = soapypower.writer.SoapyPowerBinFormat()

with open('output', 'rb') as f:
    header, _, args, device_info = formatter.read(f)

    print("DEVICE INFO:", device_info)
    print("DEVICE HEADER:", args['device'])
    print("SWEEP HEADER:", args['sweep'])

    print("REGULAR HEADER:", header)

Output:
image

Closes #6.

xloem commented 6 years ago

alexnask, thanks so much for this work!

@xmikos, are you around to merge this PR?

alexnask, if there’s no reply from xmikos, ping me and I’ll close the issue

xmikos commented 6 years ago

Hello, I am still around, but I had no time to work on my SDR projects :-( I will try to look at it and merge it today or tomorrow evening.

alexnask commented 6 years ago

@xmikos
Hi, thanks for your time :)

The only part I'm a bit unsure about is

device_info = simplesoapy.detect_devices(self._args['device']['soapy_args'], True)[0]

The assumption is that SoapySDR opens the first device that matches the soapy_args and that the order is the same as the detect_devices function, it seems to work out well with some testing.

Apart from that, the rest of the code is just reading and writing the arguments passed to the SoapyDevice and to the sweep function, it is pretty trivial (the only slight complications are strings, where length + data is written and the time_limit option which can be None).

alexnask commented 6 years ago

@xloem
Hi, I would really appreciate if you could close the issue if you are satisfied with this solution.
I will be working on any improvements on this pull request if xmikos deems they are necessary, so that it can be merged in master.

xloem commented 6 years ago

thanks alexnask; I'll close.

I've started using your work already, although I haven't tried reading the data back for processing yet. My only concern is I noticed the header information is output with every single data packet. This might be overkill. What do you think?

alexnask commented 6 years ago

@xloem
Yes, this is true.
I could make it a file header instead of a header for every measurement run, I just wrote it that way to match the old binary format, it seems that each packet is independent by design.

alexnask commented 6 years ago

@xloem @xmikos
Updated the code to write/read the recording settings once, in the beginning of the file.
Here is a test reading script:

import soapypower.writer

formatter = soapypower.writer.SoapyPowerBinFormat()

with open('output', 'rb') as f:
    args, device_info = formatter.read_header(f)
    print("DEVICE INFO:", device_info)
    print("DEVICE HEADER:", args['device'])
    print("SWEEP HEADER:", args['sweep'])

    i = 1
    tup = formatter.read(f)
    while tup is not None:
        tup = formatter.read(f)
        i += 1

    print("READ {} MEASUREMENTS".format(i))

If you need any help converting your measurements from the previous format to this one, I could write a script to do so.

xloem commented 6 years ago

I've been using this patch locally for a while and it seems to work very well!

If it were to be made perfect, I came up with the following possible concerns:

I was thinking, to resolve some of the above, it might be simpler to record simply the commandline arguments as an array of strings, and the resulting device information. I'm not sure, though.

alexnask commented 6 years ago

@xloem
Those are some good points.
I will look into them and get back to you.

I don't think passing the command line arguments as an array of string is the best solution but as you say any other solution entails code duplication (forwarding all arguments/settings to the file writer).
I chose to record the arguments the way I did so that a recording environment can be recreated by building a SoapySDR device and calling the sweep function.