Working on native AirSpy support for dump1090-fa

Yeah that’s what I’m doing, well on the IQ format now. Last night I was trying to figure out a converter to take the real format and get it into a format the demod expects. One thing though… If we use the real format instead of IQ, I think we lose the mean power calculation. The mean level we get just from the magnitude but mean power we currently get from the sum of the squares of I and Q.

One other thing with the IQ format. If we get that from libairspy, it’s already had the dc block applied. Not sure if that’s good or bad.

EDIT: I’m really downsampling, not decimating since I haven’t got the low pass filter yet.

Any hardware clock that’s not a division by power of 2 involves some kind of VCO and various dividers in the loop. They are not at all as phase precise as a software resampled.

I’d really try to go for 12 MSPS real a the 12 MSPS IQ isn’t possible on the airspy mini and it’s not stable for everyone using a RPi even with the R2.

I’m not sure i follow.

    for (i = 0; i < nsamples; ++i) {
        I = (int16_t) le16toh(*in++);
        Q = (int16_t) le16toh(*in++);
        fI = I / 2048.0f;
        fQ = Q / 2048.0f;

        magsq = fI * fI + fQ * fQ;                                                                                                     
        if (magsq > 1)
            magsq = 1;

        float mag = sqrtf(magsq);
        sum_power += magsq;
        sum_level += mag;
        *mag_data++ = (uint16_t) (mag * 65535.0f + 0.5f);
    }   

Looks to me I and Q aren’t treated any different, so it’s symmetric?
Have you tried just taking 2 real samples and sticking them in there as I and Q?

So you get 12 bit real samples at 12 MHz, throw away 3 of 5 samples.
The remaining 2 whichever you choose you can stick into the 16 bit converter after shifting left by 4.

Don’t want to pretend i understand the intricacies of the IQ data stuff, but that’s what i’d try.

Really you’d want your own converter function as you already have magnitude data?

I think the issue would be that Q has to be phase shifted 90 degrees from I or “bad things will happen”. I’ll try it though. I also need to verify that the 12 bit sample is simply stuffed into 16 bits with its sign bit in tact or whether the 12 bit sample is converted to a 16 bit int. We can also get 16 bit real unsigned int and 32 bit real float so those are possibilities as well although the float format results in double data rate of course.

To reiterate what I said early on in the thread.

dump1090 cares about the strength of the carrier, that’s all. To get that from a RF signal you need an envelope detector of some sort. The current implementation does that simply by looking at the magnitude of the I/Q signal. This works because complex signals are phasors; a constant amplitude constant frequency signal looks like a vector of constant length rotating around the origin.

That approach doesn’t work with a real signal. A constant-amplitude constant-frequency signal is a sinusoid. You need to use other techniques to turn that into a constant magnitude. One way is just a low-pass filter.

1 Like

A low pass filter with what cutoff?

Nevermind. I think I’ve got it.

I’d guess 12MSPS real → take absolute value → LPF with 1.2MHz cutoff → use every 5th sample would work OK. And tune the LO so that 1090MHz appears at an IF well above 1.2MHz.

(sorry, missed the “take absolute value” part earlier)

Strictly for level detection, cutoff like 10-100 Hz? You only need something faster than the ALC time constant.
For the signal demodulation, that’s a different thing, like @obj obj said above.
I would not decimate by throwing samples away, but rather integrate them, and get that average value.

Yep, the converter is really simple, convert to absolute value and accumulate it for the out_mean_level.

I’m working on real decimation instead of just downsampling by taking 1 in 5.

1 Like

@prog I just bought another R2 so I’d hope this would entitle me to a few minutes of your time for a direct question and answer that would save me a lot of time…

airspy_nos_conf and airspy_mini_conf show the sample_rate to IF frequency relationship as simply IF = sample_rate / 2. I see configs for 12 ms/s and below but not for 20 and 24. Can I assume they are 10MHz and 12MHz respectively? If not, what are they?

Progress report:
Using the INT16_REAL format at 12 ms/s and just simple math to downsample.
dump1090-fa w/ native airspy support: about 10% cpu

