<div dir="ltr">If you have not done so I strongly urge you to install 64 bit Raspbian, Ubuntu 20.04 LTS 64 bit version, etc. It makes a difference.<div><br></div><div>Bob</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Oct 25, 2020 at 7:02 PM Phil Karn via Ground-Station <ground-station@lists.openresearch.institute> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This may be of interest to those working on multi-channel voice<br>
bandwidth satellite uplinks.<br>
<br>
I've been working on my own multichannel SDR for some time. I've got it<br>
demodulating all 216 FM channels in the TASMA 2m (soCal spectrum<br>
coordinator) bandplan and multicasting the demodulated PCM and Opus<br>
compressed audio on my home LAN.<br>
<br>
The front end hardware is an Airspy R2 providing 20 Ms/s. The samples<br>
are real, so it covers a 10 MHz bandwidth minus some for anti-alias<br>
filtering. The R2 is connected to a Pi4 that multicasts the raw samples<br>
on my home Ethernet at 250 Mb/s, where they're picked up by an 8-core<br>
3.4 GHz i7 running Linux and the bulk of the SDR code.<br>
<br>
I can plug the R2 directly into the i7 but I wanted to stress-test the<br>
network and see what the Pi can do. Unless something major happens, I'll<br>
see *no* sample drops between the Pi4 and the SDR program on the i7. I<br>
tried connecting a second Airspy R2 on the same Pi4, but it only has a<br>
single USB 2.0 bus and that was asking too much.<br>
<br>
My SDR makes extensive use of the overlap-save method of fast<br>
convolution for filtering. One of the really neat properties of<br>
overlap-save is that you can have an arbitrary number of independent<br>
filters all sharing a single forward FFT. The incoming sample stream is<br>
converted to the frequency domain, and then each demodulator thread<br>
picks just the frequency domain bins it wants. (The usable bin size is<br>
controlled by the FFT block rate, which is currently 100 Hz.) The<br>
forward FFT is shared by all demodulator threads. Each demodulator needs<br>
its own inverse FFT to convert back to the time domain, but they run at<br>
a much lower sample rate (48 kHz at present). The output sample rate is<br>
controlled by the number of FFT bins chosen, so you can easily decimate<br>
to any multiple of the block rate, i.e., any output sample rate that's a<br>
multiple of 100 Hz.<br>
<br>
The SDR is highly threaded so it takes good advantage of multi-core<br>
CPUs. One thread runs the 400 k point forward FFT (10 ms block rate (100<br>
frames/sec) with a 2:1 overlap for the fast convolutions. This takes<br>
about 38% of one CPU core, shared by all demodulators.<br>
<br>
Each channel demodulator runs in a separate thread and is completely<br>
independent of the others. They downsample (to 48 kHz), apply the<br>
desired filtering (currently 16 kHz, but easily changed) and demodulates<br>
to baseband. I'm using the FM demodulator for 2m, but I also have a<br>
'linear' demodulator for all the other modes (SSB, CW, IQ, envelope AM,<br>
synchronous AM, etc). Fine tuning is done for RF frequencies not<br>
multiples of 100 Hz, but that's more important for the linear modes than FM.<br>
<br>
My FM demodulator has an experimental "threshold extension" scheme that<br>
looks at the magnitude of each pre-demod sample and attenuates the<br>
demodulator output when the magnitude is below some fraction of the<br>
average amplitude. I haven't quantified it yet but it very audibly<br>
attenuates the "popcorn" noise you get in a FM signal at threshold. My<br>
squelch works from first principles: measure the mean and variance of<br>
the signal amplitude, convert to SNR, and open the squelch if it's above<br>
a threshold (currently 6 dB). It works so well I haven't felt the need<br>
for a squelch knob.<br>
<br>
While the NBFM demodulator needs the 48 kHz sample rate, I *could* use a<br>
lower sample rate (e.g., 16 kHz or even 8 kHz) for the narrowband modes.<br>
But I currently run the linear demodulator at 48 kHz since that's what<br>
the Opus codec prefers, and it doesn't seem to cost much anyway. (The<br>
compressed Opus bit rate only depends on the quality setting, not the<br>
input sample rate).<br>
<br>
Each FM demodulator thread uses about 0.7% - 1.0% of a CPU core, which<br>
is too small to get an accurate reading. When demodulating 216 channels<br>
everything uses about 133% CPU, i.e. 1.33 cores (of 8) on average. Opus<br>
compression actually requires considerably more CPU horsepower than FM<br>
demodulation, and I've discovered I need to thread it more. (Normal<br>
activity on the 2m band isn't a problem; I discovered the Opus limit<br>
only when I introduced a bug in my FM SNR routine that opened most of<br>
the 216 squelches at once.)<br>
<br>
I also have a 1200 bps AFSK AX.25 packet demodulator running on every<br>
channel, reporting whatever it hears to the APRS network. This doesn't<br>
take much CPU since it runs only when a squelch is open. The packet<br>
demodulator is a separate Linux program, reading the demodulated PCM<br>
audio from the SDR and multicasting its decoded frames back onto the<br>
LAN, where they're picked up by yet another program that reports them to<br>
the APRS network.<br>
<br>
My thinking for some time is that a satellite transponder designed to<br>
regenerate narrowband voice should have a multichannel receiver much<br>
like mine feeding the received digital audio streams into a single<br>
multiplexed downlink. In effect, I now have exactly this on my home<br>
network. To listen, I fire up an audio monitor program on my laptop that<br>
joins the IP multicast groups carrying the Opus-compressed audio and<br>
each active 2m channel pops up on my local display. I can pan each<br>
signal in the stereo image, adjust its gain, mute certain channels, etc.<br>
Joining the multicast group is handled by the network subsystem<br>
(including my smart Ethernet switch). The SDR itself just shovels out<br>
the bits and it doesn't care or even know how many users are listening.<br>
<br>
In a satellite, these multicast streams would come down multiplexed onto<br>
a single high speed downlink like the DVB-S2 subsystem you're designing.<br>
At the moment, my receiver only handles analog FM, compressing each<br>
audio channel with Opus. But it provides the framework for narrowband<br>
digital modes, or a hybrid analog/digital system. Each digital<br>
demodulator can run as an independent Linux process, reading the<br>
multicast output of a channel from my SDR, demodulating the signal and<br>
multicasting its own bit stream back onto the network. I'm looking at<br>
porting the MMDVM code to my system so it will work with multicast PCM<br>
audio in and out.<br>
<br>
In a satellite I envision a mixture of Opus-encoded analog FM streams<br>
and demodulated digital uplink streams, with an eventual transition to<br>
digital only.<br>
<br>
Anyway, this is all a proof of concept I think you might find<br>
interesting. The main programs are currently 'airspy', 'radio', 'opus',<br>
'packet' and 'aprs'. Each runs as a Linux daemon, automatically started<br>
at boot time. The 'radio' program reads a single configuration file<br>
telling it the frequencies and modes on which to listen and where to<br>
multicast the demodulated outputs (one IP multicast group can handle<br>
multiple streams).<br>
<br>
So this thing can operate totally turnkey with NO user interface except<br>
for the config file. It just demodulates each stream and multicasts the<br>
results for anybody on the LAN who wants to listen. I've been running an<br>
earlier version as a turnkey APRS receive-only iGate for several years<br>
on a Raspberry Pi 3 and an AMSAT UK Funcube Pro+ dongle (its 192 kHz<br>
sample rate is easily handled by a Pi2 or 3).<br>
<br>
There is an optional control/status interface to each demodulator that<br>
uses my own UDP-based protocol for which I've written a control client.<br>
You can enable/disable this on a per-demodulator basis in the config<br>
file. I typically start the regular demodulators without a control<br>
channel, then add one I can use to look around manually if I want.<br>
<br>
I'm ready to put this code out for general play. It's still pretty rough<br>
but I think it's a good proof of concept.<br>
<br>
Phil<br>
<br>
<br>
<br>
<br>
<br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr" style="font-size:small">Bob McGwier</div><div dir="ltr" style="font-size:small">Founder, Federated Wireless, Inc</div><div dir="ltr"><font size="2">Founder and Technical Advisor, HawkEye 360, Inc</font></div><div dir="ltr">ARDC Grants Committee<br><div style="font-size:small">Adjunct Professor Virginia Tech</div><div style="font-size:small">Former Chief Scientist: The Ted and Karyn Hume Center for National Security and Technology<br></div><div><div style="font-size:small">Senior Member IEEE, Facebook: N4HYBob, ARS: N4HY</div><div style="font-size:small"><div><br></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>