diff --git a/demod_2400.c b/demod_2400.c index 5fdefca..32cdb8a 100644 --- a/demod_2400.c +++ b/demod_2400.c @@ -19,6 +19,8 @@ #include "dump1090.h" +#include + // 2.4MHz sampling rate version // // When sampling at 2.4MHz we have exactly 6 samples per 5 symbols. @@ -389,6 +391,9 @@ void demodulate2400AC(struct mag_buf *mag) memset(&mm, 0, sizeof(mm)); + double noise_stddev = sqrt(mag->mean_power - mag->mean_level * mag->mean_level); // Var(X) = E[(X-E[X])^2] = E[X^2] - (E[X])^2 + unsigned noise_level = (unsigned) ((mag->mean_power + noise_stddev) * 65535 + 0.5); + for (f1_sample = 1; f1_sample < mlen; ++f1_sample) { // Mode A/C messages should match this bit sequence: @@ -414,10 +419,6 @@ void demodulate2400AC(struct mag_buf *mag) // 17 SPI // 18 0 quiet zone (X4) // 19 0 quiet zone (X5) - // 20 0 quiet zone (X6) - // 21 0 quiet zone (X7) - // 22 0 quiet zone (X8) - // 23 0 quiet zone (X9) // Look for a F1 and F2 pair, // with F1 starting at offset f1_sample. @@ -447,26 +448,26 @@ void demodulate2400AC(struct mag_buf *mag) if (m[f1_sample+2] > m[f1_sample+0] || m[f1_sample+2] > m[f1_sample+1]) continue; // quiet part of bit wasn't sufficiently quiet - unsigned f1_noise = (m[f1_sample-1] + m[f1_sample+2]) / 2; - unsigned f1_signal = (m[f1_sample+0] + m[f1_sample+1]) / 2; + unsigned f1_level = (m[f1_sample+0] + m[f1_sample+1]) / 2; - if (f1_noise * 4 > f1_signal) { - // require 12dB SNR + if (noise_level * 2 > f1_level) { + // require 6dB above noise continue; } // estimate initial clock phase based on the amount of power // that ended up in the second sample - unsigned f1_clock = 25 * f1_sample; - if (m[f1_sample+1] > f1_noise) { - f1_clock += 25 * (m[f1_sample+1] - f1_noise) / (2*(f1_signal - f1_noise)); - } + + float f1a_power = (float)m[f1_sample] * m[f1_sample]; + float f1b_power = (float)m[f1_sample+1] * m[f1_sample+1]; + float fraction = f1b_power / (f1a_power + f1b_power); + unsigned f1_clock = (unsigned) (25 * (f1_sample + fraction * fraction) + 0.5); // same again for F2 // F2 is 20.3us / 14 bit periods after F1 - unsigned f2_clock = f1_clock + (87 * 14); unsigned f2_sample = f2_clock / 25; + assert(f2_sample < mlen + Modes.trailing_samples); if (!(m[f2_sample-1] < m[f2_sample+0])) continue; @@ -474,174 +475,78 @@ void demodulate2400AC(struct mag_buf *mag) if (m[f2_sample+2] > m[f2_sample+0] || m[f2_sample+2] > m[f2_sample+1]) continue; // quiet part of bit wasn't sufficiently quiet - unsigned f2_noise = (m[f2_sample-1] + m[f2_sample+2]) / 2; - unsigned f2_signal = (m[f2_sample+0] + m[f2_sample+1]) / 2; + unsigned f2_level = (m[f2_sample+0] + m[f2_sample+1]) / 2; - if (f2_noise * 4 > f2_signal) { - // require 12dB SNR + if (noise_level * 2 > f2_level) { + // require 6dB above noise continue; } - unsigned f1f2_signal = (f1_signal + f2_signal) / 2; + unsigned f1f2_level = (f1_level > f2_level ? f1_level : f2_level); - // look at X1, X2, X3 which should be quiet - // (sample 0 may have part of the previous bit, but - // it always covers the quiet part of it) - unsigned x1_clock = f1_clock + (87 * 7); - unsigned x1_sample = x1_clock / 25; - unsigned x1_noise = (m[x1_sample + 0] + m[x1_sample + 1] + m[x1_sample + 2]) / 3; - if (x1_noise * 4 >= f1f2_signal) - continue; - - unsigned x2_clock = f1_clock + (87 * 15); - unsigned x2_sample = x2_clock / 25; - unsigned x2_noise = (m[x2_sample + 0] + m[x2_sample + 1] + m[x2_sample + 2]) / 3; - if (x2_noise * 4 >= f1f2_signal) - continue; - - unsigned x3_clock = f1_clock + (87 * 16); - unsigned x3_sample = x3_clock / 25; - unsigned x3_noise = (m[x3_sample + 0] + m[x3_sample + 1] + m[x3_sample + 2]) / 3; - if (x3_noise * 4 >= f1f2_signal) - continue; - - unsigned x1x2x3_noise = (x1_noise + x2_noise + x3_noise) / 3; - if (x1x2x3_noise * 4 >= f1f2_signal) // require 12dB separation - continue; - - // ----- F1/F2 average signal - // ^ - // | at least 3dB - // v - // ----- minimum signal level we accept as "on" - // ^ - // | 3dB - // v - // ---- midpoint between F1/F2 and X1/X2/X3 - // ^ - // | 3dB - // v - // ----- maximum signal level we accept as "off" - // ^ - // | at least 3dB - // v - // ----- X1/X2/X3 average noise - - float midpoint = sqrtf(x1x2x3_noise * f1f2_signal); // so that signal/midpoint == midpoint/noise - unsigned quiet_threshold = (unsigned) midpoint; - unsigned noise_threshold = (unsigned) (midpoint * 0.707107 + 0.5); // -3dB from midpoint - unsigned signal_threshold = (unsigned) (midpoint * 1.414214 + 0.5); // +3dB from midpoint - -#if 0 - fprintf(stderr, "f1f2 %u x1x2x3 %u midpoint %.0f noise_threshold %u signal_threshold %u\n", - f1f2_signal, x1x2x3_noise, midpoint, noise_threshold, signal_threshold); - - fprintf(stderr, "f1 %u f2 %u x1 %u x2 %u x3 %u\n", - f1_signal, f2_signal, x1_noise, x2_noise, x3_noise); -#endif - - // recheck F/X bits just in case - if (f1_signal < signal_threshold) - continue; - if (f2_signal < signal_threshold) - continue; - if (x1_noise > noise_threshold) - continue; - if (x2_noise > noise_threshold) - continue; - if (x3_noise > noise_threshold) - continue; + float midpoint = sqrtf(noise_level * f1f2_level); // geometric mean of the two levels + unsigned signal_threshold = (unsigned) (midpoint * M_SQRT2 + 0.5); // +3dB + unsigned noise_threshold = (unsigned) (midpoint / M_SQRT2 + 0.5); // -3dB // Looks like a real signal. Demodulate all the bits. + unsigned uncertain_bits = 0; unsigned noisy_bits = 0; unsigned bits = 0; unsigned bit; unsigned clock; - for (bit = 0, clock = f1_clock; bit < 24; ++bit, clock += 87) { + for (bit = 0, clock = f1_clock; bit < 20; ++bit, clock += 87) { unsigned sample = clock / 25; bits <<= 1; noisy_bits <<= 1; + uncertain_bits <<= 1; // check for excessive noise in the quiet period - if (m[sample+2] >= quiet_threshold) { - //fprintf(stderr, "bit %u was not quiet (%u > %u)\n", bit, m[sample+2], quiet_threshold); + if (m[sample+2] >= signal_threshold) { noisy_bits |= 1; - continue; } // decide if this bit is on or off - unsigned bit_signal = (m[sample+0] + m[sample+1]) / 2; - if (bit_signal >= signal_threshold) { + if (m[sample+0] >= signal_threshold || m[sample+1] >= signal_threshold) { bits |= 1; - } else if (bit_signal > noise_threshold) { + } else if (m[sample+0] > noise_threshold && m[sample+1] > noise_threshold) { /* not certain about this bit */ - //fprintf(stderr, "bit %u was uncertain (%u < %u < %u)\n", bit, noise_threshold, bit_signal, signal_threshold); - noisy_bits |= 1; + uncertain_bits |= 1; } else { /* this bit is off */ } } -#if 0 - fprintf(stderr, "bits: %06X noisy: %06X\n", bits, noisy_bits); - - unsigned j, sample; - static const char *names[24] = { - "F1", "C1", "A1", "C2", - "A2", "C4", "A4", "X1", - "B1", "D1", "B2", "D2", - "B4", "D4", "F2", "X2", - "X3", "SPI", "X4", "X5", - "X6", "X7", "X8", "X9" - }; - - fprintf(stderr, "-1 ... %6u\n", m[f1_sample-1]); - for (j = 0; j < 24; ++j) { - clock = f1_clock + 87 * j; - sample = clock / 25; - fprintf(stderr, "%2u %-3s %6u %6u %6u %6u ", j, names[j], m[sample+0], m[sample+1], m[sample+2], m[sample+3]); - if ((m[sample+0] + m[sample+1])/2 >= signal_threshold) { - fprintf(stderr, "ON\n"); - } else if ((m[sample+0] + m[sample+1])/2 <= noise_threshold) { - fprintf(stderr, "OFF\n"); - } else { - fprintf(stderr, "UNCERTAIN\n"); - } - } -#endif - - if (noisy_bits) { - /* XX debug */ - continue; - } - // framing bits must be on - if ((bits & 0x800200) != 0x800200) { + if ((bits & 0x80020) != 0x80020) { continue; } // quiet bits must be off - if ((bits & 0x0101BF) != 0) { + if ((bits & 0x0101B) != 0) { + continue; + } + + if (noisy_bits || uncertain_bits) { continue; } // Convert to the form that we use elsewhere: // 00 A4 A2 A1 00 B4 B2 B1 SPI C4 C2 C1 00 D4 D2 D1 unsigned modeac = - ((bits & 0x400000) ? 0x0010 : 0) | // C1 - ((bits & 0x200000) ? 0x1000 : 0) | // A1 - ((bits & 0x100000) ? 0x0020 : 0) | // C2 - ((bits & 0x080000) ? 0x2000 : 0) | // A2 - ((bits & 0x040000) ? 0x0040 : 0) | // C4 - ((bits & 0x020000) ? 0x4000 : 0) | // A4 - ((bits & 0x008000) ? 0x0100 : 0) | // B1 - ((bits & 0x004000) ? 0x0001 : 0) | // D1 - ((bits & 0x002000) ? 0x0200 : 0) | // B2 - ((bits & 0x001000) ? 0x0002 : 0) | // D2 - ((bits & 0x000800) ? 0x0400 : 0) | // B4 - ((bits & 0x000400) ? 0x0004 : 0) | // D4 - ((bits & 0x000040) ? 0x0080 : 0); // SPI + ((bits & 0x40000) ? 0x0010 : 0) | // C1 + ((bits & 0x20000) ? 0x1000 : 0) | // A1 + ((bits & 0x10000) ? 0x0020 : 0) | // C2 + ((bits & 0x08000) ? 0x2000 : 0) | // A2 + ((bits & 0x04000) ? 0x0040 : 0) | // C4 + ((bits & 0x02000) ? 0x4000 : 0) | // A4 + ((bits & 0x00800) ? 0x0100 : 0) | // B1 + ((bits & 0x00400) ? 0x0001 : 0) | // D1 + ((bits & 0x00200) ? 0x0200 : 0) | // B2 + ((bits & 0x00100) ? 0x0002 : 0) | // D2 + ((bits & 0x00080) ? 0x0400 : 0) | // B4 + ((bits & 0x00040) ? 0x0004 : 0) | // D4 + ((bits & 0x00004) ? 0x0080 : 0); // SPI // This message looks good, submit it @@ -656,7 +561,7 @@ void demodulate2400AC(struct mag_buf *mag) // Pass data to the next layer useModesMessage(&mm); - f1_sample += (24*87 / 25); + f1_sample += (20*87 / 25); Modes.stats_current.demod_modeac++; } }