# FSK analysis: only ever find one frequency

I've trying to write this software as part of my amateur radio and SDR hobby for analyzing various two-level FSK signals. I'm very new to DSP but have been having a lot of fun so far learning more about this subject. My long-term idea is to try and automatically detect the mark and space frequencies, as well as the baud rate, in arbitrary signals (maybe this is incredibly naive -- I don't know).

Right now I'm trying to get this software working using a known signal, known mark and space frequencies, and known baud rate. I've tested it with samples from sources like the Emergency Alert System, Bell 103, and even a pure $2600\textrm{ Hz}$ sine wave just to make sure that my frequency detection algorithm (very basic zero-crossing detection) works correctly.

I get back a $2600\textrm{ Hz}$ frequency when I test against the pure $2600\textrm{ Hz}$ sine wave sample so I'm at least somewhat confident about my ability to detect one particular frequency. However, I can never extract the mark and space frequencies when I use two-level FSK samples.

What I'm using right now is a sliding window that starts at the beginning of a sample and moves along the sample, changing both the starting position of the window and the overall length of the window, in an effort to try and find a good fit. But no matter what, I never see the mark or space frequency (actually, sometimes I will get a somewhat near read on one of the two frequencies but never both).

The project is pretty small if you want to have a look for yourself and give me some pointers (no pun intended). Apologies for the amount of code in the Cli project right now. I've put the code that I'm pretty confident about into their own classes and behind interfaces but my "work-in-progress" code is currently just living in the Main() method of the command-line interface.

Here is my current "window algorithm" in a nutshell:

1. Start with window positioned at $0\textrm{ ms}$ into the sample
2. Start with window length of a fairly minimal value
3. Count zero crossings across the current window to determine the frequency of the signal in that window
4. Output various information about the window and the frequency it contains
5. Increase the window length and repeat until the window length hits a maximum (maybe $1-10\textrm{ ms}$ in $0.25-1.0\textrm{ ms}$ increments -- all easily configured)
6. Once the maximum window length is reached, reset to the minimum window length, increment the window position a little, and repeat the varying window length frequency samples again
7. Repeat this until the maximum window position is reached

And here is a screenshot of the software running, where it was able to accurately detect one of the two FSK frequencies but not the other:

EDIT 1: Turns out I had a bad sample. When I looked at a frequency spectrum plot I only saw one frequency peak, whereas a 2-level FSK spectrum should have two peaks. I found another sample and now my window algorithm is working much better.

EDIT 2: Still using the same algorithm but now with the new sample and a few very minor tweaks to the software am successfully decoding at least the first non-trivial amount of this NWR/NOAA SAME signal. You can very clearly see the 1010 1011 preamble repeating at the beginning.

EDIT 3: Refactored a lot of the code and cleaned-up the Cli project so that it is actually just a Command-Line Interface.

• How do you handle transitions of symbols (from one frequency to the next) using this approach? – Dan Boschen Jun 13 '16 at 17:34
• I was thinking that the frequency during a transition would be clearly outside of the tolerable deviation from the two FSK frequencies and so I would just reject it and advance the window again. – Dan Jun 13 '16 at 17:35
• A zero crossing detector is very sensitive to noise (you may have multiple zeros crossings and not just one at your true crossings). In addition the analog channel that the signal passes through could also cause artifacts at the transition between symbols (change from one frequency to the next) that would affect the robustness of your approach. That said, if you want to make this work in minimum noise conditions with ideal (Wideband, no multipath and minimum distortion channels) then you can add hysteresis to your crossing detectors and validate your algorithm with both tones alone. – Dan Boschen Jun 13 '16 at 17:41
• My lunch break is over but hope this was helpful! – Dan Boschen Jun 13 '16 at 17:44
• Okay, that makes sense. I think I'd still like to get this approach working (with ideal signals) and then upgrade to more real world signals and be motivated to change to a more robust approach. I'm 99% sure I can pick up either tone alone (I've analyzed several pure sinusoidal signals (1,000 Hz, 2,000 Hz, 2,600 Hz, etc) and was able to recover the frequency perfectly. Everything seems to fall apart when I use a real FSK signal though... – Dan Jun 13 '16 at 17:45