I am working on a processing multiple signals using a single source
block.
The background is below, but I had a couple of high level questions:
What is the best approach performance wise for selecting multiple
~15khz
channels from a 2mhz+ source block? Is it using a Xlating FIR Filter
with a
low-pass? Is it more efficient to use a SIN Sig source & Multiply Block
with a low-pass FIR Filter? Is there a better way to extract a filter?
What is the best way to have different bunch of blocks processing
each
signal run independently and not block each other? I want to do this as
a
GR C++ program is there any way to run the signal source and chanelizers
as
one thread and then have the different processing chains run as separate
threads? Is there a way to put a queue or buffer inbetween blocks that
would allow for a chain of blocks to be separated between threads?
Or am I better off doing the basic signal/channel processing for
everything
in a single process and then writing the results to a file and then
having a process which goes through the files and does the more
intensive
vocoder work in non-real time?
Any pointers or examples of how to do threading with GR C++ code would
be
really helpful. I am not sure of the best architectual approach.
Background:
I have taken the gr-smartnet code and done a skeleton implementation in
C++. I want to process the digital trunking channel and then decode and
record the digital audio from all of the different talk groups. Since it
is
trunked, channels will be randomly be turning on and off and talk groups
will be switching from channels. It would be good to have a separate
thread
for the trunk decoding and the separate digital audio recorders.
Ideally, I
would like to be able to do this over 8 or 10Mhz using my HackRF.
My code, which is working enough to decode the trunking channel, is
here:
I’ve found using the FFT blocks are the most cpu efficient way to
extract a
channel from the whole 20MHz of the HackRF. Have a look at my latest
Scanoo release built in GRC which uses the ‘Keep X in N’ block to select
the channel required. There’s also a spectrum sense mode which locks on
to
the strongest signal within the 20MHz bandwidth if it is not in the
blocked
frequency list:
It uses the gr-osmosdr GRC block and the Funcube Dongle Pro+ is second
in
the list of compatible devices so yes it will work:
However, In order to work using the 192KHz bandwidth of the Funcube Pro+
you will need to fiddle with the sample rates and make sure that they
are
something like the following:
samp_rate = 192e3
channel_samp_rate = (quad_samp_rate * 1)
quad_samp_rate = (audio_samp_rate * 1)
audio_samp_rate = (48e3)
I’ll update Scanoo to have an option in the GUI for the
‘channel_samp_rate’
and ‘quad_samp_rate’ multipliers for easy Funcube use and better
flexibility. Thanks for asking the question!
FYI, the Xlating FIR filter uses a rotating complex unit vector (with
periodic renormalization) to accomplish the frequency shift, so this is
much more computationally efficient than the signal source block.
Also, it may be an option to use the polyphase channelizer block.
What is the best approach performance wise for selecting multiple ~15khz
channels from a 2mhz+ source block? Is it using a Xlating FIR Filter with a
low-pass? Is it more efficient to use a SIN Sig source & Multiply Block with a
low-pass FIR Filter? Is there a better way to extract a filter?
Xlating FIRs just generate the sin internally and apply it themselves;
they are mathematically equivalent to shifting your signal and filtering
it afterwards.
You can, of course, use bandpasses, if you’re after a specific sprectral
shape. Try the gr_filter_design toolbox, it’s even neater than doing
your calculations in Matlab (or scipy).
However, as Mike already pointed out, depending on your signal and
potential interferers of course, selection by trunkated fft is faster
and as intuitive.
What is the best way to have different bunch of blocks processing each signal
run independently and not block each other? I want to do this as a GR C++ program
is there any way to run the signal source and chanelizers as one thread and then
have the different processing chains run as separate threads? Is there a way to
put a queue or buffer inbetween blocks that would allow for a chain of blocks to
be separated between threads?
I’m not quite sure I understand your question correctly. GNU Radio has
built-in concurrency for blocks.
Tom R. has a blog entry on core affinity, see http://gnuradio.squarespace.com/home/2013/2/7/block-core-affinity.html .
Or am I better off doing the basic signal/channel processing for everything in a
single process and then writing the results to a file and then having a process
which goes through the files and does the more intensive vocoder work in non-real
time?
Ok, this is another issue: If you think your computation is too heavy
for your platform, then splitting it into an online and offline part
might make sense. If you really want to find out what eats your cpu, try
the helpful performance counters http://gnuradio.org/redmine/projects/gnuradio/wiki/performancecounters .
Since decoding voice is usually a process that has to happen only for
one channel at a time, you might as well just save the input samples for
later offline decoding, extract only one channel at a time online and
decode that one for playback.
Although that might be wasteful on storage capacities (2Msam/s with
2*4B/sam=16MB/s), but it gives you the power to do the most amazing and
computationally intensive filtering/equalizing/fec/… on your samples
when you’re not doing it in real time anyways.
Another well-tested trick: Network sinks/sources. Just use your rx
machine to do the trunking, and if it has enough power left, select the
right frequencies of each talk group by filter/fft, and send streams of
samples for each group via network to your decoder machine(s).
Any pointers or examples of how to do threading with GR C++ code would be really
helpful. I am not sure of the best architectual approach.
Well, you can “multi-thread” your own block’s work function, but I’d
advise you not to do that unless you really know what your scheduler
will do to you. Simply rely on GNU Radio to fully use up your available
CPU power to schedule several blocks at once; you have enough of them.
Background:
I have taken the gr-smartnet code and done a skeleton implementation in C++. I
want to process the digital trunking channel and then decode and record the
digital audio from all of the different talk groups. Since it is trunked, channels
will be randomly be turning on and off and talk groups will be switching from
channels. It would be good to have a separate thread for the trunk decoding and
the separate digital audio recorders. Ideally, I would like to be able to do this
over 8 or 10Mhz using my HackRF.
My code, which is working enough to decode the trunking channel, is here: GitHub - robotastic/sdr: My exerpiments with SDR
Awesome project!
Xlating FIRs just generate the sin internally and apply it themselves; they are
mathematically equivalent to shifting your signal and filtering it afterwards.
You can, of course, use bandpasses, if you’re after a specific sprectral shape.
Try the gr_filter_design toolbox, it’s even neater than doing your calculations in
Matlab (or scipy).
However, as Mike already pointed out, depending on your signal and potential
interferers of course, selection by trunkated fft is faster and as intuitive.
Awesome - I will stick with Xlating FIRs then. I will have to get
smarter on how to use the FFT to do the frequency shifting. I checked
out Mike’s app, but I don’t have 3.7 installed yet so I couldn’t play
around with it.
I’m not quite sure I understand your question correctly. GNU Radio has built-in
concurrency for blocks.
Tom R. has a blog entry on core affinity,
seehttp://gnuradio.squarespace.com/home/2013/2/7/block-core-affinity.html .
I will give the block core affinity a try. I think what maybe happening
is that 2 process heavy blocks are being scheduled for the same core. I
have a 4 core machine and it is only hitting ~60% CPU utilization, but
it stops/slows decoding the trunking stream while it is doing vocoder
work. It doesn’t seem to have a problem doing NBFM Demod and recording,
so I think the additional processing requirements of decoding digital
audio is the problem. The Performance Counters seem like a great
approach. It should give me a better idea where all the cycles are
going. The network source/sink approach also sounds like a good one. And
I have a spare laptop…
Awesome project!
Thanks! I am having way too much fun with a $20 dongle. GNURadio is
awesome.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.