0
$\begingroup$

This question is a sequel of the discussion that started in this question. Dan Boschen suggested some very nice solutions to decode a Bell 103 FSK signal. I am especially interested in decoding the 300bps signals with a C program running on a microcontroller. Unfortunately, the real input shows some deviations I cannot yet explain, which complicate everything. Andy Walls has indicated that it is Carrier Frequency Offset (CFO). Hence this post.

The real input signal

signal = [-2654, -7612, -3886, 7878, 11615, 3576, -7827, -8718, 2024, 10608, 7037, -4689, -10767, -3449, 7954, 9506, -268, -10213, -7943, 3860, 10379, 4329, -7315, -10597, -993, 9291, 8319, -1073, -8453, -9421, -3838, 4587, 9746, 8721, 2079, -6025, -10183, -7285, 543, 7892, 9928, 5577, -2463, -9105, -9553, -3460, 4873, 9778, 8289, 1465, -6545, -10267, -6913, 1409, 9233, 9670, 1549, -7870, -10014, -2476, 7280, 10301, 4253, -5740, -10644, -5449, 4735, 10329, 6648, -3054, -10283, -7899, 1853, 9598, 8580, -116, -9005, -9653, -1175, 8088, 9893, 4392, -3651, -9721, -9107, -2347, 5821, 9970, 7589, 329, -7404, -10201, -5967, 2302, 8859, 9547, 4147, -4083, -9749, -8730, -1712, 6344, 10047, 7267, -227, -7833, -10173, -4173, 5971, 10306, 5370, -4504, -10636, -6707, 3355, 10120, 7727, -1563, -9704, -8781, 437, 9021, 9372, 1417, -8025, -10149, -2603, 7177, 10249, 4220, -5744, -10668, -5861, 3143, 9068, 8965, 2886, -5287, -10183, -8154, -627, 7100, 9972, 6363, -1451, -8575, -9938, -4485, 3901, 9493, 8821, 2499, -5667, -10182, -7705, 6, 7571, 9986, 5825, -2953, -10279, -8524, 1050, 9229, 8920, 568, -8609, -9954, -1889, 7670, 10083, 3544, -6378, -10624, -4769, 5398, 10408, 6134, -3699, -10422, -7309, 2637, 9894, 8222, -642, -8674, -9449, -3731, 4583, 9831, 8655, 2073, -6095, -10210, -7331, 538, 7869, 9865, 5497, -2561, -9185, -9618, -3499, 4834, 9739, 8214, 1379, -6616, -10322, -6953, 1080, 8409, 9903, 3054, -6925, -10372, -4007, 6091, 10442, 5543, -4415, -10569, -6726, 3321, 10072, 7715, -1583, -9742, -8847, 336, 8928, 9332, 1383, -8081, -10213, -2681, 7110, 10289, 4978, -3519, -9480, -9000, -2202, 5933, 10045, 7614, 315, -7409, -10204, -5942, 2302, 8857, 9509, 4089, -4137, -9793, -8746, -1724, 6328, 10021, 7222, -275, -7838, -10123, -4857, 4825, 10468, 6696, -2987, -10231, -7801, 1940, 9661, 8653, -69, -8957, -9569, -1109, 8162, 9911, 2851, -6971, -10531, -4089, 5999, 10393, 5513, -4426, -10578, -6787, 2807, 9047, 8738, 2828, -5427, -10221, -8193, -622, 7121, 9974, 6362, -1471, -8559, -9908, -4432, 3953, 9537, 8864, 2520, -5641, -10149, -7648, 56, 7589, 9994, 5989, -2088, -9526, -9544, -573, 8418, 9480, 2021, -7641, -10408, -3409, 6581, 10342, 4891, -5077, -10617, -6097, 4070, 10274, 7276, -2246, -9966, -8345, 1145, 9352, 9059, 713, -8506, -10084, -3341, 4988, 9829, 8253, 1308, -6650, -10324, -6863, 1158, 8236, 9730, 4961, -3183, -9470, -9348, -2856, 5407, 9862, 7865, 757, -7108, -10304, -6431, 1743, 8569, 9581, 3392, -6440, -10648, -4769, 5371, 10406, 6074, -3750, -10452, -7322, 2604, 9869, 8181, -838, -9383, -9254, -389, 8576, 9648, 2108, -7540, -10389, -3403, 6571, 10352, 5141, -3853, -9537, -8504, -1471, 6542, 10119, 7243, -323, -7846, -10123, -5404, 2918, 9108, 9246, 3457, -4768, -10013, -8423, -1103, 6785, 10003, 6737, -959, -8269, -10056, -4821, 4225, 10333, 7837, -1482, -9649];

