Teensy Convolution SDR (Software Defined Radio)

DD4WH

Well-known member
IMG_2200.jpg

Audio sample of AM reception of Jil FM from Algeria on medium wave 531kHz received here in Central Europe yesterday night with the Teensy Convolution SDR: HERE
The sound is a bit treble-boosted, because it was recorded with a very wide filter and the recording with the smartphone also boosted the treble and attenuated the bass a bit.

I am quite happy now with the reception and audio quality of the very first prototype of the Teensy Convolution SDR.

The source code of this prototype alpha version is HERE

What is the TEENSY CONVOLUTION SDR?
- a Software defined Radio for LongWave/MediumWave/ShortWave & wideband FM Stereo
- it needs a quite simple hardware quadrature sampling detector (QSD) like the Softrock or similar [I use this very simple QSD provided as a PCB by Joris kthkit[at]xs4all[dot]nl pa0rwe.nl/wp-content/uploads/2015/07/sdr_schematic.gif
- unlike other standalone-SDRs that use IQ-input from a QSD, the main filtering and demodulation is done in the frequency domain by Fast Convolution, this enables much steeper filters than the usual phasing approach

Specifications at the moment:

EDITED 2017_05_03 for new features:

* Teensy 3.6 with audio board working in floating point
* reception from about 12kHz to 30Mhz (in undersampling mode 50MHz to 151MHz)
* decimation-by-8
* FFT and inverse FFT with 1024 points using the new CMSIS DSP lib complex FFT function
* filtering with 513 tap FIR filter (in decimated 12ksps) --> comparably steep filters are normally available in commercial receivers from 2000$ upwards ;-)
* filter coefficients are calculated by the Teensy itself and the filter bandwidth can be chosen arbitrarily by the user
* demodulation of real synchronous AM with selectable sideband and "stereo" option, 9 "different" AM demodulators, LSB, USB, pseudo-Stereo-USB, pseuso-Stereo-LSB (maybe more to come . . .)
* demodulation of wideband FM Stereo transmissions
* display up to 192kHz of frequency spectrum
* Zoom into the spectrum for greater frequency resolution detail: Zoom FFT enables us to have up to 10Hz resolution in the spectrum display
* superb audio quality
* needs about 46% of the processor ressources at 96ksps sample rate and SAM demodulation, about 48% at 192ksps and AM demodulation, SAM at 192ksps needs 78% because of the atan2f calculations
* autotune on demand --> press a button and the carrier of an AM station is caught with an accuracy < 1Hz
* automatic gain control AGC borrowed from the excellent wdsp library by Warren Pratt
* dynamic frequency graticules on the x-axis of the spectrum display
* S-meter
* display of signal strength in dBm or dBm/Hz
* small frequency display showing the SAM carrier frequency
* real time clock working and on display
* optional manual IQ amplitude and phase imbalance correction
* automatic IQ amplitude and phase imbalance correction to account for imbalances in your hardware IQ production
* menu system to adjust many parameters
* save and load settings to/from EEPROM
* play MP3 or AAC files in Hifi stereo quality from the SD card
* reception of wideband FM broadcast stations by 1/5 undersampling with the same hardware --> MONO, but HiFi quality when using 192ksps sample rate
* automatic test for the "twinpeak syndrome" - a fault in the mirror rejection that occurs sometimes at startup. This is now reliably detected by the automatic IQ phase correction algorithm and the codec restarted to cure the problem
* AGC now has an optical indicator for the AGC threshold and many more AGC parameters can be adjusted
* Codec gain has now its own automatic AGC
* Spectrum display now also has an "AGC" that prevents empty screen for small signals
* manual notch filter with adjustable notch frequency and notch bandwidth


What is the SDR still lacking? --> wishlist ;-)

- at higher sample rates, tuning and filter bandwidth setting is disturbed by clicking noises. Audio should be set muted temporarily in such situations
- automatic realtime-clock adjustment by tuning into one of the time-signal-stations, eg. DCF-77
- Noise reduction in the frequency domain: I am very interested in implementing one of those sophisticated noise reduction algorithms that work in the frequency domain, eg. this one: HERE
- morse code decoder
- PSK31 decoder
- record and play IQ recordings on/from SD card

This thread is meant to discuss questions and developments of this and other SDRs built with the Teensy.
 
Last edited:
no ;-)

contact Joris, he sent me a PCB of the QSD about a year ago. Maybe he has some more?

