Works with GR 3.6, breaks with 3.7

I have a GnuRadio C++ program that decodes and records a SmartNet
Trunked radio system. It is running great under GnuRadio 3.6.5.1, but it
doesn’t seem to be working under 3.7.6.

3.6 is installed in /usr/local and 3.7.6 was installed in my home
directory using PyBombs. My updated program compiles against 3.7 with no
problem and runs. It will pick up a few of the trunking commands, so it
is working, but the ratios is about 1 to 100 compared to 3.6. I also
tried running it in a Ubuntu VM with 3.7 installed at /usr/local and had
the same results.

I corrected for the change with XlatingFirFilter in 3.7, so it is the
opposite offset of 3.6. It looks like it could be a tuning error though,
the flow graph seems to be failing mostly at the CRC check. Did anything
else change with Blocks in 3.7? I looked at gr-osmosdr but I didn’t
notice huge discrepancies between the 3.6 and 3.7 branches.

Are there some obvious things I could be missing? I feel like this is
something small and stupid that I missing.

The diff between the two versions is here, smartness.cc is the main file
that decodes the control channel. As you can see, there is not that much
different:

https://github.com/robotastic/smartnet-recorder/compare/master...3.7-Update#diff-73510702485a7dd2f7000285cbd5e557R40
https://github.com/robotastic/smartnet-recorder/compare/master...3.7-Update#diff-73510702485a7dd2f7000285cbd5e557R40

Here is the central code block that does it. Anything obviously dumb
here?

float samples_per_second = samp_rate;
float syms_per_sec = 3600;
float gain_mu = 0.01;
float mu=0.5;
float omega_relative_limit = 0.3;
float offset = chan_freq - center_freq; // have to reverse it for 3.7
because it swapped in the switch.
float clockrec_oversample = 3;
int decim = int(samples_per_second / (syms_per_sec *
clockrec_oversample));
float sps = samples_per_second/decim/syms_per_sec;
const double pi = boost::math::constants::pi();

cout << "Control channel offset: " << offset << endl;
cout << "Decim: " << decim << endl;
cout << "Samples per symbol: " << sps << endl;

std::vector<float> lpf_taps;

init_loggers(max_loggers, center_freq, samp_rate);

gr::msg_queue::sptr queue = gr::msg_queue::make();

lpf_taps = gr::filter::firdes::low_pass(1, samp_rate, 10000, 12000);

gr::filter::freq_xlating_fir_filter_ccf::sptr prefilter =
gr::filter::freq_xlating_fir_filter_ccf::make(decim,
lpf_taps,
offset,
samp_rate);

gr::digital::fll_band_edge_cc::sptr carriertrack =
gr::digital::fll_band_edge_cc::make(sps, 0.6, 64, 0.35);

gr::analog::pll_freqdet_cf::sptr pll_demod = 

gr::analog::pll_freqdet_cf::make(2.0 / clockrec_oversample,
2pi/clockrec_oversample, -2pi/clockrec_oversample);

gr::digital::clock_recovery_mm_ff::sptr softbits =
gr::digital::clock_recovery_mm_ff::make(sps, 0.25 * gain_mu * gain_mu,
mu, gain_mu, omega_relative_limit);

gr::digital::binary_slicer_fb::sptr slicer =
gr::digital::binary_slicer_fb::make();

gr::digital::correlate_access_code_tag_bb::sptr start_correlator =
gr::digital::correlate_access_code_tag_bb::make(“10101100”,0,“smartnet_preamble”);

smartnet_deinterleave_sptr deinterleave =
smartnet_make_deinterleave();

smartnet_crc_sptr crc = smartnet_make_crc(queue);

tb->connect(src,0,prefilter,0);
tb->connect(prefilter,0,carriertrack,0);
tb->connect(carriertrack, 0, pll_demod, 0);
tb->connect(pll_demod, 0, softbits, 0);
tb->connect(softbits, 0, slicer, 0);
tb->connect(slicer, 0, start_correlator, 0);
tb->connect(start_correlator, 0, deinterleave, 0);
tb->connect(deinterleave, 0, crc, 0);

tb->start();

I just tried doing a complete PyBombs reinstall and that didn’t seem the
help. I checked and simple GRC files run fine. I can also see the signal
where I expect it to be in GQRX, so I think my tuning parameters are
correct.

Are there some other things I should try?

Sent from my iPhone

Luke,

I researched this for a bit (OK, maybe it was more like staring
blankly)… unfortunately on a windows machine w/out git. Nothing
stands
out at the momentt. I’ll give it another try tomorrow! =)

Also, I’ve never used the PLL blocks for freq demod before. Can you set
something up with a graphical sink and send some snapshots showing what
the
output of that looks like?