The signal consists of a repeating 101010 pattern, with a total of 427 samples. The samples are obtained at PCM Fs = 8 kHz, which has been verified by use of a logic analyzer. The resulting frequency spectrum is shown below. It deviates from the expected 1070 and 1270 Hz. In particular, the big lobe at 1170 Hz exactly in between the two expected frequencies, and the two smaller side lobes.

Real input signal consisting of FSK encoded repeating 10 pattern

Unfortunately I do not have an oscilloscope available to verify the 1070 and 1270 Hz signals are actually there. I am hoping to have one tomorrow, or Monday. However, the hardware generating the real signal is Bell 103 compliant and has not had problems in previous tests (although those were some time ago).

$\endgroup$
1
  • $\begingroup$ The spectrum here results from the 150 Hz square wave (alternating symbols at 300 baud) that you've FM modulated. The main peak is the center frequency and the side peaks are each 150 Hz away from the central peak. This spectrum is pathological for this FSK. To see the general spectrum for this FSK, you have to perform spectrum analysis on a long, random stream of symbols. $\endgroup$
    – Andy Walls
    May 14, 2020 at 14:20

1 Answer 1

0
$\begingroup$

You actually haven't written a question here.

However, processing the signal samples you provided, I don't see CFO

enter image description here

I do see that the first symbol is way off frequency.

The Octave code that generated this picture is

% Octave requires an explcit load of the signal processing packasge, once.
pkg load signal

Fs = 8000; % sample rate
f1 = 1070;
f2 = 1270;

