Open Source DSP Audio Processor for FT-817

gi1mic

Member
I have released an open source DSP audio processing project based on the Teensy audio library that targets Radio Amateur applications.

The Teensy 3.2/3.5/3.6 are ideal add-ons for older Radio Amateur equipment which does not include built-in audio DSP functions. It also opens many possibilities for integrating non-DSP functions such as USB CAT control, audio interfacing, Morse decoding etc. into a single simple to install hardware/software package that can be easily updated.

My focus has been installing the Teensy into a portable Yaesu FT817 rig but the same principles can be applied to vendor’s equipment or with an external amplified speaker.

I only discovered the Teensy and its Audio library a few weeks ago so it is still very early days for me. That means the code and feature set is continually changing and is not what I would class as production quality. More like a proof of concept :)

This project would not have been possible without the great work of Paul Stoffregen and Bob Maling.


The current release:

1. Removes the need to use external tools to calculate the filters. It is all now done in the code. There are examples of bandpass, bandstop, hipass and lowpass included in the "filterList[]" array.
2. Enabled emulation of a USB sound card allowing direct audio RX on a PC. To use this, make sure you select "Serial + Midi + Audio" for the "USB Type" on the Arduino Tools menu before compiling.
3. Added USB to CAT support but have not had time to test it yet!
4. Added options to enable different types of debugging support. Just make sure you don’t use these in CAT mode
5. Added support for the Teensy audio board. This makes it easy to use with external amplified speakers. To use it comment out "#define FT817" and uncomment "#define SPEAKER"
6. Added support for a rotary encoder to change the centre points of the filters. Its not much use yet since the setting is not saved between power cycles but I will add that in due course.
7. Upped the baud rate to 115200 from 9600

Full details and source code are available from https://gi1mic.github.io/

With luck, a few more features will be added shortly.

If you have questions or want to help, contact me here but be aware my DSP knowledge is limited to what I have read in the past couple of weeks!

Note: Comments within the code frequently provide more detail than my write-ups.

A video of the prototype is available via https://www.youtube.com/watch?v=s9hHDQcvHOI
 
Last edited:
Hi Gareth, GI1MIC,
About your interesting teensy filter, please consider also the feasibility to implement an audio binaural or pseudo-binaural filter for CW .
73 and thanks for your nice filter!
Augustoi I2JJR HB9TZA
 
Hi Gareth, GI1MIC,
About your interesting teensy filter, please consider also the feasibility to implement an audio binaural or pseudo-binaural filter for CW .

By binaural do you mean stereo?

It would be easy to convert the project for stereo but you would need use a Teensy audio shield or switch to a Teensy 3.6/3.6 to get dual DAC's for output. Given stereo would require more CPU cycles the larger Teensy boards would probably be the better option. Actual code changes would be minimal, mainly just duplicating sections of code.

As for pseudo-binaural I am not sure how it is typical accomplished. I suspect using time delays introduced at various frequencies to create a second pseudo channel but it is not something I have ever considered.


Gareth, GI1MIC
 
Sorry one of the things I have considered trying is detecting and "re-generating" Morse tone i.e. you would never actually hear the original RF signal just a pure "generated" or pre-recorded tone which could easily be in stereo.

For fun I already added Morse to speech decode capability which works reasonably well so playing back a tone or pre-recorded sample would not be a hard to add.
 
Binaural Audio to help CW detection by ear by oile-up

By binaural do you mean stereo?
As for pseudo-binaural I am not sure how it is typical accomplished. I suspect using time delays introduced at various frequencies to create a second pseudo channel but it is not something I have ever considered.
Gareth, GI1MIC

Hi Gareth, no , binaural CW reception is not a stereo reception, but yes, it requires two audio output channels.
I try to explain binaural as a sort of space-diversity by ears, hi .
You take the signal (before detection for pure binaural, after for pseudo-binaural) and introduce a relative phase/frequency shift : one channel from high to low freq , and the other reverse , low to high.
If done to the IF you then detect the signals, one for left channel, one for right channel, and then amplify it for headphones (better than speakers).
On detected audio for pseudo, you get the audio and process it the same way, one left up-down, one right down-up on phase/frequency.
The result is that the audio frequencies are "seen" by our brain as were coming from different points of the surrounding space, thus bettering the discrimination among them.
For example, you "feel" or "see" the audio "spreaded" high to low tones in front of you. This better the job of the op to decode.
It may be understand as a stereo hearing, but it is not properly a stereo signal, so to say.
These times ( 1970 or so) it was done by hardware of course. Years after, I asked to F6CTE to include something like this in his freeware MultiPSK and he implemented a good pseudo-binaural solution in it; you may hear it there as a test, it maybe interesting for you.
Hope these notes help you, Gareth; 73 and thanks.
Augusto
 
Hi! I amhaving problems compiling the source code into my teensy 3.2