Also also, is the Band-Edge FLL ideal for GMSK? My possibly, incorrect
understanding of that block is that it was more ideal for PAM with
common
RRC.

-John

John,

I use the BE FLL for auto-doppler correction in the rare case where I am
not actively correcting for doppler. But, the correction is really
slow. I’m probably not using it correctly, but it works OK in that rare
case when it’s all I’ve got.

Very Respectfully,

Dan CaJacob

On Fri, Oct 17, 2014 at 2:28 AM, John M.
<[email protected]

On 10/17/2014 08:28 AM, John M. wrote:

Also also, is the Band-Edge FLL ideal for GMSK? My possibly, incorrect
understanding of that block is that it was more ideal for PAM with
common RRC.

For the record: It might work coincidentally because of the rolloff-y
shape of GMSK, but it’s derived for and designed for common PAM/RRC, as
John says and I wouldn’t recommend it for anything else.
To look up the math, I suggest Harris’ works.

Cheers,
M

Thanks for looking into it! To be honest, I am not really good at RF. I
based my code off the python code in gr-smartnet. The fsk-demod python
file
is here:

It is quite possible that it just happened to work because of an error
that
got patched in Gr 3.7.

Are there some good examples for GMSK/FSK demodulation that I could
borrow
from instead?

Recreating this in GRC sounds like a great idea so I can scope along the
way. I will give that a try next.

Thanks again for the pointers, fresh eyes are really helpful when you
have
been staring at it for so long.

  • Luke

On Fri, Oct 17, 2014 at 8:18 AM, Martin B. [email protected]

Also, my understanding for the PLL blocks were that they were ideal for
“strong carrier” signals like AM. When I say strong carrier i mean a
signal that has an obvious carrier which isn’t “hidden” under
modulation…

Anyway, the GMSK block might be a good place to start.

-John

On Fri, Oct 17, 2014 at 7:35 AM, John M.
<[email protected]

It doesn’t have frequency correction - I can probably follow up with
some
ideas on how to implement that part. But the GMSK demod might do OK for
you initially. It doesn’t do anything intelligent to deal with the data
shaping - its just a non-coherent slicer.

If you want to design in GRC but keep your top-level application as is,
you
can use a hier block. You can also use a command line parameter or
other
mechanism to select your demodulator at start-time for easy comparisons.

[typed one handed… my daughter has my other and]

-John

It actually looks like the control channel for Motorola SmartNet is FSK:
"On
the control (data) channel the base station transmits 84 bits frames at
3600 bit/s with direct frequency modulation of the carrier using
Frequency
Shift Keying (FSK). "

I will at least see if I can get something that looks right out the
other
side. Would it be best to use one of the GFSK examples in gr-digital?

On Fri, Oct 17, 2014 at 10:37 AM, John M. <

On Fri, 2014-10-17 at 12:00 -0400, [email protected]
wrote:

Also, my understanding for the PLL blocks were that they were ideal for
“strong carrier” signals like AM. When I say strong carrier i mean a
signal that has an obvious carrier which isn’t “hidden” under modulation…

John and Luke,

Yup. GMSK doesn’t have any narrow and strong spectral feature on which
one can lock a PLL. (And the band-edge FLL is the wrong thing to use
too.)

You can however get a spectral feature from the square of the GMSK
signal. Assuming you have an approximately random bit stream,
squaring the GMSK signal gives you spectral peaks at f_c +/- f_b/2,
where f_c is the center frequency and f_b is your bit rate. See the
attached “GMSK_squared_spectrum.png” which shows the spectra from a
random bit stream.

So you can get a non-data-aided coarse frequency correction doing
essentially what older versions of gr-ais did. See the attached
“square_and_fft_freq_sync.grc.png”. The gr-ais “freqest” block is the
only non-stock gnuradio block and it just walks the FFT looking for the
spectral peaks at +/- f_b/2 and outputs a frequency correction values
based on how many FFT bins the peaks are offset from the expected center
frequency.

The major tradeoff is the length of the FFT:

  1. More FFT points gives you finer resolution bins and a finer
    correction.
  2. More FFT points protects against pathological data sequences (e.g. a
    long run of 0’s) that give different spectral peaks which screw up the
    correction.
  3. Fewer FFT points ensures the start and end of bursts get the proper
    correction as the correction reacts faster to the transition from
    dead-air to modulated signal.
  4. Fewer FFT points ensures faster reaction to changes in frequency
    offset.

Although, if you have a known preamble to inspect, data-aided carrier
frequency offset correction is way better than the above non-data-aided
stuff.

Regards,
Andy

Figured I’d chime in since I wrote the code in question. The band edge
FLL
is probably the wrong thing to use, but it did work surprisingly well
for
my local setup (at very high SNR), so I left it in. The square-and-FFT
block works great for MSK, but Smartnet isn’t MSK, it’s FSK, and its
lack
of phase coherence (and variable deviation) mean you won’t see those
nice
1/2-bitrate FFT spikes.