% Given input signal
x = [-2654, -7612, -3886, 7878, 11615, 3576, -7827, -8718, 2024, 10608, 7037, -4689, -10767, -3449, 7954, 9506, -268, -10213, -7943, 3860, 10379, 4329, -7315, -10597, -993, 9291, 8319, -1073, -8453, -9421, -3838, 4587, 9746, 8721, 2079, -6025, -10183, -7285, 543, 7892, 9928, 5577, -2463, -9105, -9553, -3460, 4873, 9778, 8289, 1465, -6545, -10267, -6913, 1409, 9233, 9670, 1549, -7870, -10014, -2476, 7280, 10301, 4253, -5740, -10644, -5449, 4735, 10329, 6648, -3054, -10283, -7899, 1853, 9598, 8580, -116, -9005, -9653, -1175, 8088, 9893, 4392, -3651, -9721, -9107, -2347, 5821, 9970, 7589, 329, -7404, -10201, -5967, 2302, 8859, 9547, 4147, -4083, -9749, -8730, -1712, 6344, 10047, 7267, -227, -7833, -10173, -4173, 5971, 10306, 5370, -4504, -10636, -6707, 3355, 10120, 7727, -1563, -9704, -8781, 437, 9021, 9372, 1417, -8025, -10149, -2603, 7177, 10249, 4220, -5744, -10668, -5861, 3143, 9068, 8965, 2886, -5287, -10183, -8154, -627, 7100, 9972, 6363, -1451, -8575, -9938, -4485, 3901, 9493, 8821, 2499, -5667, -10182, -7705, 6, 7571, 9986, 5825, -2953, -10279, -8524, 1050, 9229, 8920, 568, -8609, -9954, -1889, 7670, 10083, 3544, -6378, -10624, -4769, 5398, 10408, 6134, -3699, -10422, -7309, 2637, 9894, 8222, -642, -8674, -9449, -3731, 4583, 9831, 8655, 2073, -6095, -10210, -7331, 538, 7869, 9865, 5497, -2561, -9185, -9618, -3499, 4834, 9739, 8214, 1379, -6616, -10322, -6953, 1080, 8409, 9903, 3054, -6925, -10372, -4007, 6091, 10442, 5543, -4415, -10569, -6726, 3321, 10072, 7715, -1583, -9742, -8847, 336, 8928, 9332, 1383, -8081, -10213, -2681, 7110, 10289, 4978, -3519, -9480, -9000, -2202, 5933, 10045, 7614, 315, -7409, -10204, -5942, 2302, 8857, 9509, 4089, -4137, -9793, -8746, -1724, 6328, 10021, 7222, -275, -7838, -10123, -4857, 4825, 10468, 6696, -2987, -10231, -7801, 1940, 9661, 8653, -69, -8957, -9569, -1109, 8162, 9911, 2851, -6971, -10531, -4089, 5999, 10393, 5513, -4426, -10578, -6787, 2807, 9047, 8738, 2828, -5427, -10221, -8193, -622, 7121, 9974, 6362, -1471, -8559, -9908, -4432, 3953, 9537, 8864, 2520, -5641, -10149, -7648, 56, 7589, 9994, 5989, -2088, -9526, -9544, -573, 8418, 9480, 2021, -7641, -10408, -3409, 6581, 10342, 4891, -5077, -10617, -6097, 4070, 10274, 7276, -2246, -9966, -8345, 1145, 9352, 9059, 713, -8506, -10084, -3341, 4988, 9829, 8253, 1308, -6650, -10324, -6863, 1158, 8236, 9730, 4961, -3183, -9470, -9348, -2856, 5407, 9862, 7865, 757, -7108, -10304, -6431, 1743, 8569, 9581, 3392, -6440, -10648, -4769, 5371, 10406, 6074, -3750, -10452, -7322, 2604, 9869, 8181, -838, -9383, -9254, -389, 8576, 9648, 2108, -7540, -10389, -3403, 6571, 10352, 5141, -3853, -9537, -8504, -1471, 6542, 10119, 7243, -323, -7846, -10123, -5404, 2918, 9108, 9246, 3457, -4768, -10013, -8423, -1103, 6785, 10003, 6737, -959, -8269, -10056, -4821, 4225, 10333, 7837, -1482, -9649];

% Scale to between +/- 1.0 to avoid ridiculously large numbers on plots
xs = x/max(abs(x));

% Run through a Hilbert filter to make the signal analytic
xsc = hilbert(xs);

% FM demodulate using an approximate d(phi)/dt
y = arg(xsc(2:end) .* conj(xsc(1:(end-1))));
ys = y * (Fs/2)/pi;

% Plot the output of the FM discrimator
t = [1:length(ys)]/Fs;
f1line = ones(1, length(t))*f1;
f2line = ones(1, length(t))*f2;
plot(t, ys, t, f1line, t, f2line);
ylim([f1-300 f2+300]);
title('FM Discriminator Output');
xlabel('Time (seconds)');
ylabel('Frequency (Hz)');

By the way, the Octave/MatLab 'hilbert' implementation does a terrible thing - it zeros FFT bins to perform filtering - which should never be done in a real life, streaming Hilbert filter implementation. Oppenheim and Schafer have a section in their textbook regarding practical Hilbert filters.

$\endgroup$
2
  • $\begingroup$ Thank you Andy, I have also downloaded Octave and I can see it is a nice tool. I am not familiar with the Hilbert transform but it seems to make analyzing the data a lot less of a hassle. Unfortunately, this doesn't explain to me why the filter in the other post is not working, but it does resolve this post. Thanks! $\endgroup$ May 14, 2020 at 13:11
  • $\begingroup$ Be advised the Hilbert Transform is only one half of the output of a Hilbert filter. The Hilbert Filter output gives you the real and imaginary parts of the signal. The Hilbert transform only gives you the imaginary part. The Hilbert filter is easier to compute anyway: take a real signal and filter out the negative half of its frequency spectrum. $\endgroup$
    – Andy Walls
    May 14, 2020 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.