FT8 on Teensy 4

kd9kck

Active member
Hello, I am working on implementing FT8 audio processing using the Teensy 4.0.

I am basing my process off https://github.com/kgoba/ft8_lib

So far I have figured out that I will be getting very close to the full memory on the Teensy due requiring 13 seconds of recorded audio.

I am starting to think it isn't a fessable project but I haven't actually done anything but look at what the memory foot print would be. Since I am running the audio into a FFT would it benefit me to break up the work process audio as its recording and only store the FFT?

Also should I write a new FFT Block or just work on samples out of a queue with a FFT program. I know I will be processing audio and trying to pick out freqs in the FFT that are only 6.25 hz apart.



Is this a task that just isn't suited to even try on the Teensy?
 
I had a look at decoding ft8 and ft4 on a teensy4 and concluded that there was wasn't enough memory. But I've had a look at the ft8_lib that you linked and it might fit on a T4.1. I've compiled it with cygwin on a PC and I'm going to add some debugging to it to print out how much memory it mallocs. I'll let you know how it goes.

Pete
 
How FT4 might have better luck then FT8 due to having shorter time slices.Requiring less memory for audio samples. But it would require more processing I think.


I will try and compile it and take a look will valgrind on my server to look at memory usage.
 
Heres a valgrind run on one of the test wavs.