Or use any other IQ-SDR: Fifi-SDR, FA-SDR, Softrock etc. There are many kits around.

I will try to put some suggestions for kits to use on my github Wiki in the next weeks, but not tonight, it´s too late ;-).
 
Very interesting stuff Frank. The problem in North America is that we don't have the longwave AM stations that Europe has. There's WWVB at 60kHz and then from 100kHz to about 450kHz there are just non-directional beacons for aircraft navigation. Even if we did, the other problem is that I doubt that I would have the patience to wind all those coils! Just replacing the burned out backlights in my IC735 is a major undertaking :)

Pete
 
Hi Pete,

Oh, I just took LW stations for the video, because they have the best reception and audio quality during daytime when there are not many stations around on shortwave. The Teensy Convolution SDR receives VLF, LW, MW, and SW from about 12kHz up to 30MHz ;-). And I guess you have a lot of mediumwave AM radio stations in North America, many more than we have in Central Europe (no MW stations broadcasting from Germany & France any more, by the way . . .). And shortwave can be used to listen to the whole world (just listening to music from Radio Rebelde, Cuba at the moment at 5025kHz, Radio Nacional Amazonia on 6180kHz is audible, but not so good today ;-)).

Coils: that must be a misunderstanding, there is exactly one coil in the Teensy Convolution SDR. I have some analog lowpass filters with some coils in my old project, the Teensy SDR, maybe that caused the confusion ;-). And coil winding is not complicated at all . . . The old Teensy SDR had a totally different demodulation approach using phasing in the time domain compared to Fast Convolution in the new Teensy Convolution SDR.

I will try to put some more info on the hardware into the wiki in the next weeks.
 
Last edited:
Hey Frank,
My memory is failing! I read the "reception from about 12kHz to 30Mhz" and 15 minutes later had forgotten it.

coil winding is not complicated at all
No, it isn't but I find it tedious.

Anyway, you've gone a magnificent job with the Teensy Convolution SDR.

Pete
 
Teensy Convolution SDR is evolving further:

* now uses decimate- and interpolate-by-8 in a two-step fashion (decimate-by-4 followed by decimate-by-2 --> processing in 12ksps --> interpolate-by-2 followed by interpolate-by-4 --> all implemented with the arm polyphase functions) in order to save MCU cycles (thanks Walter and Jim for your hints on that)
* true synchronous AM demodulation (SAM) in the same way as the big SDRs do --> phase detector, PLL and NCO
* up to 96kHz spectrum display with SAM demodulation
* up to 192kHz spectrum display with AM demodulaton
* in order to test different magnitude calculation algorithms, DC elimination algorithms and after-demodulation-filtering, I implemented nine "different" AM modes for testing
* now I use a 1024point FFT with 513 FIR coefficients instead of a 4096 point FFT with 2049 coefficients, but because of the x8-decimation, the filtering is still twice as good as before ;-)
* autotune on demand --> press a button and the carrier of an AM station is caught with an accuracy < 1Hz

next step is implementing a stereo version of SAM and sideband-selected SAM reception by implementing Hilbert filters in the SAM algorithm for sideband suppression.

In case you are interested: Source code HERE
 
Last edited:
Any plans to do NBFM demodulation using 25 to 30 KHz channel spacing for VHF and UHF ham radio? If so I can design an RF front end for such use. I spent 41 years at Motorola designing two way radio stuff, and was "retired" a couple of years ago.

George (KB4LRE)
 
Hi George,

my interest is mainly in the 0-30MHz frequencies, so narrowband FM demodulation is not on my list for the Teensy Convolution SDR, because it´s only used on 10m. If you are interested in FM demodulation, Clint has implemented that in the mcHF source code: https://github.com/df8oe/mchf-github

But maybe there are others here interested in the VHF/UHF frontend hardware?
 
Hi Frank,
I am new to this forum but have followed your SDR work with great interest. I started a new project with your original Teensy SDR, then discovered the Convolution variant and the newer DSP library functionality. I have followed the directions in this thread several times and on multiple computers but continue to have problems compiling your Convolution code of 2016-12-21.
Here are some specifics:
Arduino 1.6.13 and Teensyduino 1.33
The following files loaded into /--/Arduino/hardware/teensy/avr/cores/teensy3