As Andy points out, the “right” answer is to correlate against the
modulated preamble and develop phase, frequency, and timing estimates
from
the known preamble.

–n

Thanks! I clearly have a lot of RF theory to read up on.

The Band Edge FLL works great for me too, on 3.6. Does anyone know if
there were changes to it or surrounding blocks in 3.7 that would make it
stop working?

I have a pretty strong, clean signal.

Sent from my iPhone

The good news is. the GFSK block doesn’t do anything specific to
Gaussian
FSK. So I guess tha tall works out =)

You’re outputs might be more illustrative if you rebuild it in from the
blocks actually inside the GFSK demod block:

quad demod > clock recovery -> slicer

Tom changed it to use the fir_filter_with_buffer vs. the standard
fir_filter internally, but as the taps remain the same I’d imagine it to
be
more or less numerically identical.

First step I think is to verify that the FLL is actually the problem –
get
a scope on the output of the FLL and see that your FSK signal is more or
less at baseband.

–n

On Sat, 2014-10-18 at 08:00 -0700, Nick F. wrote:

Figured I’d chime in since I wrote the code in question. The band edge
FLL is probably the wrong thing to use, but it did work surprisingly
well for my local setup (at very high SNR), so I left it in. The
square-and-FFT block works great for MSK, but Smartnet isn’t MSK, it’s
FSK,

Oops, I thought the thread was about GMSK. I guess I didn’t read far
enough back. :stuck_out_tongue:

Thanks Nick.

-Andy

On 10/18/2014 05:57 PM, Luke B. wrote:

The Band Edge FLL works great for me too, on 3.6. Does anyone know if
there were changes to it or surrounding blocks in 3.7 that would make it
stop working?

None of the DSP was changed, if it worked before it should™ still
work. The reason we say it’s a bad choice is that it was derived for
PSK/PAM signals. The reason it still might work is that the
implementation runs 2 filters at the band-edges and compares the energy
content of those, and that difference might be sufficient to correct
your frequency offset if you have sufficient averaging (i.e. low enough
loop bandwidth).

M


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

Thanks - Most bizarre. That probably means it is somewhere in my code. I
am still trying to rebuild the demodulator just in case it helps. I have
been following this guide:
http://www.inguardians.com/pubs/GRC_signal_analysis_InGuardians_v1.pdf
http://www.inguardians.com/pubs/GRC_signal_analysis_InGuardians_v1.pdf

I have attached a screenshot of the graph I am using and what the output
looks like in Baudline. Does the output look about right? I was having
trouble finding the FSK Deviation for the Quad Demod for Moto SmartNet.
Does 4500Hz seem about right?

On the off chance that someone has some free time to look into this, I
have built the Smartnet trunk control channel in GRC. I have also made a
capture of the signal. Everything is working the way it does on my C++
program. It is able find a lot of frames where the preamble matches, but
barely any of them bas the CRC test. The expected behavior is that there
would be 2-3 frames that pass the CRC test every second, and that is how
it works under 3.6.5.

The SmartNet stuff is rolled into 3.7 blocks. Git clone, cmake . , make,
sudo make install

If anyone sees some obvious mistakes let me know. I know this not the
ideal way to decode an FSK signal, but it works perfectly in 3.6.

Thanks for any pointers people have!

Capture of the signal:
WeTransfer - Send Large Files & Share Photos Online - Up to 2GB Free http://we.tl/ZMD8R5uQfR

GRC Blocks for Smartnet

https://github.com/robotastic/gr-smartnet

GRC to decode Smartnet Tunking channel

On Mon, 2014-11-03 at 12:01 -0500, [email protected]
wrote:

The SmartNet stuff is rolled into 3.7 blocks. Git clone, cmake . ,
make, sudo make install

If anyone sees some obvious mistakes let me know. I know this not the
ideal way to decode an FSK signal, but it works perfectly in 3.6.

Hi Luke,

I have not built the SmartNet blocks yet, but:

Your low pass filter looks way too wide and you’ll get aliases when you
decimate by 185. 2 Msps / 185 = 10.81 ksps, so the Nyquist frequency is
5.405 kHz. I winged this is as a low pass filter and things looked
better:

firdes.low_pass_2(1, samp_rate, 4500, 1000, 60, firdes.WIN_HANN, 6.76)

The 60 dB down may be overkill, you can make it smaller for a filter
with less delay.

I found an offset slider value of -15k made things look about centered
manually.

You might want to put a waterfall sink before and after the FLL
Band-Edge filter to observe how it is making the spectrum wobble around
a little. If you change your offset slider, you can see the FLL
band-edge filter centering things back up; so that looks like it is
working.

Regards,
Andy