Tot:  73 Vis:  73 RSSI: Max  -8.2+ Mean -22.7 Min -31.6-  MaxD:  206.6nm+     /
Hex    Mode  Sqwk  Flight   Alt    Spd  Hdg  Dist(nm) Bearing  RSSI  Msgs  Ti

airspy_adsb: about 16% cpu

Tot:  90 Vis:  90 RSSI: Max   0.0+ Mean  -4.5 Min -15.4-  MaxD:  206.8nm+     -
Hex    Mode  Sqwk  Flight   Alt    Spd  Hdg  Dist(nm) Bearing  RSSI  Msgs  Ti

Still much more work to do.

What entitles you to ask questions directly is courtesy. It has nothing to do with your purchase. But thank you for getting an Airspy!

Without digging into unnecessary details, I will assume you want to tune the device properly so that the decimated bandwidth is centered around 1090 MHz.
The frequency to set using the API is:

Frequency = 1090000000 + Fadc * (0.25 - 1.0 / (4 * decimation_ratio))

Where Fadc is the real sample rate and decimation_ratio is 5, in your case.

Note however that the spectrum bandwidth will hit the edge of the IF filter which is 0.5 MHz. This means you will lose 0.5 MHz of useful spectrum.

2 Likes

Actually, I just wanted the IF frequency that gets set when using 20 or 25 ms/s rates.

The IF frequency is always Fs / 4, but this is of very little interest for what you are doing.
If you don’t want to dig into spectral inversion, polyphase filtering, aliasing, nyquist zones, etc. use the formula I posted and 1090MHz will be centered at the decimated IF.

2 Likes

It would be useful to document this relationship between the frequency that you pass to libairspy and the frequency that the LO is set to, since this is critical information to have if you want to deal with real samples.

The only guaranteed information is that the center frequency of the baseband signal, be it IQ or Real, corresponds to the frequency set using the API. All the rest can change (and has changed in the past) with hardware, firmware and library revisions. This is a common knowledge/practice/characteristic with all SDRs.

For example, we could change the tuner chip with a different architecture which will impact the entire processing chain, then the above above formula will no longer be valid. If this happens, we will supply a new library that is backward compatible with all the existing hardware and software but adds support for the new architecture. I can guarantee this will happen at some point and any other assumptions may not work.

Now that said, maybe a “spectrum polarity” API should be added to avoid any speculation about how this or that thing is implemented. The Real stream gives an inverted spectrum, but the complex analytic signal does not. The “Why” and “How” is a long story and is not subject to debate at this point.

The recommendation is to use the API which abstracts the hardware and gives a consistent behavior for all the hardware and firmware revisions. This worked well so far since the first release in 2014.

2 Likes

For real signals, isn’t that equivalent to guaranteeing that the LO is at either (tuned + Fs/4) or (tuned - Fs/4)?

edit: that is, there are two possible mappings:

  1. inverted spectrum
    baseband 0 = RF (set frequency + Fs/4)
    baseband Fs/4 = RF (set frequency)
    baseband Fs/2 = RF (set frequency - Fs/4)

  2. uninverted spectrum
    baseband 0 = RF (set frequency - Fs/4)
    baseband Fs/4 = RF (set frequency)
    baseband Fs/2 = RF (set frequency + Fs/4)

For simple AM modulation that’s at the tuned frequency (as in the dump1090 case) it doesn’t matter, but you need to know which case it is for anything that has a frequency dependency away from the tuned frequency (FSK, multiple channels, etc)

I’m unclear here - which API do you mean? Are you saying “only use the complex formats, don’t use the real formats”?

Was thinking about this last night… can we get the info by dumping the r820t or the si5351 registers? It’s still hardware dependent but there are libairspy APIs for getting the registers of both devices.

Ouch. Just tune to 1090MHz and use prog’s guarantee above - with real sampling the tuned frequency (i.e. 1090MHz carrier) will always be at Fs/4

“Ouch” is right. :slight_smile: There’s no advantage that I can see for using IQ format anyway. Same for float. With INT16 we can avoid floating point math as much as possible and convert it to float only when/if necessary.