libarm_cortexM4l_math.a
arm_math.h
arm_const_structs.h
arm_common_tables.h
libarm_cortexM4lf_math.a
Made the modifications in arm_math.h suggested by Duff on 10-22
#include <stdint.h>
#define __ASM __asm
#define __INLINE inline
#define __STATIC_INLINE static inline
#define __CORTEX_M 4
#define __FPU_USED 0
#define ARM_MATH_CM4
#include "core_cmInstr.h"
#include "core_cm4_simd.h"

Commented out per Duff's same post:
/*#if defined(ARM_MATH_CM7)
#include "core_cm7.h"
#elif defined (ARM_MATH_CM4)
#include "core_cm4.h"
#elif defined (ARM_MATH_CM3)
#include "core_cm3.h"
#elif defined (ARM_MATH_CM0)
#include "core_cm0.h"
#define ARM_MATH_CM0_FAMILY
#elif defined (ARM_MATH_CM0PLUS)
#include "core_cm0plus.h"
#define ARM_MATH_CM0_FAMILY
#else
#error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0"
#endif

#undef __CMSIS_GENERIC enable NVIC and Systick functions */

And inserted into arm_math.h #define __FPU_USED 1

I have tried compiling with different further steps, including directly loading the arm_xxx, etc files posted by Paul S on Github (10-22) into the same directory (/-/cores/teensy3), but no success. An example error message at this point is "arm_cfft_instance_f32' does not name a type"

Sorry for the lengthy message, but I suspect others may run into similar challenges. Can you point me to steps I may be missing or where I might go wrong?
Anything in boards.txt? Are the libarm_cortexM4lf_math.a and libarm_cortexM4l_math.a by themselves sufficient or are additional steps needed to extract these file?

I hope you can help!
Jan
 
Hi Jan,
seems you made a lot of progress since we communicated by PM!

From your description it seems you have done it right, except potentially the following:

1.)
And inserted into arm_math.h #define __FPU_USED 1
--> do not insert it, change the existing #define __FPU_USED 0 to 1 !

2.) did you add this to your script?
Code:
#include <arm_math.h>
#include <arm_const_structs.h>

3.) the two files libarm_cortexM4lf_math.a and libarm_cortexM4l_math.a have to be in a different folder, I think:
c:\Program Files (x86)\Arduino\hardware\tools\arm\arm-none-eabi\lib\

Good Luck,
73 de Frank
 
Hi Frank,
Thanks for your very quick reply:)
I moved the .a files as you mentioned and confirmed that the script includes the required #include files, but a quick test still ended up with similar compile errors. I'll do some more testing later today, will let you know what I find
Jan
 
Hi Frank - I finally succeeded in compiling the Teensy Convolution code! Your direction about the location of the .a files was key, as well as fixing some file version discrepancies. In the hope that it may help others, here is a full summary of steps (including those described in earlier posts by Duff and yourself, to capture the full picture in one post).

Two important items to check for the Teensy Convolution project:
1. use the correct Si5351 library for Arduino environment from Jason Milldrum here: https://github.com/etherkit/Si5351Arduino

2. Follow these install guidelines for the required CMSIS version 4.5.0 library functions:
A)download the CMSIS v4.5.0 library from https://github.com/ARM-software/CMSIS
B) unzip and copy these three files from the unzipped sub directory /CMSIS/Include:
arm_common_tables.h ; arm_const_structs.h ; arm_math.h
C) save these files to /--/Arduino/hardware/teensy/avr/cores/teensy3 (/--/ being the root of your Arduino environment)
D) Make these modification to the arm_math.h file
insert:
#include <stdint.h>
#define __ASM __asm
#define __INLINE inline
#define __STATIC_INLINE static inline
#define __CORTEX_M 4
#define __FPU_USED 1
#define ARM_MATH_CM4
#include "core_cmInstr.h"
#include "core_cm4_simd.h"

comment out:
#if defined(ARM_MATH_CM7)
#include "core_cm7.h"
#elif defined (ARM_MATH_CM4)
#include "core_cm4.h"
#elif defined (ARM_MATH_CM3)
#include "core_cm3.h"
#elif defined (ARM_MATH_CM0)
#include "core_cm0.h"
#define ARM_MATH_CM0_FAMILY
#elif defined (ARM_MATH_CM0PLUS)
#include "core_cm0plus.h"
#define ARM_MATH_CM0_FAMILY
#else
#error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0"
#endif
#undef __CMSIS_GENERIC enable NVIC and Systick functions */
E) Copy two more files from the unzipped CMSIS library, folder CMSIS/Lib/GCC
libarm_cortexM4l_math.a ; libarm_cortexM4lf_math.a
F) save these files to /--/Arduino/hardware/tools/arm/arm-none-eabi/lib/


That's it!
Jan
 
Thanks Jan, for posting the full set of instructions to get the new CMSIS lib working with the Teensy Convolution SDR! Will help a lot when somebody wants to setup the SDR.

New features now implemented in the Teensy Convolution SDR:

* sideband selection for synchronous AM reception (in order to get rid of noise and/or disturbing signals present in one sideband)
* stereo synchronous AM reception (well, actually pseudo-Stereo: you have the demodulated lower sideband on the left ear and the demodulated upper sideband on the right ear, while the SAM PLL locks to the carrier) --> nice to listen to with strong stations
* ZOOM FFT for the spectrum display: this technique adapted from the Lyons (2011) book is used to zoom into the spectrum display in order to see more detail with higher frequency resolution (while still using the same 256-point-FFT). Spectrum display now can show bandwidths from 96 (192) kHz down to 6kHz (frequency resolution down to 10Hz per bin, depending on the user-chosen sample rate). More resolution is possible, but for my radio purposes 10Hz/21Hz resolution is more than enough

Have fun with the Teensy Convolution SDR,

Frank
 
EDIT: spam message already deleted, thanks Robin, thanks Paul!
 
Last edited:
Hi DD4WH

Could you pls post the SW block diagram of the Convolution SDR showing the signal flow and processing done in this Teensy based project?

Also perhaps alongwith a writeup explaining the functioning of those blocks?

TIA.
 
The "SW block diagram of the Convolution SDR" does not exist, so I can´t post it ;-).

Have a look at the source code, it is not at all highly optimized, because I am not a programmer, so the flow in the source code should be very easy to follow.

Signal flow in brief is as follows:

I & Q data input from the QSD hardware into the LINE input of the Teensy audio board -->
queue 32 blocks of 128 samples of I & Q -->
convert int16_t to float32_t -->
Software I & Q amplitude and phase correction -->
Frequency translation by sampling rate / 4 without multiplication (see Rick Lyons´ book which explains how that works) -->
lowpass filter and downsample-by-4 -->
lowpass filter and downsample-by-2 -->
prepare buffers for digital convolution (I use the overlap and discard/save algorithm) -->
1024-point-FFT --> [from now on we are in the frequency domain]
fill those parts of the FFT buffer with zeros that are of no interest (e.g. upper sideband, when in LSB) -->
complex multiply the FFT buffer with the FFT results of a 513 tap FIR filter that has to be calculated once depending on the bandwidth chosen by the user -->
1024-point-inverse-FFT & take only the 2nd half of the iFFT output (overlap and discard/save) --> [we are back again in time domain]
Automatic gain control [controls both I & Q] -->
demodulation algorithm according to the chosen Demodulation mode:
- LSB / USB --> no demodulation necessary, just take the real part of the iFFT output
- AM: nine different algorithms implemented, take a look at the corresponding page in the wiki
- SAM: side band selected synchronous AM demodulation, see Whiteley 2011 (wiki) for an explanation
-->
upsample-by-2 and lowpass filter -->
upsample-by-4 and lowpass filter -->
scaling has to be done after this interpolation by 8 -->
take the 32 blocks of audio, convert them from float32_t to int16_t -->
push the 32 blocks x 128 samples into the output queue and listen to the radio ! ;-)

Not listed in the flow are the:
- spectrum display function
- Zoom FFT function
- and all the menus and settings, e.g. sample rate change etc.

Hope that helps in understanding and building the Teensy Convolution SDR!

Also perhaps alongwith a writeup explaining the functioning of those blocks?

Well, sorry, can´t do that, I have other books to write ;-): try these resources listed in my wiki:

https://github.com/DD4WH/Teensy-ConvolutionSDR/wiki/Links-&-Resources

And also this helps a lot for the general understanding of the Convolution approach:

Borgerding, M. (2006): Turning Overlap-Save into a Multiband Mixing, Downsampling Filter Bank. http://www.3db-labs.com/01598092_MultibandFilterbank.pdf
 
The "SW block diagram of the Convolution SDR" does not exist, so I can´t post it ;-).

Have a look at the source code, it is not at all highly optimized, because I am not a programmer, so the flow in the source code should be very easy to follow.

Signal flow in brief is as follows:

