From dae6abf009d6aee7d4fed055d9afb4443e473354 Mon Sep 17 00:00:00 2001 From: gvanem Date: Fri, 20 Dec 2024 08:50:03 +0100 Subject: [PATCH] Moved 2 MS/s demodulator code to a new file 'demod-2000.c'. --- src/Dump1090.vcxproj | 2 + src/Makefile.Windows | 3 +- src/demod-2000.c | 332 ++++++++++++++++++++++++++++++++++++++++ src/demod-2000.h | 12 ++ src/dump1090.c | 352 ++----------------------------------------- src/misc.h | 15 +- 6 files changed, 373 insertions(+), 343 deletions(-) create mode 100644 src/demod-2000.c create mode 100644 src/demod-2000.h diff --git a/src/Dump1090.vcxproj b/src/Dump1090.vcxproj index ddbcbad..1196c16 100644 --- a/src/Dump1090.vcxproj +++ b/src/Dump1090.vcxproj @@ -152,6 +152,7 @@ + @@ -175,6 +176,7 @@ + diff --git a/src/Makefile.Windows b/src/Makefile.Windows index 64b7cfd..cb27c2d 100644 --- a/src/Makefile.Windows +++ b/src/Makefile.Windows @@ -306,6 +306,7 @@ SOURCES = aircraft.c \ airports.c \ cfg_file.c \ csv.c \ + demod-2000.c \ dump1090.c \ interactive.c \ misc.c \ @@ -372,7 +373,7 @@ endif ifeq ($(USE_READSB_DEMOD),1) CFLAGS += -DUSE_READSB_DEMOD - SOURCES += externals/demod_2400.c + SOURCES += externals/demod-2400.c endif OBJECTS = $(call c_to_obj, $(SOURCES)) diff --git a/src/demod-2000.c b/src/demod-2000.c new file mode 100644 index 0000000..5ccf972 --- /dev/null +++ b/src/demod-2000.c @@ -0,0 +1,332 @@ +/**\file demod-2000.c + * \ingroup Samplers + * \brief Demodulator for 2 MS/s decoding + */ +#include "misc.h" +#include "demod-2000.h" + +/** + * Detect a Mode S messages inside the magnitude buffer pointed by `m` + * and of size `mlen` bytes. Every detected Mode S message is converted + * into a stream of bits and passed to the function to display it. + * + * In the outer loop to find the preamble and a data-frame: + * `mlen == 131310` bits, but `j == [0 .. mlen - (2*120)]`. + * Hence `j == [0 .. 131070]`. + * + * In the inner loop to extract the bits in a frame: + * index `i == [0 .. 2*112]`. + * + * \todo Use the pulse_slicer_ppm() function from the RTL-433 project. + * \ref https://github.com/merbanan/rtl_433/blob/master/src/pulse_slicer.c#L259 + */ +uint32_t demodulate_2000 (uint16_t *m, uint32_t mlen) +{ + uint8_t bits [MODES_LONG_MSG_BITS]; + uint8_t msg [MODES_LONG_MSG_BITS / 2]; + uint16_t aux [MODES_LONG_MSG_BITS * 2]; + uint32_t j; + uint32_t frame = 0; + bool use_correction = false; + uint32_t rc = 0; /**\todo fix this */ + + /** + * The Mode S preamble is made of pulses of 0.5 microseconds + * at the following time offsets: + * + * 0 - 0.5 usec: first pulse. + * 1.0 - 1.5 usec: second pulse. + * 3.5 - 4 usec: third pulse. + * 4.5 - 5 usec: last pulse. + * + * Like this (\ref ../docs/The-1090MHz-riddle.pdf, "1.4.2 Mode S replies"): + * ``` + * < ----------- 8 usec / 16 bits ---------> < ---- data -- ... > + * __ __ __ __ + * | | | | | | | | + * | |_| |________| |_| |__________________ .... + * + * ----|----|----|----|----|----|----|----| + * 10 10 00 01 01 00 00 00 + * j: 0 1 2 3 4 5 6 7 8 9 10 ... + * ``` + * + * If we are sampling at 2 MHz, every sample in our magnitude vector + * is 0.5 usec. So the preamble will look like this, assuming there is + * an pulse at offset 0 in the array: + * + * ``` + * 0 ----------------- + * 1 - + * 2 ------------------ + * 3 -- + * 4 - + * 5 -- + * 6 - + * 7 ------------------ + * 8 -- + * 9 ------------------- + * ``` + */ + for (j = 0; j < mlen - 2*MODES_FULL_LEN; j++) + { + int low, high, delta, i, errors; + bool good_message = false; + + if (Modes.exit) + break; + + if (use_correction) + goto good_preamble; /* We already checked it. */ + + /* First check of relations between the first 10 samples + * representing a valid preamble. We don't even investigate further + * if this simple test is not passed. + */ + if (!(m[j] > m[j+1] && + m[j+1] < m[j+2] && + m[j+2] > m[j+3] && + m[j+3] < m[j] && + m[j+4] < m[j] && + m[j+5] < m[j] && + m[j+6] < m[j] && + m[j+7] > m[j+8] && + m[j+8] < m[j+9] && + m[j+9] > m[j+6])) + { + if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) + dump_raw_message ("Unexpected ratio among first 10 samples", msg, m, j, frame); + + if (Modes.max_frames > 0 && ++frame > Modes.max_frames) + return (rc); + continue; + } + + /* The samples between the two spikes must be lower than the average + * of the high spikes level. We don't test bits too near to + * the high levels as signals can be out of phase so part of the + * energy can be in the near samples. + */ + high = (m[j] + m[j+2] + m[j+7] + m[j+9]) / 6; + if (m[j+4] >= high || m[j+5] >= high) + { + if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) + dump_raw_message ("Too high level in samples between 3 and 6", msg, m, j, frame); + + if (Modes.max_frames > 0 && ++frame > Modes.max_frames) + return (rc); + continue; + } + + /* Similarly samples in the range 11-14 must be low, as it is the + * space between the preamble and real data. Again we don't test + * bits too near to high levels, see above. + */ + if (m[j+11] >= high || m[j+12] >= high || m[j+13] >= high || m[j+14] >= high) + { + if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) + dump_raw_message ("Too high level in samples between 10 and 15", msg, m, j, frame); + + if (Modes.max_frames > 0 && ++frame > Modes.max_frames) + return (rc); + continue; + } + + Modes.stat.valid_preamble++; + +good_preamble: + + /* If the previous attempt with this message failed, retry using + * magnitude correction. + */ + if (use_correction) + { + memcpy (aux, m + j + MODES_PREAMBLE_US * 2, sizeof(aux)); + if (j && detect_out_of_phase(m + j)) + { + apply_phase_correction (m + j); + Modes.stat.out_of_phase++; + } + /** \todo Apply other kind of corrections. */ + } + + /* Decode all the next 112 bits, regardless of the actual message + * size. We'll check the actual message type later. + */ + errors = 0; + for (i = 0; i < 2 * MODES_LONG_MSG_BITS; i += 2) + { + low = m [j + i + 2*MODES_PREAMBLE_US]; + high = m [j + i + 2*MODES_PREAMBLE_US + 1]; + delta = low - high; + if (delta < 0) + delta = -delta; + + if (i > 0 && delta < 256) + bits [i/2] = bits [i/2-1]; + + else if (low == high) + { + /* Checking if two adjacent samples have the same magnitude + * is an effective way to detect if it's just random noise + * that was detected as a valid preamble. + */ + bits [i/2] = 2; /* error */ + if (i < 2*MODES_SHORT_MSG_BITS) + errors++; + } + else if (low > high) + { + bits [i/2] = 1; + } + else + { + /* (low < high) for exclusion + */ + bits [i/2] = 0; + } + } + + /* Restore the original message if we used magnitude correction. + */ + if (use_correction) + memcpy (m + j + 2*MODES_PREAMBLE_US, aux, sizeof(aux)); + + /* Pack bits into bytes + */ + for (i = 0; i < MODES_LONG_MSG_BITS; i += 8) + { + msg [i/8] = bits [i] << 7 | + bits [i+1] << 6 | + bits [i+2] << 5 | + bits [i+3] << 4 | + bits [i+4] << 3 | + bits [i+5] << 2 | + bits [i+6] << 1 | + bits [i+7]; + } + + int msg_type = msg[0] >> 3; + int msg_len = modeS_message_len_by_type (msg_type) / 8; + + /* Last check, high and low bits are different enough in magnitude + * to mark this as real message and not just noise? + */ + delta = 0; + for (i = 0; i < 8 * 2 * msg_len; i += 2) + { + delta += abs (m[j + i + 2 * MODES_PREAMBLE_US] - + m[j + i + 2 * MODES_PREAMBLE_US + 1]); + } + delta /= 4 * msg_len; + + /* Filter for an average delta of three is small enough to let almost + * every kind of message to pass, but high enough to filter some + * random noise. + */ + if (delta < 10*255) + { + use_correction = false; + continue; + } + + /* If we reached this point, and error is zero, we are very likely + * with a Mode S message in our hands, but it may still be broken + * and CRC may not be correct. This is handled by the next layer. + */ + if (errors == 0 || (Modes.error_correct_2 && errors <= 2)) + { + modeS_message mm; + double signal_power = 0.0; + int signal_len = mlen; + uint32_t k, mag; + + /* Decode the received message and update statistics + */ + rc += decode_modeS_message (&mm, msg); + + /* measure signal power + */ + for (k = j; k < j + MODES_FULL_LEN; k++) + { + mag = m [k]; + signal_power += mag * mag; + } + mm.sig_level = signal_power / (65536.0 * signal_len); + + /* Update statistics. + */ + if (mm.CRC_ok || use_correction) + { + if (errors == 0) + Modes.stat.demodulated++; + if (mm.error_bit == -1) + { + if (mm.CRC_ok) + Modes.stat.good_CRC++; + else Modes.stat.bad_CRC++; + } + else + { + Modes.stat.bad_CRC++; + Modes.stat.fixed++; +#if 0 + if (mm.error_bit < MODES_LONG_MSG_BITS) + Modes.stat.single_bit_fix++; + else Modes.stat.two_bits_fix++; +#endif + } + } + + /* Output debug mode info if needed. + */ + if (!use_correction) + { + if (Modes.debug & DEBUG_DEMOD) + dump_raw_message ("Demodulated with 0 errors", msg, m, j, frame); + + else if ((Modes.debug & DEBUG_BADCRC) && mm.msg_type == 17 && (!mm.CRC_ok || mm.error_bit != -1)) + dump_raw_message ("Decoded with bad CRC", msg, m, j, frame); + + else if ((Modes.debug & DEBUG_GOODCRC) && mm.CRC_ok && mm.error_bit == -1) + dump_raw_message ("Decoded with good CRC", msg, m, j, frame); + } + + /* Skip this message if we are sure it's fine. + */ + if (mm.CRC_ok) + { + j += 2 * (MODES_PREAMBLE_US + (8 * msg_len)); + good_message = true; + if (use_correction) + mm.phase_corrected = true; + } + + /* Pass data to the next layer + */ + if (mm.CRC_ok) + modeS_user_message (&mm); + } + else + { + if ((Modes.debug & DEBUG_DEMODERR) && use_correction) + { + LOG_STDOUT ("The following message has %d demod errors:", errors); + dump_raw_message ("Demodulated with errors", msg, m, j, frame); + } + } + + /* Retry with phase correction if possible. + */ + if (!good_message && !use_correction) + { + j--; + use_correction = true; + } + else + { + use_correction = false; + } + } + return (rc); +} diff --git a/src/demod-2000.h b/src/demod-2000.h new file mode 100644 index 0000000..8d22a09 --- /dev/null +++ b/src/demod-2000.h @@ -0,0 +1,12 @@ +/**\file demod-2000.h + * \ingroup Samplers + * \brief Demodulator for 2 MS/s decoding + */ +#ifndef DEMOD_2000_H +#define DEMOD_2000_H + +#include + +uint32_t demodulate_2000 (uint16_t *m, uint32_t mlen); + +#endif diff --git a/src/dump1090.c b/src/dump1090.c index cca70e6..0f7030f 100644 --- a/src/dump1090.c +++ b/src/dump1090.c @@ -22,6 +22,7 @@ #include "misc.h" #include "net_io.h" #include "cfg_file.h" +#include "demod-2000.h" #include "sdrplay.h" #include "speech.h" #include "location.h" @@ -86,7 +87,7 @@ global_data Modes; */ static void modeS_send_raw_output (const modeS_message *mm); static void modeS_send_SBS_output (const modeS_message *mm, const aircraft *a); -static void modeS_user_message (const modeS_message *mm); + void modeS_user_message (const modeS_message *mm); static bool set_bandwidth (const char *arg); static bool set_bias_tee (const char *arg); @@ -114,8 +115,6 @@ static bool set_web_page (const char *arg); static int fix_single_bit_errors (uint8_t *msg, int bits); static int fix_two_bits_errors (uint8_t *msg, int bits); -static uint32_t detect_modeS (uint16_t *m, uint32_t mlen); -static int modeS_message_len_by_type (int type); static uint16_t *compute_magnitude_vector (const uint8_t *data); static void background_tasks (void); static void modeS_exit (void); @@ -711,7 +710,7 @@ static bool modeS_init_RTLSDR (void) * This RX-data callback gets data from the local RTLSDR, a remote RTLSDR * device or a local SDRplay device asynchronously. * We then populate the data buffer for "Pulse Position Modulation" decoding in - * `detect_modeS()`. + * `demodulate_2000()`. * * \note A Mutex is used to avoid race-condition with the decoding thread. * \node "Mode S" is "Mode Select Beacon System" (\ref "docs/The-1090MHz-riddle.pdf" chapter 1.4.) @@ -803,7 +802,7 @@ static int infile_read (void) } compute_magnitude_vector (Modes.data); - rc += detect_modeS (Modes.magnitude, Modes.data_len/2); + rc += demodulate_2000 (Modes.magnitude, Modes.data_len/2); background_tasks(); if (Modes.exit || Modes.infile_fd == STDIN_FILENO) @@ -898,7 +897,7 @@ static void main_data_loop (void) } else #endif - detect_modeS (Modes.magnitude, Modes.data_len/2); + demodulate_2000 (Modes.magnitude, Modes.data_len/2); LeaveCriticalSection (&Modes.data_mutex); @@ -1031,8 +1030,8 @@ static void dump_raw_message_JS (const char *descr, uint8_t *msg, const uint16_t * display packets in a graphical format if the Javascript output was * enabled. */ -static void dump_raw_message (const char *descr, uint8_t *msg, const uint16_t *m, - uint32_t offset, uint32_t frame) +void dump_raw_message (const char *descr, uint8_t *msg, const uint16_t *m, + uint32_t offset, uint32_t frame) { int j; int msg_type = msg[0] >> 3; @@ -1558,11 +1557,11 @@ static void decode_ES_surface_position (struct modeS_message *mm, bool check_imf } /** - * Decode a raw Mode S message demodulated as a stream of bytes by `detect_modeS()`. + * Decode a raw Mode S message demodulated as a stream of bytes by `demodulate_2000()`. * * And split it into fields populating a `modeS_message` structure. */ -static int decode_modeS_message (modeS_message *mm, const uint8_t *_msg) +int decode_modeS_message (modeS_message *mm, const uint8_t *_msg) { uint32_t CRC; /* Computed CRC, used to verify the message CRC. */ const char *AIS_charset = "?ABCDEFGHIJKLMNOPQRSTUVWXYZ????? ???????????????0123456789??????"; @@ -2097,7 +2096,7 @@ static uint16_t *compute_magnitude_vector (const uint8_t *data) * Note: this function will access m[-1], so the caller should make sure to * call it only if we are not at the start of the current buffer. */ -static int detect_out_of_phase (const uint16_t *m) +int detect_out_of_phase (const uint16_t *m) { if (m[3] > m[2]/3) return (1); @@ -2140,7 +2139,7 @@ static int detect_out_of_phase (const uint16_t *m) * In this way similar levels will be interpreted more likely in the * correct way. */ -static void apply_phase_correction (uint16_t *m) +void apply_phase_correction (uint16_t *m) { int j; @@ -2165,7 +2164,7 @@ static void apply_phase_correction (uint16_t *m) * Use a rewrite of the 'demodulate2400()' function from * https://github.com/wiedehopf/readsb.git */ -static uint32_t detect_modeS (uint16_t *m, uint32_t mlen) +uint32_t demodulate_2400 (uint16_t *m, uint32_t mlen) { struct mag_buf mag; uint32_t rc = 0; /**\todo fix this */ @@ -2176,333 +2175,6 @@ static uint32_t detect_modeS (uint16_t *m, uint32_t mlen) mag.sysTimestamp = MSEC_TIME(); demodulate2400 (&mag); } - -#else -/** - * Detect a Mode S messages inside the magnitude buffer pointed by `m` - * and of size `mlen` bytes. Every detected Mode S message is converted - * into a stream of bits and passed to the function to display it. - * - * In the outer loop to find the preamble and a data-frame: - * `mlen == 131310` bits, but `j == [0 .. mlen - (2*120)]`. - * Hence `j == [0 .. 131070]`. - * - * In the inner loop to extract the bits in a frame: - * index `i == [0 .. 2*112]`. - * - * \todo Use the pulse_slicer_ppm() function from the RTL-433 project. - * \ref https://github.com/merbanan/rtl_433/blob/master/src/pulse_slicer.c#L259 - */ -static uint32_t detect_modeS (uint16_t *m, uint32_t mlen) -{ - uint8_t bits [MODES_LONG_MSG_BITS]; - uint8_t msg [MODES_LONG_MSG_BITS / 2]; - uint16_t aux [MODES_LONG_MSG_BITS * 2]; - uint32_t j; - uint32_t frame = 0; - bool use_correction = false; - uint32_t rc = 0; /**\todo fix this */ - - /** - * The Mode S preamble is made of pulses of 0.5 microseconds - * at the following time offsets: - * - * 0 - 0.5 usec: first pulse. - * 1.0 - 1.5 usec: second pulse. - * 3.5 - 4 usec: third pulse. - * 4.5 - 5 usec: last pulse. - * - * Like this (\ref ../docs/The-1090MHz-riddle.pdf, "1.4.2 Mode S replies"): - * ``` - * < ----------- 8 usec / 16 bits ---------> < ---- data -- ... > - * __ __ __ __ - * | | | | | | | | - * | |_| |________| |_| |__________________ .... - * - * ----|----|----|----|----|----|----|----| - * 10 10 00 01 01 00 00 00 - * j: 0 1 2 3 4 5 6 7 8 9 10 ... - * ``` - * - * If we are sampling at 2 MHz, every sample in our magnitude vector - * is 0.5 usec. So the preamble will look like this, assuming there is - * an pulse at offset 0 in the array: - * - * ``` - * 0 ----------------- - * 1 - - * 2 ------------------ - * 3 -- - * 4 - - * 5 -- - * 6 - - * 7 ------------------ - * 8 -- - * 9 ------------------- - * ``` - */ - for (j = 0; j < mlen - 2*MODES_FULL_LEN; j++) - { - int low, high, delta, i, errors; - bool good_message = false; - - if (Modes.exit) - break; - - if (use_correction) - goto good_preamble; /* We already checked it. */ - - /* First check of relations between the first 10 samples - * representing a valid preamble. We don't even investigate further - * if this simple test is not passed. - */ - if (!(m[j] > m[j+1] && - m[j+1] < m[j+2] && - m[j+2] > m[j+3] && - m[j+3] < m[j] && - m[j+4] < m[j] && - m[j+5] < m[j] && - m[j+6] < m[j] && - m[j+7] > m[j+8] && - m[j+8] < m[j+9] && - m[j+9] > m[j+6])) - { - if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) - dump_raw_message ("Unexpected ratio among first 10 samples", msg, m, j, frame); - - if (Modes.max_frames > 0 && ++frame > Modes.max_frames) - return (rc); - continue; - } - - /* The samples between the two spikes must be lower than the average - * of the high spikes level. We don't test bits too near to - * the high levels as signals can be out of phase so part of the - * energy can be in the near samples. - */ - high = (m[j] + m[j+2] + m[j+7] + m[j+9]) / 6; - if (m[j+4] >= high || m[j+5] >= high) - { - if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) - dump_raw_message ("Too high level in samples between 3 and 6", msg, m, j, frame); - - if (Modes.max_frames > 0 && ++frame > Modes.max_frames) - return (rc); - continue; - } - - /* Similarly samples in the range 11-14 must be low, as it is the - * space between the preamble and real data. Again we don't test - * bits too near to high levels, see above. - */ - if (m[j+11] >= high || m[j+12] >= high || m[j+13] >= high || m[j+14] >= high) - { - if ((Modes.debug & DEBUG_NOPREAMBLE) && m[j] > DEBUG_NOPREAMBLE_LEVEL) - dump_raw_message ("Too high level in samples between 10 and 15", msg, m, j, frame); - - if (Modes.max_frames > 0 && ++frame > Modes.max_frames) - return (rc); - continue; - } - - Modes.stat.valid_preamble++; - -good_preamble: - - /* If the previous attempt with this message failed, retry using - * magnitude correction. - */ - if (use_correction) - { - memcpy (aux, m + j + MODES_PREAMBLE_US * 2, sizeof(aux)); - if (j && detect_out_of_phase(m + j)) - { - apply_phase_correction (m + j); - Modes.stat.out_of_phase++; - } - /** \todo Apply other kind of corrections. */ - } - - /* Decode all the next 112 bits, regardless of the actual message - * size. We'll check the actual message type later. - */ - errors = 0; - for (i = 0; i < 2 * MODES_LONG_MSG_BITS; i += 2) - { - low = m [j + i + 2*MODES_PREAMBLE_US]; - high = m [j + i + 2*MODES_PREAMBLE_US + 1]; - delta = low - high; - if (delta < 0) - delta = -delta; - - if (i > 0 && delta < 256) - bits [i/2] = bits [i/2-1]; - - else if (low == high) - { - /* Checking if two adjacent samples have the same magnitude - * is an effective way to detect if it's just random noise - * that was detected as a valid preamble. - */ - bits [i/2] = 2; /* error */ - if (i < 2*MODES_SHORT_MSG_BITS) - errors++; - } - else if (low > high) - { - bits [i/2] = 1; - } - else - { - /* (low < high) for exclusion - */ - bits [i/2] = 0; - } - } - - /* Restore the original message if we used magnitude correction. - */ - if (use_correction) - memcpy (m + j + 2*MODES_PREAMBLE_US, aux, sizeof(aux)); - - /* Pack bits into bytes - */ - for (i = 0; i < MODES_LONG_MSG_BITS; i += 8) - { - msg [i/8] = bits [i] << 7 | - bits [i+1] << 6 | - bits [i+2] << 5 | - bits [i+3] << 4 | - bits [i+4] << 3 | - bits [i+5] << 2 | - bits [i+6] << 1 | - bits [i+7]; - } - - int msg_type = msg[0] >> 3; - int msg_len = modeS_message_len_by_type (msg_type) / 8; - - /* Last check, high and low bits are different enough in magnitude - * to mark this as real message and not just noise? - */ - delta = 0; - for (i = 0; i < 8 * 2 * msg_len; i += 2) - { - delta += abs (m[j + i + 2 * MODES_PREAMBLE_US] - - m[j + i + 2 * MODES_PREAMBLE_US + 1]); - } - delta /= 4 * msg_len; - - /* Filter for an average delta of three is small enough to let almost - * every kind of message to pass, but high enough to filter some - * random noise. - */ - if (delta < 10*255) - { - use_correction = false; - continue; - } - - /* If we reached this point, and error is zero, we are very likely - * with a Mode S message in our hands, but it may still be broken - * and CRC may not be correct. This is handled by the next layer. - */ - if (errors == 0 || (Modes.error_correct_2 && errors <= 2)) - { - modeS_message mm; - double signal_power = 0.0; - int signal_len = mlen; - uint32_t k, mag; - - /* Decode the received message and update statistics - */ - rc += decode_modeS_message (&mm, msg); - - /* measure signal power - */ - for (k = j; k < j + MODES_FULL_LEN; k++) - { - mag = m [k]; - signal_power += mag * mag; - } - mm.sig_level = signal_power / (65536.0 * signal_len); - - /* Update statistics. - */ - if (mm.CRC_ok || use_correction) - { - if (errors == 0) - Modes.stat.demodulated++; - if (mm.error_bit == -1) - { - if (mm.CRC_ok) - Modes.stat.good_CRC++; - else Modes.stat.bad_CRC++; - } - else - { - Modes.stat.bad_CRC++; - Modes.stat.fixed++; -#if 0 - if (mm.error_bit < MODES_LONG_MSG_BITS) - Modes.stat.single_bit_fix++; - else Modes.stat.two_bits_fix++; -#endif - } - } - - /* Output debug mode info if needed. - */ - if (!use_correction) - { - if (Modes.debug & DEBUG_DEMOD) - dump_raw_message ("Demodulated with 0 errors", msg, m, j, frame); - - else if ((Modes.debug & DEBUG_BADCRC) && mm.msg_type == 17 && (!mm.CRC_ok || mm.error_bit != -1)) - dump_raw_message ("Decoded with bad CRC", msg, m, j, frame); - - else if ((Modes.debug & DEBUG_GOODCRC) && mm.CRC_ok && mm.error_bit == -1) - dump_raw_message ("Decoded with good CRC", msg, m, j, frame); - } - - /* Skip this message if we are sure it's fine. - */ - if (mm.CRC_ok) - { - j += 2 * (MODES_PREAMBLE_US + (8 * msg_len)); - good_message = true; - if (use_correction) - mm.phase_corrected = true; - } - - /* Pass data to the next layer - */ - if (mm.CRC_ok) - modeS_user_message (&mm); - } - else - { - if ((Modes.debug & DEBUG_DEMODERR) && use_correction) - { - LOG_STDOUT ("The following message has %d demod errors:", errors); - dump_raw_message ("Demodulated with errors", msg, m, j, frame); - } - } - - /* Retry with phase correction if possible. - */ - if (!good_message && !use_correction) - { - j--; - use_correction = true; - } - else - { - use_correction = false; - } - } - return (rc); -} #endif /* USE_READSB_DEMOD */ /** diff --git a/src/misc.h b/src/misc.h index a971f1d..ad071de 100644 --- a/src/misc.h +++ b/src/misc.h @@ -665,8 +665,19 @@ void modeS_signal_handler (int sig); int modeS_vasprintf (char **bufp, _Printf_format_string_ const char *format, va_list args); int modeS_asprintf (char **bufp, _Printf_format_string_ const char *format, ...) ATTR_PRINTF(2, 3); -bool decode_RAW_message (mg_iobuf *msg, int loop_cnt); /* in 'dump1090.c' */ -bool decode_SBS_message (mg_iobuf *msg, int loop_cnt); /* in 'dump1090.c' */ +/* + * Common decoding functions in 'dump1090.c' + */ +int decode_modeS_message (modeS_message *mm, const uint8_t *_msg); +bool decode_RAW_message (mg_iobuf *msg, int loop_cnt); +bool decode_SBS_message (mg_iobuf *msg, int loop_cnt); +void modeS_user_message (const modeS_message *mm); +int detect_out_of_phase (const uint16_t *m); +void apply_phase_correction (uint16_t *m); +int modeS_message_len_by_type (int type); +void dump_raw_message (const char *descr, uint8_t *msg, const uint16_t *m, + uint32_t offset, uint32_t frame); + uint32_t ato_hertz (const char *Hertz); bool str_startswith (const char *s1, const char *s2); bool str_endswith (const char *s1, const char *s2);