i get this errors

Arduino:1.8.2 (Windows 7), TD: 1.36, Tarjeta:"Teensy 3.2 / 3.1, Serial, 96 MHz (overclock), Faster, US English"

C:\Users\cesar\Desktop\GI1MIC-DSP-Filter\GI1MIC-DSP-Filter.ino:71:22: fatal error: settings.h: No such file or directory

compilation terminated.

Se encontraron múltiples librerías para "SD.h"
Usado: C:\Program Files\Arduino\hardware\teensy\avr\libraries\SD
No usado: C:\Program Files\Arduino\libraries\SD
Error compilando para la tarjeta Teensy 3.2 / 3.1.

Este reporte podría tener más información con
"Mostrar salida detallada durante la compilación"
opción habilitada en Archivo -> Preferencias.

looks like a problem with the sd.h
Multiple libraries were found for sd.h

any help would be highly appreciated. I am a noob :(
 
Your code appears to be missing a file. From the limited info you've given, that's all I can tell.

I am a noob :(

No matter how little experience, you can post the actual code you're compiling (see the "Forum Rule" at the top of every page).

We can help you much more if we can see the actual code.
 
Hello i have a brand new teensy 3.2 and i tried to compile this lines

Code Issues 0 Pull requests 0 Pulse
GI1MIC-DSP-Filter/GI1MIC-DSP-Filter.ino

/*
* The GI1MIC $20 Dollar DSP Audio Filter
*
* Visit https://gi1mic.github.io/ for information on how to use this code.
*
* Email via GI1MIC at outlook.com
*
* Modify "settings.h" to suit your needs
*
*
* This project is for installing into a Yaesu FT-817 but easily be adapted
* for many other radios.
*
* What does it do?
* - Act as multiple DSP filters based on hi pass, lo pass, band pass or band stop (filter points can be defined in Hz within the code)
* - It uses voice messages to describe which filter has been selected
* - It is a USB to CAT interface
* - It emulates a USB sound card for receiving rig audio on a computer
* - Performs Morse to voice decode and Morse to USB serial decode
* - It can speak the radio config to assist the visually impaired (FT817 only)
*
*
* Version 2.2
* Some code updates
* Added support for audio files held on a SD card attached via a Teensy WIZ820IO addon board
* New speech files
* Includes tools to regenerate the speech files. This should make it easy to convert to other languages
* Adds speech readout of rig controls - Requires the CAT interface to be connected
*
* Version 2.1a
* Added a FIFO to the morse 2 speech decode to improve decoding when using SD card playback
*
* Version 2.1
* Minor bug fixes
* Configuration options now held in "settings.h"
* Added option to say callsign on boot
* Added Morse to speech decode based on WB7FHC code. This works OK for locally generated Morse but not ready for primetime.
* If you compile for the Teensy Audio board it will use WAV files on the card for playback.
* Otherwise it uses Texas Instruments speech synthesis architecture (Linear Predictive Coding) i.e. Speak & Spell voice synthesis
* Suspect the latter is taking too much time for Morse decode to work reliably
* Verified CAT control - dropped USB serial speed to 38400 to provide compatibility with some rig control software
* Version 2.0
* Moved to using real-time calculated FIR filters based on Bob Maling code
* Added support for Teensy audio board for simplified integration with an amplified speaker this uses
* a SD card fitted to the audio board to hold the speech files instead of the precompiled audio.
* Added preliminary support for USB -> CAT interface for rig control
* Added support for USB RX audio (Make sure you select Audio/Midi/Serial on the tools menu to compile without errors).
* USB TX may be added but it will require a Teensy 3.5/3.6 as they have dual DAC's (OK, it may be possible on the 3.2 using PWM...)
*
* Version 1.2
* This update changes the Morse coefficients to an improved set based on a Windowed hamming FIR filter.
* See the https://gi1mic.github.io/ for a MATLAB simulation of the filter.
* Note: this is a very sharp filter - you may want to generate your own!
*
* Version 1.1
* Code Tidy-up
* Smaller (lower quality) voice prompts
* Debug and FT817 mode controlled via defines
*
* Version 1.0
* Initial release which had no version number
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Encoder.h>
#include <Bounce.h>
#include "settings.h"
#include "cat.h"
#include "dynamicFilters.h"
#include "dspfilter.h"
#include "morseDecode.h"
#include "speech.h"
#include "configSpeak.h"

bool toneDet = false;

//---------------------------------------------------------------
void setup() {
Serial.begin(38400);
delay(500);

#ifdef DECODER
morseInit();
#endif

AudioMemory(8);

#ifdef SDCARD
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
#ifdef DEBUG
boolean status = card.init(SPI_FULL_SPEED, SDCARD_CS_PIN);
if (status) {
Serial.println("SD card is connected :)");
} else {
Serial.println("SD card is not connected or unusable :-(");
return;
}
#endif
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
};
};
#endif

#ifdef FT817
audioOutput.analogReference(INTERNAL);
#else
// Down mix stereo to mono on input
monoMixer.gain(0, 0.5); // Left
monoMixer.gain(1, 0.5); // Right
monoMixer.gain(2, 0.0); // Not used
monoMixer.gain(3, 0.0); // Not used

audioControl.enable(); // Start the SGTL5000
audioControl.inputSelect(AUDIO_INPUT_LINEIN);
audioControl.lineInLevel(5); // Set input level to 1.33V
audioControl.volume(0.8); // Set headset volume level

#endif

// Initialize the mixer (Normally the totals should add to 1.0 max)
audioOutputMixer.gain(0, 0.9); // Filtered radio audio
audioOutputMixer.gain(1, 0.9); // Audio Prompt (we get away with this since this input is not normally active)
audioOutputMixer.gain(2, 0.9); // Audio Prompt SD
audioOutputMixer.gain(3, 0); // PC Audio Input (Not used for now)

// Start in passthru mode
audioFilter(fir_active1,
NUM_COEFFICIENTS,
ID_BANDPASS,
W_HAMMING,
60.0,
20000.0 );
myFilter.begin(fir_active1, NUM_COEFFICIENTS);
// myFilter.begin(FIR_PASSTHRU, 0); // passthru mode

#ifdef FT817
pinMode(SELECT_PIN, INPUT);
#else
pinMode(SELECT_PIN, INPUT_PULLUP);
#endif

// Morse detect stuff
toneDetect.frequency(TONEFREQUENCY, TONEDURATION);
toneDetect.threshold(TONETHRESHOLD);

initCAT();
initConfigSpeak();

#ifdef CALLSIGN
muteRadio(); // Mute while reading callsign
speakChars(CALLSIGN);
unMuteRadio(); // Reset the ausio level
#endif

#ifdef DEBUG
Serial.println("setup done");
#endif
}


float toneState;
//---------------------------------------------------------------
void loop()
{

filterSelect.update(); // read the button state

if (filterSelect.fallingEdge()) { // On button press - switch to next filter in the list
filterIndex++;
if (filterIndex >= (sizeof(filterList) / sizeof(filter)))
filterIndex = 0; // if end of array, then loop to begining

if (filterList[filterIndex].filterID == MORSEDECODE) {
lowerRadio(); // Lower the radio volume in Morse Decode mode to make it easier to hear
}else {
unMuteRadio(); // Reset the ausio level
}

audioFilter( fir_active1,
filterList[filterIndex].coeff,
filterList[filterIndex].filterType,
filterList[filterIndex].window,
filterList[filterIndex].freqLow,
filterList[filterIndex].freqHigh );
#ifdef SDCARD
speakSD(filterList[filterIndex].filterName[0].c_str());
#else
speak(filterList[filterIndex].audioSample);
#endif
}
// Rotary Encoder - move the centerpoint of the filter
long newKnob;
newKnob = knob.read();
if (newKnob != kPosition) {
int diff = (newKnob - kPosition) * 4;
#ifdef DEBUG
Serial.print("Knob = ");
Serial.print(diff);
Serial.println();
#endif
filterList[filterIndex].freqLow += diff;
filterList[filterIndex].freqHigh += diff;
audioFilter(fir_active1,
NUM_COEFFICIENTS,
filterList[filterIndex].filterType,
filterList[filterIndex].window,
filterList[filterIndex].freqLow,
filterList[filterIndex].freqHigh );
kPosition = newKnob;
}


#ifdef SHOWPERF
// print debug and resource usage
if (millis() - last_time >= 2500) {
if ( audioInputPeak.available() ) {
Serial.print("Peak input level = ");
Serial.print(audioInputPeak.readPeakToPeak());
Serial.print(", ");
}
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
last_time = millis();
}
#endif
serviceCAT();
serviceSpeech();
serviceConfigSpeak();

#ifdef DECODER
if (filterList[filterIndex].filterID == MORSEDECODE) { // Service morse decoding
if (toneDetect) {
morseKeyDown();
}else {
morseKeyUp();
};
};
#endif
}
 
You have not installed the software correctly. You appear to be compiling only GI1MIC-DSP-Filter.ino without its supporting files. I installed the DSP filter software from the zip file, and it compiles without any errors (when compiled as USB Type "Audio").

Pete
 
I don' t find that zip you refer to. All i see is a lot of files on the folder. I ser the source code link on instructions web and that is what I tried to compile. ..
 
I just compiled that gi1mic-dsp-filter.ino
Do i have to compile everything? I mean. Dspfilter.h
Cat.cpp
...

Etc etc
 
Yes, you have to compile it all. I downloaded the ZIP file from here and unzipped it into my Teensy directory. Then open the .ino file in the IDE and compile.

Pete
 
Looks like it was correctly compiled
I downloaded the zip and executed the ino do arduino app on windows was launched
Compiling was successful
But when i try to upload to teensy i get

Teensy did not respond to a USB-based request to automatically reboot. Please the program mode button on hour teensy to uploaf your sketch


Ok i press the button but nothing happens
 
I had a problem with the usb cable
Now it is ok
I uploaded it and asked me to push the button on tenensy

Now i am redy to use it fisically unoluged from ghe pc? Do i need to push the button to make it work? Thanks
 
The Push button is only there to switch the Teensy into program mode.

When you unplug it from the PC, it will start to run by itself each time it is powered.
 
The code which you posted above ist just NOT a standalone program, but rather seems to be a pool of various options. in ever case, you‘ll need to connect a rotary encoder to the Teensy to tune the filter center frequency. Then you will have to add several #defines to the code to select the different options.
You really should study the code until you understand everything before you start using it.
 
Ok I just saw that the author posted that if you don't want to mess with the code you may just use the hex files and load it up...


Quick Start

Just want to try it without the hassle of setting up a development environment?
"
Download a recent HEX file from the "bin" folder and use the Teensy command line loader as described here
"
 
Audio processing is fine, equalization is a MUST, but it would be a very nice addition for this project to also implement an RF compressor/clipper using the Hilbert transform, and a noise gate just like Voice Shaper. This means Microphone --> Equalization/noise gate ----> SSB modulation ---> SSB envelope compression/clipping ----> SSB Demodulation ----> Processed Audio sent to transmitter.

The three stages of SSB processing can be achieved digitally using the hilbert transform, but I don't know how far can you go with the teensy.

In my opinion, Voice Shaper is, by far, the most flexible and powerful speech processor available today for SSB. In the other hand, there is the need for a computer to run the software... so I see a lot of potential for an RF processing stage in this project. I guess this can be easily created in MATLAB.

73 DE LU6PSG
 
Last edited:
Hi Gareth...
Many thanks for this. I spent the weekend prototyping a board to add to my uBitx, with some success.
The uBitx is without AGC so I will need to add one before I can properly use this board, but that should not be a huge problem.
I wonder would there be enough horsepower in the Teensy to implement autonotch or noise-reduction?
Regards
Gerry

20180303_110911.jpg
 
Hi Gareth...
Many thanks for this. I spent the weekend prototyping a board to add to my uBitx, with some success.
The uBitx is without AGC so I will need to add one before I can properly use this board, but that should not be a huge problem.
I wonder would there be enough horsepower in the Teensy to implement autonotch or noise-reduction?
Regards
Gerry

Hi gerryk
Let us know how do You complete Your project with AGC.
I have ordered uBITX and have Teensy board, so I would like to use it like You.
Noise reduction would be great :)

Regards
Lukas
SQ9RZM
 
Hi!

looks like a great HAM RADIO project!

@LU6PSG: you are talking about TRANSMIT, whereas this thread is about RECEIVE
I do not think that RF clipping is the right way to achieve good TX SSB quality. Dave Hershberger has recently published a very nice and elegant way to treat the baseband audio in order to achieve Controlled Envelope SSB.
www.arrl.org/files/file/QEX_Next_Issue/2014/Nov-Dec_2014/Hershberger_QEX_11_14.pdf
It needs an SSB modulator (search for Weaver in this forum) and good linear phase filters (simple FIR filters are sufficient, search for Convolution SDR in this forum).
So this could be achieved with the Teensy with careful audio baseband processing.

@SQ9RZM, Gerry:
We have implemented autonotch filtering with the LMS algorithm and a very nicely working spectral noise reduction for the Teensy Convolution SDR (source code is on github):

https://github.com/DD4WH/Teensy-ConvolutionSDR

However, the noise reduction only works with floating point processing and the Teensy 3.6 (and by manually installing the newer version of the ARM DSP library in Teensyduino)

Reason for floating point is that you need an audio chain with FFT --> audio processing in the frequency domain --> inverse FFT
And that FFT-iFFT audio conversion only works out with nice audio if you are using floating point processing (maybe due to inaccuracies when doing fixed point FFT processing). And floating point processing with the smaller Teensies is a little slow, so I took the T3.6.

The LMS algorithm (for the autonotch) could run with fixed point processing on the T3.2, but I have not tried that. If you do, try the ARM library algorithm for normalized LMS and take a low number of taps, eg. 32 and 64 samples for delay buffer.

Have fun with the Teensy!

Frank DD4WH


@HB9TZA
By the way, the Teensy Convolution SDR also has binaural receive modes like IQ-mode, Stereo SSB (LSB left ear, USB right ear) and Stereo SAM (snychroneous AM demodulation of lower and upper sidebands to the left/right ear).
 
Back
Top