Code:
chibill@jwg1:~/Desktop/ft8_lib$ valgrind ./decode_ft8 tests/20m_busy/test_01.wav
==40938== Memcheck, a memory error detector
==40938== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==40938== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==40938== Command: ./decode_ft8 tests/20m_busy/test_01.wav
==40938==
Sample rate 12000 Hz, 92 blocks, 960 bins
==40938== Conditional jump or move depends on uninitialised value(s)
==40938==    at 0x10A8E6: kiss_fftr_alloc (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==    by 0x109807: extract_power(float const*, ft8::MagArray*) (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==    by 0x10A3FD: main (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==
Block size = 1920
Subblock size = 960
N_FFT = 3840
FFT work area = 38688
Max magnitude: -16.8 dB
==40938== Invalid read of size 1
==40938==    at 0x10CEC8: ft8::find_sync(ft8::MagArray const*, unsigned char const*, int, ft8::Candidate*, int) (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==    by 0x10A428: main (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==  Address 0x1ffeef8622 is on thread 1's stack
==40938==  3726 bytes below stack pointer
==40938==
==40938== Conditional jump or move depends on uninitialised value(s)
==40938==    at 0x10CF41: ft8::find_sync(ft8::MagArray const*, unsigned char const*, int, ft8::Candidate*, int) (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==    by 0x10A428: main (in /home/chibill/Desktop/ft8_lib/decode_ft8)
==40938==
000000  57  1.5 2278 ~  PY2DPM ON6UF RR73
000000  63  1.2 1122 ~  CQ HB9CUZ JN47
000000  58  1.3 1509 ~  JO1COV DL4SBF 73
000000  71  1.3 2141 ~  LZ365BM <0628> 73
000000  61  1.3 2328 ~  CQ R8AU MO05
000000  81  1.2 2691 ~  CQ OE8GMQ JN66
000000  57  1.1 2050 ~  PD0CIF/PHOTO
000000  65  1.5 1291 ~  EA9ACD HA5LGO -13
000000  74  1.1  891 ~  SA5QED IQ5PJ 73
000000  61  1.4  706 ~  CQ IK4LZH JN54
000000  94  1.3  822 ~  LY2EW DL1KDA RR73
000000  87  1.4 1563 ~  JI1TYA DH1NAS 73
000000  79  1.2 1372 ~  CQ OK6LZ JN99
000000 101  1.3  559 ~  OE3MLC G3ZQQ 73
000000  96  1.0  956 ~  CQ IU8DMZ JN70
000000 103  1.2  338 ~  JO1COV PE1OYB JO21
000000  89  2.2 1450 ~  CQ RX3ASQ KO95
000000  70  1.1 1616 ~  JO1COV PA0CAH JO21
000000  96  2.3  772 ~  JA1FWS OK2BV JN89
Decoded 19 messages
==40938==
==40938== HEAP SUMMARY:
==40938==     in use at exit: 0 bytes in 0 blocks
==40938==   total heap usage: 5 allocs, 5 frees, 404,280 bytes allocated
==40938==
==40938== All heap blocks were freed -- no leaks are possible
==40938==
==40938== Use --track-origins=yes to see where uninitialised values come from
==40938== For lists of detected and suppressed errors, rerun with: -s
==40938== ERROR SUMMARY: 22255 errors from 3 contexts (suppressed: 0 from 0)

The amount allocated is constant for all the tests.

The thing valgrind doesn't tell me is how much memory is in the program as like a already existing predefined array.
 
Yea. Thats an idea. Plus the Teensy 4.1 has ethernet which is nice as well.

I think I am going to try my best to get the memory foot print down on my server first then hopefully it will be able to fit on the 4.0 but if not I will get a 4.1 (Haven't really done much with the 4.0 yet.)
 
Also another question I have is if its possible to run the Teensy at a lower sample rate? As running at 44.1 Khz mean I need FFT with 7056 bins. While the protocol will work with a sample rate of 12 Khz with 1920 bins. (A huge improvement, I wonder if I can find a weird sample rate to get a nice power of 2 for the FFT)
 
Are recordings of actual received audio signals published anywhere?

Or maybe someone with the right radio gear and audio recording equipment would be willing to record some WAV files?
 
I can record some audio if needed. Also in the library I am investigating to use there are many test wave files that are of one 15 sec cycle.
 
Also just wondering would it be possible to attach an external SPI ram chip to my Teensy 4.0 I already have in some way or would my only choice for adding PSRAM be to buy a Teensy 4.1?
 
A memory chip connected to the ordinary SPI pins will not be useful. The IMXRT chip has 2 different types of SPI ports. The ordinary "LPSPI" are for peripheral chips. FlexSPI is optimized for memory. Only Teensy 4.1 exposes a FlexSPI port for the memory chips.
 
Dang it. Was hoping I could use my existing Teensy 4.0 (I might be able to abuse https://github.com/rhelmus/virtmem but its probably not worth the trouble.)

I don't know much about the IMXRT chip used in the Teensy 4 maybe I should do some research.

For now I am going to do some deving on an ESP I have with enough memory.(WROVER) Need to decided if I want to get a new teensy just to experiment with this.
 
My gut feeling is you probably can use Teensy 4.0, maybe with a little creative effort.

For example, to save 200K of RAM you could put all the WAV data into a "PROGMEM const" array. As long as you only need to read the data, having it in read-only flash should work just as well.
 
I think this bit of code at the beginning of main() is going to make life difficult, if not impossible, even on a T4.1
Code:
    int sample_rate = 12000;
    int num_samples = 15 * sample_rate;
    float signal[num_samples];

That means that the signal array is 720kB.

Pete
 
Yea. That is going to be a really problem. But the thing is I don't actually get all the signal's samples at once. (From what I can tell.) I can FFT them as soon as I have enough samples in a buffer of sorts then over write the old samples.

Also I can do the "PROGMEM const" array for testing possibly.

(I would look at the original code for FT8 but Fortran is very confusing for me.)
 
Charley W5BAA has programmed Pocket_FT8 on Teensy 3.6 and Teensy 4.1.

It implements real-time decoding and coding FT8 signals for ham radio portable operation.

Have not tried it yet, I am still waiting for components to build one.

The code and building and operating manual is here:
https://groups.io/g/ucx/files/W5BAA_Pocket-FT8

I have put the files into a github repo to make those files easily accessible for me. Just to mention that I have not contributed code to the project. :)
https://github.com/DD4WH/Pocket_FT8
 
Back
Top