Add a --no-fix-df option

Usually, all message candidates are speculatively corrected as if
they were DF11/17/18, even if the DF field has a different value. This
allows correction of messages when there is correctable damage to the
DF field.

However, running every message candidate through a couple of CRC checks
is expensive, CPU-wise, when decoding messages off the air, as there are
a large number of message candidates that are actually just junk data, and
computing CRCs for all of those adds up. The --no-fix-df option allows
disabling this sort of correction. The tradeoff is that messages with
damage to the DF field will not be corrected.
This commit is contained in:
Oliver Jowett 2021-03-08 14:23:35 +08:00
parent d90426e1ce
commit a135d2b915
5 changed files with 14 additions and 2 deletions

View File

@ -113,6 +113,7 @@ static void modesInitConfig(void) {
Modes.gain = MODES_MAX_GAIN; Modes.gain = MODES_MAX_GAIN;
Modes.freq = MODES_DEFAULT_FREQ; Modes.freq = MODES_DEFAULT_FREQ;
Modes.check_crc = 1; Modes.check_crc = 1;
Modes.fix_df = 1;
Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL; Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL;
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
Modes.json_interval = 1000; Modes.json_interval = 1000;
@ -334,6 +335,7 @@ static void showHelp(void)
"--fix Enable single-bit error correction using CRC\n" "--fix Enable single-bit error correction using CRC\n"
"--fix-2bit Enable two-bit error correction using CRC (use with caution)\n" "--fix-2bit Enable two-bit error correction using CRC (use with caution)\n"
"--no-fix Disable error correction using CRC\n" "--no-fix Disable error correction using CRC\n"
"--no-fix-df Disable error correction of the DF message field (reduces CPU requirements)\n"
"--no-crc-check Disable messages with broken CRC (discouraged)\n" "--no-crc-check Disable messages with broken CRC (discouraged)\n"
"--mlat display raw messages in Beast ascii mode\n" "--mlat display raw messages in Beast ascii mode\n"
"--stats With --ifile print stats at exit. No other output\n" "--stats With --ifile print stats at exit. No other output\n"
@ -547,6 +549,8 @@ int main(int argc, char **argv) {
Modes.nfix_crc = 2; Modes.nfix_crc = 2;
} else if (!strcmp(argv[j],"--no-fix")) { } else if (!strcmp(argv[j],"--no-fix")) {
Modes.nfix_crc = 0; Modes.nfix_crc = 0;
} else if (!strcmp(argv[j],"--no-fix-df")) {
Modes.fix_df = 0;
} else if (!strcmp(argv[j],"--no-crc-check")) { } else if (!strcmp(argv[j],"--no-crc-check")) {
Modes.check_crc = 0; Modes.check_crc = 0;
} else if (!strcmp(argv[j],"--phase-enhance")) { } else if (!strcmp(argv[j],"--phase-enhance")) {

View File

@ -324,6 +324,7 @@ struct _Modes { // Internal state
sdr_type_t sdr_type; // where are we getting data from? sdr_type_t sdr_type; // where are we getting data from?
int nfix_crc; // Number of crc bit error(s) to correct int nfix_crc; // Number of crc bit error(s) to correct
int check_crc; // Only display messages with good CRC int check_crc; // Only display messages with good CRC
int fix_df; // Try to correct damage to the DF field, as well as the main message body
int raw; // Raw output format int raw; // Raw output format
int mode_ac; // Enable decoding of SSR Modes A & C int mode_ac; // Enable decoding of SSR Modes A & C
int mode_ac_auto; // allow toggling of A/C by Beast commands int mode_ac_auto; // allow toggling of A/C by Beast commands

View File

@ -71,6 +71,7 @@ static void faupInitConfig(void) {
// Now initialise things that should not be 0/NULL to their defaults // Now initialise things that should not be 0/NULL to their defaults
Modes.nfix_crc = 1; Modes.nfix_crc = 1;
Modes.check_crc = 1; Modes.check_crc = 1;
Modes.fix_df = 1;
Modes.net = 1; Modes.net = 1;
Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL; Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL;
Modes.maxRange = 1852 * 360; // 360NM default max range; this also disables receiver-relative positions Modes.maxRange = 1852 * 360; // 360NM default max range; this also disables receiver-relative positions

View File

@ -268,8 +268,13 @@ static int correctMessage(const unsigned char *in, unsigned char *out)
const unsigned uncorrected_df = getbits(in, 1, 5); const unsigned uncorrected_df = getbits(in, 1, 5);
const uint32_t df_bit = 1 << uncorrected_df; const uint32_t df_bit = 1 << uncorrected_df;
// Select the right bitset based on the maximum number of bit errors in the DF field that we could correct.
// nb: strictly speaking, --no-fix-df doesn't _entirely_ disable correction of the DF field when nfix_crc == 2
// (DF17 could be corrected to DF18 or vice versa), but it does disable the CPU hungry part of it.
const unsigned fix_df_bits = (Modes.fix_df ? Modes.nfix_crc : 0);
struct errorinfo *long_ei = NULL; struct errorinfo *long_ei = NULL;
if (df_correctable_long[Modes.nfix_crc] & df_bit) { if (df_correctable_long[fix_df_bits] & df_bit) {
uint32_t long_syndrome = modesChecksum(in, MODES_LONG_MSG_BITS); uint32_t long_syndrome = modesChecksum(in, MODES_LONG_MSG_BITS);
if (isLongPIMessage(in) && long_syndrome == 0) { if (isLongPIMessage(in) && long_syndrome == 0) {
// DF17/18 message with correct checksum // DF17/18 message with correct checksum
@ -281,7 +286,7 @@ static int correctMessage(const unsigned char *in, unsigned char *out)
} }
struct errorinfo *short_ei = NULL; struct errorinfo *short_ei = NULL;
if (df_correctable_short[Modes.nfix_crc] & df_bit) { if (df_correctable_short[fix_df_bits] & df_bit) {
uint32_t short_syndrome = modesChecksum(in, MODES_SHORT_MSG_BITS); uint32_t short_syndrome = modesChecksum(in, MODES_SHORT_MSG_BITS);
if (isShortPIMessage(in) && (short_syndrome & 0xFFFF80) == 0) { if (isShortPIMessage(in) && (short_syndrome & 0xFFFF80) == 0) {
// DF11 message with correct checksum // DF11 message with correct checksum

View File

@ -57,6 +57,7 @@ static void view1090InitConfig(void) {
// Now initialise things that should not be 0/NULL to their defaults // Now initialise things that should not be 0/NULL to their defaults
Modes.check_crc = 1; Modes.check_crc = 1;
Modes.fix_df = 1;
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
Modes.interactive = 1; Modes.interactive = 1;
Modes.maxRange = 1852 * 300; // 300NM default max range Modes.maxRange = 1852 * 300; // 300NM default max range