Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

airspy support #8

Closed
wants to merge 13 commits into from
Closed

airspy support #8

wants to merge 13 commits into from

Conversation

labomb
Copy link

@labomb labomb commented Feb 19, 2017

The multi-device handling framework in the dev branch is VERY nice. It was quite a straight-forward task to slot in support for the Airspy device, and should be just easy for most any other device out there.

One thing that might be useful is the ability to configure/track unique buffer sizes (rtl/mag) by device as well (for example, the Airspy has a fixed 64k sample buffer size)... but it works quite well as is.

While it works well enough, the current Airspy approach isn't exactly ideal... it really could benefit from some demodulation code that is specific to the Airspy sample rates/format instead of resampling on each callback.

sdr_airspy.c Outdated
pthread_mutex_lock(&Modes.data_mutex);
if (Modes.exit) {
airspy_stop_rx(AIRSPY.dev);
return 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to unlock the mutex in this path

sdr_airspy.c Outdated
if (!isdigit(s[0])) // we expect at least one number
return false;

if( strlen(s) > 2 ) { // check for hexadecimal

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strtoull will do this for you if you pass base == 0

sdr_airspy.c Outdated
if (s[0] == '-') // likely forgot a parameter
return false;

if (!isdigit(s[0])) // we expect at least one number

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strtoull will return s_end == s if there are no digits, so this is already handled below

sdr_airspy.c Outdated

u64_val = strtoull(s, &s_end, base);
if( (s != s_end) && (*s_end == 0) ) {
switch(utype) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These need a range check

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you mean range check for valid values per the Airspy API, airspyOpen will handle invalid range options. If you mean something else, I would appreciate additional detail.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean if the user gives you a value 257 for a uint8_t type then you will stuff 257 into 8 bits and get a result of 1 and not notice that it's out of range. You should check that the unsigned long long value is not too large for the target type.

}

bool airspyOpen(void) {
#define AIRSPY_STATUS(status, message) \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want an error-exit label that does teardown rather than just returning; there is a bunch of other teardown that might be needed depending on how far you get (freeing the soxr stuff and your buffers etc)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to carry that over from the test clone, thanks for catching it.

sdr_airspy.c Outdated
free_bufs = (Modes.first_filled_buffer - next_free_buffer + MODES_MAG_BUFFERS) % MODES_MAG_BUFFERS;

// Give the demodulater what it expects
soxr_process(AIRSPY.resampler, inptr, i_len, &i_done, outptr, MODES_RTL_BUF_SIZE, &o_done);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you do the resampling after you've released the mutex?

Copy link
Author

@labomb labomb Feb 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can, if it's okay to release the mutex before the 'FIFO is full' if statement. slen is needed there, and it's derived from o_done, which is only known after resampling. I wasn't sure, but happy to move the release up (and remove it from the 'FIFO is full' block) if it causes no issue from your perspective.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's safe; but you know the resampling ratio so you should know how many samples the resampler should produce given an input size.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Releasing the mutex before resampling doesn't appear to have any negative affects based on limited testing.

Regarding sample counts produced by the resampler, there are 3 different results. I did a quick 1 minute run using the Airspy Mini at it's max sample rate of 6Mhz:

resulting sample count of 26112: 4710 times in the 1 minute period
resulting sample count of 26764: 175 times in the 1 minute period
resulting sample count of 26765: 701 time in the 1 minutes period

sdr_airspy.c Outdated

// The resampler often produces an odd sample count, no real value in tracking how often
if (o_done & 1)
o_done -= 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably going to hose mlat timing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admittedly haven't tested mlat, but I assume you mean because of the numerous dropped samples. I determined while debugging that the Airspy gives a consistent sample count at each callback, but the resampler was either x or x+1 (don't recall the exact number). Not sure why.

I wish I had the knowledge to come up with an appropriate demod and lose the resampler, but I do not.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resampler will be giving you +/- 1 sample because the downsampling ratio is not an integer. IIRC the Airspy will be giving you samples at 20MHz and you're resampling to 2.4, so that's resampling by a factor of 3/25. For every 25 samples you give the resampler, you get 3 back. If you give it say 65536 samples it gives you back 7864 samples, or 7865 about every 3rd block, because the exact number of samples after resampling would be 7864.32.

That said.. the soxr_process docs say that i_len / i_done / o_len / o_done are all "samples per channel" and you have two channels configured here (I and Q) so I don't understand why you need to divide by 2 in the first place.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the explanation.

Re. dividing slen, in at least one prior iteration I needed to, but you are correct in that there is no need here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some more detailed testing on a new RPi3 test box I've been able to confirm that, as you correctly surmised, mlat is indeed hosed with the current approach. The mlat tracked aircraft are listed, but they are not highlighted as mlat and of course are not plotted on the map. The log indicates it's not synchronized with any nearby receivers. It's unfortunate, as I was otherwise a bit surprised with the overall performance considering the additional resampling overhead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, no surprise... the airspy is dropping a load of samples.

What is a bit of a surprise to me is that I ran a quick test that didn't run the resampler and instead just passed the buffer along just to see what effect it would have on utilization (obviously aware nothing would be decoded). I thought that the resampler was the primary utilization issue, but to the thread was still hammered at 100%. No doubt easy to explain, your insight would be appreciated.

And now a new problem... faup1090 is failing to connect to 30005. It's repeatedly trying to start with '/usr/lib/piaware/helpers/faup1090 --net-bo-ipaddr {} --net-bo-port 30005 --stdout --lat...' and failing with ' failed to connect to :30005 (is dump1090 running?): can't resolve : Name or service not known'. dump1090-fa is indeed running. mlat-client is also giving ' Connection to :30005 failed: [Errno -2] Name or service not known'. The /etc/default/dump1090-fa file looks fine.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you will have to do some profiling there, it's probably in libairspy I'd guess if you're not doing anything much in the callback.

The piaware/faup1090 errors sound like a configuration problem, what's your piaware config?

Copy link
Author

@labomb labomb Feb 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Built/installed using piaware_builder on the Pi (jessie lite), and the same for dump1090-fa using the dev-airspy branch. It's been running fine until yesterday, when I decided to try airspy_adsb. It worked as far as feeding dump1090 on port 30104, but gave the same errors in the log with faup and mlat-client. I did modify dump1090-fa to use device-type none, and tried various combinations of using/removing the net-bo-port 30005 switch in attempt to get mlat working with airspy-adsb... but no joy. Having had my fill of that, I tried to switch back today and the faup/mlat-client errors remain.

It may be messy, but here is the current contents of dump1090-fa:

RECEIVER_OPTIONS="--device-type airspy --linearity-gain 21 --enable-bit-packing --enable-airspy-biast --stats --net-bo-port 30005"
NET_OPTIONS="--net --net-heartbeat 60 --net-ro-size 1000 --net-ro-interval 1 --net-ri-port 0 --net-ro-port 30002 --net-sbs-port 30003 --net-bi-port 30004,30104 --
net-bo-port 30005"
JSON_OPTIONS="--json-location-accuracy 1"

Don't think I modified anything else, but can't be absolutely sure. If the --net-bo-ipadddr supposed to be empty in the faup command line? I noticed that switch isn't available in the dev branch with dump1090.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I mean it is a piaware configuration problem, it thinks the receiver hostname is an empty string. What is your piaware config? (Output of "piaware-config")

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah...as soon as I posted I figured as much :). And with that, I apparently changed the receiver type to 'other' while testing the airspy adsb tool! Sigh... it's back humming along. I previously never did anything with piaware-config on this box (I did on my 'production' piaware box of course)... so forgot about it.

I'll see if I can pin-point the utilization issue.

sdr_airspy.c Outdated
switch(utype) {
case 8:
{
if (u64_val > UCHAR_MAX)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want UINT8_MAX, UINT16_MAX etc here

sdr_airspy.c Outdated
airspy_start_rx(AIRSPY.dev, airspyCallback, NULL);

while ((airspy_is_streaming(AIRSPY.dev) == AIRSPY_TRUE) && (!Modes.exit)) {
usleep(500);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is close to a busy-wait; can you raise the sleep to something a bit more reasonable like 1 second?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already did, but to be safe, just tried it again. No difference in CPU usage... still 100%.

return;
}

start_cpu_timing(&airspy_thread_cpu);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unlikely to work as expected because the airspy callbacks are happening in a different thread, not the thread calling airspyRun()

@mutability
Copy link

This never quite made it over the line. reopen if needed

@mutability mutability closed this Mar 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants