AudioSDR - A single Audio block SDR (software defined radio) processor/demodulator

@robjohn...
Nice looking unit. I really like the simplicity of your panel and display!! My unit(s) are still being built on protoboards with hand wiring underneath.

I'll be delighted to share my control/display software with you. However, it's continually being updated, and is not quite as clean as I would like before being released. For example, I've (just this week) added a menu sytem for adjusting operating mode/band/adjusting operating parameters etc. It's working well but the code is still a bit untidy. :rolleyes: It's a work-in-progress and always will be.
The other thing is that the code is closely tied to my hardware. For example, I use an I2C port expander to communicate with the tactile switches on the front panel, and I have a home-brew RF front-end with an "SDR Cube" (which has 0/6/10/16 dB atten, and 4 octave-wide BPFs) and I use another port expander to control that. I am also using direct quadrature generation from the SI5351 (without the "divide by 4"). So you may have to make quite a few adjustments.

How should we proceed? I'll start by uploading the SI5351 libraries to GitHub tomorrow. Maybe we should continue by PM? It'll take me a day or so to package up all my libraries...

The things I'm working on right now are:
1) Improving the panadapter display (graphics, smoothing, and algorithm). I had to compromise with the T3.6, but the extra speed of the T4 opens up new possibilities.
2) As you say, the AM demod is not as clean as it might be, although I get a 120 Hz hum on the audio. It should be the simplest demodulator - it is just a quadrature envelope detector - but it has given me the most problems. Also, I'm not happy with the capture range in the PLL used in the SAM detector, and am looking at that.
3) A bigger project is the design of a proper adaptive audio noise reduction filter. At the moment it simply uses the notch filter in an enhancement mode.

BTW - what display are you currently using? Is it the PJRC ILI9341 2.8". I ask because I'm planning to move up to a 3.5", which will mean yet another bunch of software changes. It just never ends...

Derek
 
Hi Derek
The unit is only tidy on the outside :) using the ILI9341 3.5" with adafruit lib, has lots of nice fonts to choose. The serial interface does generate RFI though.

Interest is mainly your audioSDR functions. My first coding attempt with PJRC audio library was a simple DC IF SSB demod phasing method but image reject was poor and never got round to figuring out AM. Then found yours to try and was fairly straightforward to implement. I have buttons to scroll through the detectors and BW. Should I be able to compile code for the panadapter? I took code from the doc but there's nothing in the lib header files for panadapter.

I will definitely try out any updates you post, especially AM, panadater, AGC bar-graph and library for the SI5351 tuning.

Cheers Rob
 
Rob or anyone who cares to reply:
Does anyone have a sketch that implements a. complete ssb/cw receiver using rhis library? I'd like to load it up and use it as a starting point for my own development.

Regards
Joe
 
Yes, anyone who knows the library exists will have seen these partial functionality test sketches. I was looking to see if anyone has built a complete radio system, along with their account of how the process went and how well the final result turned out. I have some questions that only someone who has actually done it (or the author) could answer.

Thanks
Joe
 
I've got a functional SDR up and running but would like to run this code ... Currently running teensy 4.0 / QRP Labs quadrature receiver and SI5351... my issue is I can't get it to compile due to the streaming.h file is missing .. I went into AudioLib and remarked out the streaming.h file ...however its still reporting the file missing .. I checked the AudioLib again and the streaming.h file is rem'd out ...am I missing something ?

Thanks

code looks great ! .. nice library you have created ...looking forward to running it up
 
Well ... I built the ZL2CTM time domain processing SDR .. but have scaled it up to a 5" touchscreen ..Spectrum display and Waterfall display, I'll let you know how it goes as a lot of my touchscreen will need to be re-mapped to leverage the features of Audio SDR.

I have a step by step build post on the FB " Amateur QRP Radio" forum .. dated August 9 of this year .. if you have all the parts assembled you can build in in a long weekend..

https://www.facebook.com/groups/qrpradio/permalink/2719924171604479
 
okay issue resolved ...had 2 copies of the library .. edited the wrong one ...(and then promptly deleted it when I figured it out) ..please ignore my post above
 
Some help on compiling AudioSDR to t4.0

Okay .. teensy 4.0 .. followed the instructions for moving the files to the appropriate directories..(however 3 of the files were placed in the teensy3 directory .. not sure how to deal with the teensy 4 in this case..
could use some direction ..not sure if Derek is around ...

however I'm getting a compiling error AudioSDR.h ...
.
In file included from E:\libraries\AudioSDRlib/AudioSDRlib.h:1:0,from E:\AudioSDR\EXAMPLES\BareBonesWSPR\BareBonesWSPR.ino:5:

E:\libraries\AudioSDRlib/AudioSDR.h: In member function 'float32_t AudioSDR::fast_sqrt_f32(float, int)':

THE 2 BELOW ARE WARNINGS

E:\libraries\AudioSDRlib/AudioSDR.h:381:34: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
uint32_t val_int = *(int*)&x; // Same bits as in the float, but as an int
^
E:\libraries\AudioSDRlib/AudioSDR.h:383:23: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
out = *(float*)&val_int;
^
Sketch uses 49888 bytes (2%) of program storage space. Maximum is 2031616 bytes.
Global variables use 98996 bytes (18%) of dynamic memory, leaving 425292 bytes for local variables. Maximum is 524288 bytes.
 
Last edited:
ISSUE Resolved

Issue resolved .. after reading some remarks in the AudioSDR.H File .. this does generate a compiler error but apparently ... ( its okay) ....

So will test and see what happens ..

please dis-regard my post re compiling error above ..

Thanks
K
 
Thanks Derek for sharing the library. I just got this working, but not without some problems to solve. Perhaps listing my issues can help someone else. I am running on the Teensy 3.6.

Program hang, no audio: Hang on the first codec command . PJRC audio design tool says codec.enable(); needs to be the first command to the controller so I moved that command up to just after AudioNoInterrupts.

Initial testing with the LSB mode, audio sounded like SSB with an AM detector: I found that
SDR.setNoiseBlankerThresholdDb(5.0); is way too aggressive ( value from the documentation ). I am now using
SDR.disableNoiseBlanker(); to avoid searching for a proper value for my receiving location ( very quiet location ).

My hardware is a QRP Labs QCX with a G5RV antenna which brings me to things I need to look at. No signal noise sounds more like system generated noise rather than atmospherics. I wonder what the system gain should be before the audio line in? The QCX has 36db of gain to where the I and Q are made available on headers.

Other observations: A lot of bass in the audio although I think I was listening to a guy running a SDR hifi setup. The AGC works very well.

Ron
 
Thanks Derek for sharing the library. I just got this working, but not without some problems to solve. Perhaps listing my issues can help someone else. I am running on the Teensy 3.6.

Program hang, no audio: Hang on the first codec command . PJRC audio design tool says codec.enable(); needs to be the first command to the controller so I moved that command up to just after AudioNoInterrupts.

Initial testing with the LSB mode, audio sounded like SSB with an AM detector: I found that
SDR.setNoiseBlankerThresholdDb(5.0); is way too aggressive ( value from the documentation ). I am now using
SDR.disableNoiseBlanker(); to avoid searching for a proper value for my receiving location ( very quiet location ).

My hardware is a QRP Labs QCX with a G5RV antenna which brings me to things I need to look at. No signal noise sounds more like system generated noise rather than atmospherics. I wonder what the system gain should be before the audio line in? The QCX has 36db of gain to where the I and Q are made available on headers.

Other observations: A lot of bass in the audio although I think I was listening to a guy running a SDR hifi setup. The AGC works very well.

Ron

Hi Ron,
I've been away from the AudioSDR project for over a year at this point, but am getting right back into it as we speak with a Teensy 4.1 version. I'm also very familiar with the QCX/QCX+, in fact I have three of them sitting on my desk right now! (I'm running a radio club project to have members learn about theory and construction, etc by building the QCX+).

My first reaction is that the QCX is not a good choice for a front-end to AudioSDR. It is a narrow-band receiver, optimized for audio at 700 Hz, whereas the AudioSDR code expects a wide-band IQ input (0-22kHz) and performs its demodulation at 5-10 kHz (approx). I presume you are picking off the audio from the outputs on IC5a, and IC5b? - that's the only relevant spot. Now, if you look at differential amps IC5a&b you will see that they have 10k R and a 10nf C in parallel in the feedback path, which gives the amps a low-pass characteristic with a cut-off frequency of 1590 Hz! That will be fine/great for the intended 700 Hz CW audio, but not as the input to AudioSDR! I think a lot of your observations might be caused by the highly restricted bandwidth. (I also have an issue with the QRP labs QSD design in that the input impedance at the two differential inputs will not be the same - but that's a separate matter.)

BTW - I have used the QSP Labs receiver module as an input to AudioSDR in the past, and found its performance to be just so-so.

Derek, AK1WI
 
Hi Derek,

Thanks for the reply. While building the QCX I left out the 10nf caps C4, C7 and changed the QSD caps to 47nf instead of 470nf. For a bit of humor you might ask why 47nf ? I did some reading about the Tayloe detector, did some calculations, looked at some existing designs and thought 82nf or 68nf would be good, and then looked at my capacitor kit and found my choice was between 47nf or 100nf.

I am using the T3.6 because I had the matching audio board. I have a T4.1. I am wondering if I should order the audio board for that. My wiring at this point is wire wrap on header pins and could be changed very easily where needed.

Ron
 
Hi Derek .. Just a thank-you for putting this library together .. I have a builders group on facebook for simple SDRs .. (starting projects) and your library is getting used by some of the members (myself included) ...Your library is easy to follow and implement..
Great Job !!
Thanks for contributing to the community !!

cheers 73 Keith (VE3IFT)
 
Hi Derek (and Frank) : Excellent work on this advanced SDR Audio object for Teensy. Frank (DD4WH) and I had a string of posts about the "twin peaks" problem a year back. While we knew it was a random dropping of a sample in one channel, at the time I think we blamed it on the SGTL5000, where it now seems like it is an ARM MCU I2S hardware problem. I came across this thread while thinking about eliminating the Teensy Audio board for the SDR and instead using the Teensy 4's two internal 12-bit ADCs. They're not I2S, so the sample dropping problem should disappear. They're only 12-bits but looking at the QCX transceiver project, they are getting by with just the single 10-bit ADC in the M328 MCU. They have to use the ADC multiplexer and correct for the non-simultaneous sampling in software. There is a Stereo ADC Audio lib component, so it should be easy to try. Those dual SAR ADCs can sample much faster than 44100 SR, so presumably you could oversample by 4 and decimate, getting 2 more bits. Plus, they are DC-coupled (good for Weaver I hear).
Granted, they don't have a variable gain input amplifier like the SGTL5000 but I thought an op-amp and I2C dual EEPOT would handle that. For Audio output I'd likely use the Maxim MAX98357 I2S 2.5W amplifier- I've used them in the past. Or a PT8211 which I've also used. Both have applicable Teensy audio objects.
Any thoughts?
By the way, your AudioSDR PDF document is excellent. If I may, I'd only suggest that you change the following code snippit on page 6 as it contains some typos which might confuse users who copy it into their code directly:
AudioOutputI2S ouput; // should be output
In the last 2 lines, c1( mySDR and c2(mySDR //should be c3 and c4 - this won't compile as is

While it sounds like your latest version 1.01 is supposed to have eliminated the stray references to "streaming.h" , I did not find this to be the case. I had to remove it in AudioSDRpreProcessor.h and .cpp (and 1 other file but I can't recall now which one). I downloaded these from the github repo- https://github.com/DerekRowell/AudioSDR
I'm not a ham either Derek!
Cheers
 
Hi Ron: Are you saying that you have both the Teensy and the Audio adapter mounted separately and hooked up with wires or are they stacked? If the former, the earlier Audio adapter will work fine with the newer T4.x as long as you change a few wires to reflect the fact that the T4.0/1 use different pins (than the T3.6) for a few of the I2S lines. The only other change is that you need to put a 100 ohm resistor in series with the MCLK line. PJRC has good diagrams for all this on their site https://www.pjrc.com/store/teensy3_audio.html
I am using my older Audio Adapter with both T4.0 and T4.1 boards. Works fine.
Cheers
 
While we knew it was a random dropping of a sample in one channel, at the time I think we blamed it on the SGTL5000, where it now seems like it is an ARM MCU I2S hardware problem.
That's interesting! Why does it never happen with the I2S PCM1808 as ADC?
 
Hi,

After learning a bit from this library and the ZL2CTM code, I wrote my own implementation. For the twin peaks issue, I put a 2 element FIR filter in I and Q channels, constants 1.0 and 0.0 and just swap the constants when needed. I am using the stacked boards.

I didn't seem to have any issue in implementing the Weaver method. It is toward the middle of a video I uploaded to youtube, about at 4:12.

https://www.youtube.com/watch?v=QqMDmRqCZDI
 
For my HW, the approach with instrument ampilifiers (INA) works very good ) and without "Twin Peaks"
I built a SDR board for that (my very first receiver project) and it works really great.
Unfortunately, i moved, and live now mid-town with many neighbours(wow..30WLANs neaby!), a streetcar nearby and not enough place for a good antenna.
So I had to give up.
 
That's interesting! Why does it never happen with the I2S PCM1808 as ADC?

Hi Frank: I was just re-quoting an earlier post in this thread- I only have the SGTL5000 on the Teensy Audio board and I certainly had the problem using that codec. If you don't get it with the T.I. -Burr-Brown PCM1808 then the MCU's I2S hardware must be fine. But, I am still interested to see if the Teensy 4.x ADCs would work OK- considering my comments on the QCX-SSB project using the AVRs single 10-bit ADC. It is good to hear from you again.It must be the middle of the night there!
I have been doing various other types of MCU projects over the last year with ESP32, STM32 and Silabs Bluetooth MCUs in addition to the Teensy boards.
Cheers
 
at the time I think we blamed it on the SGTL5000, where it now seems like it is an ARM MCU I2S hardware problem.

Hi Brian, nice to hear that you are still working with Teensy and SDR!

As I wrote earlier in several posts in this forum:

The twinpeak problem (problem of random order of samples at startup of several audio codecs) is definitely a problem of the CODEC, NOT of the MCU!

1.) I have experienced the very same problem with Teensy 3.6, Teensy 4.0, STM32F4, STM32F7 and STM32H7
2.) I have experienced the very same problem with audio codecs SGTL5000 and WM8731
3.) I have NEVER experienced this problem with ADC PCM1808 (an audio ADC, NOT a codec). I have used the ADC PCM1808 with Teensy 3.6, Teensy 4.0 and Teensy 4.1 running my Teensy Convolution SDR software.
4.) The problem ALWAYS occurs at startup of the codec, it NEVER occurs once the codec has started and is running properly