I & Q data input from the QSD hardware into the LINE input of the Teensy audio board -->
queue 32 blocks of 128 samples of I & Q -->
convert int16_t to float32_t -->
Software I & Q amplitude and phase correction -->
Frequency translation by sampling rate / 4 without multiplication (see Rick Lyons´ book which explains how that works) -->
lowpass filter and downsample-by-4 -->
lowpass filter and downsample-by-2 -->
prepare buffers for digital convolution (I use the overlap and discard/save algorithm) -->
1024-point-FFT --> [from now on we are in the frequency domain]
fill those parts of the FFT buffer with zeros that are of no interest (e.g. upper sideband, when in LSB) -->
complex multiply the FFT buffer with the FFT results of a 513 tap FIR filter that has to be calculated once depending on the bandwidth chosen by the user -->
1024-point-inverse-FFT & take only the 2nd half of the iFFT output (overlap and discard/save) --> [we are back again in time domain]
Automatic gain control [controls both I & Q] -->
demodulation algorithm according to the chosen Demodulation mode:
- LSB / USB --> no demodulation necessary, just take the real part of the iFFT output
- AM: nine different algorithms implemented, take a look at the corresponding page in the wiki
- SAM: side band selected synchronous AM demodulation, see Whiteley 2011 (wiki) for an explanation
-->
upsample-by-2 and lowpass filter -->
upsample-by-4 and lowpass filter -->
scaling has to be done after this interpolation by 8 -->
take the 32 blocks of audio, convert them from float32_t to int16_t -->
push the 32 blocks x 128 samples into the output queue and listen to the radio ! ;-)

Not listed in the flow are the:
- spectrum display function
- Zoom FFT function
- and all the menus and settings, e.g. sample rate change etc.

Hope that helps in understanding and building the Teensy Convolution SDR!



Well, sorry, can´t do that, I have other books to write ;-): try these resources listed in my wiki:

https://github.com/DD4WH/Teensy-ConvolutionSDR/wiki/Links-&-Resources

And also this helps a lot for the general understanding of the Convolution approach:

Borgerding, M. (2006): Turning Overlap-Save into a Multiband Mixing, Downsampling Filter Bank. http://www.3db-labs.com/01598092_MultibandFilterbank.pdf

--------

Thanks there. This is a helpful writeup.

The signal processing approach seems different from the Phasing / Weaver methods.

What audio setup / amplifier do you have after the Teensy audio board? The AM audio is very good.

Can you post some SSB audio samples if you can, in your free time?

Regards,
 
The signal processing approach seems different from the Phasing / Weaver methods.

Yes, those methods work in the time domain, convolution works in the frequency domain, you can read about that in the references I gave in my last post and in the wiki.

Maybe the description of my old Teensy SDR project -which uses a phasing approach- is also of some use for you (there are some more references in that pdf):

https://github.com/DD4WH/Teensy-SDR-Rx/blob/master/Teensy.SDR.Documentation.DD4WH.pdf

What audio setup / amplifier do you have after the Teensy audio board? The AM audio is very good.
no amp or setup, just the Teensy audio board headphone output. You should hear the Stereo-SAM audio and the SSB! Build the SDR and you will be surprised ;-).
 
I think so. It should work with every device that produces I & Q baseband signals. However, you have to make sure that the Teensy can control your local oscillator. Teensy Convolution SDR has code for the Si5351 LO.

As far as I know, the Softrock kit you mention has a fixed frequency LO? Then you would be able to receive only ONE single ham band with about 96kHz bandwidth. AND you would have to alter the code in order to frequency translate the I&Q signals in software, because you would need software tuning and not hardware tuning of the LO (because your LO is fixed frequency). That would require that you implement a quadrature oscillator in software (see Whiteley 201, pages 22ff for an explanation). You can insert bits of code that I have used for the Weaver way of frequency shifting (take the oscillator that is more costly in terms of processor usage, but that can move you to every frequency you need): you can find the Weaver code here (look at function freq_conv2):

https://forum.pjrc.com/threads/3897...using-quadrature-oscillators?highlight=weaver

An alternative would be to buy/build a QSD frontend that uses the Si5351 as a local oscillator. They should be available for 30-50$.
One example is the Elektor SDR, which works very well in my setup.
https://www.elektor.com/elektor-sdr-reloaded-150515-91?___store=default&___from_store=de
 
Thanks for the reply. I had looked at SoftRock and Eektor and it seemed the price of admission was pretty low with the SoftRock board, will look again at the Elector shield.
 
Back
Top