Thus, my conclusion is:

1.) The mentioned problem is a problem of several brands of audio CODEC chips at the time of the start-up of the audio codec chip
2.) The problem is NOT a problem of I2S handling in MCUs, it is independent of whatever MCU you use and seems to be present in at least two codec brands

@rcarr: would it be possible for you to share your work-around-code ?

@Derek: yes, I agree with Brian, your write-up is excellent!

73 Frank DD4WH
 
Derek's library mentions correcting the phasing issue automatically. I made it a menu item and call this function when I see issues on the waterfall.

Code:
// GUItool: begin automatically generated code
AudioInputI2S            IQ_in;          //xy=142,624
AudioFilterFIR           PhaseI;         //xy=280,556
AudioFilterFIR           PhaseQ;         //xy=286,722
.............................
// phase correction FIRs. Apparently sometimes the I2s audio samples are 1 step out of phase
// and waterfall shows very little opposite sideband suppression
int16_t  PhaseIfir[2] = { 32767, 0 };    // swap constants to change phasing
int16_t  PhaseQfir[2] = { 32767, 0 };
.............................
// I2S audio sometimes starts with I and Q out of order
void PhaseChange(uint8_t chg){
static int val;

   if( chg ){
      if( ++val > 2 ) val = 0;                            // rotate through the settings
   }
      // print 
   tft.setTextSize( 1 );
   tft.setCursor(262,66);
   tft.setTextColor(EGA[14],0);
   tft.print("Ph:  ");

   switch( val ){
      case 0:  
         PhaseIfir[0] = 32767;   PhaseIfir[1] = 0;        // normal in phase
         PhaseQfir[0] = 32767;   PhaseQfir[1] = 0;
         tft.print("1010");
      break;
      case 1:
         PhaseIfir[0] = 32767;   PhaseIfir[1] = 0;    
         PhaseQfir[0] = 0;       PhaseQfir[1] = 32767;    // delay Q  ( delay I if fir runs backward )
         tft.print("1001");
      break;
      case 2:
         PhaseIfir[0] = 0;       PhaseIfir[1] = 32767;    // delay I
         PhaseQfir[0] = 32767;   PhaseQfir[1] = 0;
         tft.print("0110");
      break;
   }  
}
 
Back
Top