diff --git a/dump1090.c b/dump1090.c index 25b3737..ef0504d 100644 --- a/dump1090.c +++ b/dump1090.c @@ -243,6 +243,7 @@ void modesInit(void) { // Prepare error correction tables modesChecksumInit(Modes.nfix_crc); icaoFilterInit(); + modeACInit(); if (Modes.show_only) icaoFilterAdd(Modes.show_only); diff --git a/dump1090.h b/dump1090.h index 45f0829..aac2d1e 100644 --- a/dump1090.h +++ b/dump1090.h @@ -550,7 +550,9 @@ extern "C" { // int detectModeA (uint16_t *m, struct modesMessage *mm); void decodeModeAMessage(struct modesMessage *mm, int ModeA); -int ModeAToModeC (unsigned int ModeA); +void modeACInit(); +int modeAToModeC (unsigned int modeA); +unsigned modeCToModeA (int modeC); // // Functions exported from mode_s.c diff --git a/faup1090.c b/faup1090.c index 8a29f95..3002f4b 100644 --- a/faup1090.c +++ b/faup1090.c @@ -95,6 +95,7 @@ static void faupInit(void) { // Prepare error correction tables modesChecksumInit(1); icaoFilterInit(); + modeACInit(); } // diff --git a/mode_ac.c b/mode_ac.c index baac314..c482fd7 100644 --- a/mode_ac.c +++ b/mode_ac.c @@ -29,15 +29,59 @@ // #include "dump1090.h" +#include // //========================================================================= // // Input format is : 00:A4:A2:A1:00:B4:B2:B1:00:C4:C2:C1:00:D4:D2:D1 // -int ModeAToModeC(unsigned int ModeA) + +static int modeAToCTable[4096]; +static unsigned modeCToATable[4096]; +static int internalModeAToModeC(unsigned int ModeA); + +void modeACInit() { - unsigned int FiveHundreds = 0; - unsigned int OneHundreds = 0; + for (unsigned i = 0; i < 4096; ++i) { + unsigned modeA = indexToModeA(i); + int modeC = internalModeAToModeC(modeA); + modeAToCTable[i] = modeC; + + modeC += 13; + if (modeC >= 0 && modeC < 4096) { + assert(modeCToATable[modeC] == 0); + modeCToATable[modeC] = modeA; + } + } +} + +// Given a mode A value (hex-encoded, see above) +// return the mode C value (signed multiple of 100s of feet) +// or INVALID_ALITITUDE if not a valid mode C value +int modeAToModeC(unsigned modeA) +{ + unsigned i = modeAToIndex(modeA); + if (i >= 4096) + return INVALID_ALTITUDE; + + return modeAToCTable[i]; +} + +// Given a mode C value (signed multiple of 100s of feet) +// return the mode A value, or 0 if not a valid mode C value +unsigned modeCToModeA(int modeC) +{ + modeC += 13; + if (modeC < 0 || modeC >= 4096) + return 0; + + return modeCToATable[modeC]; +} + +static int internalModeAToModeC(unsigned int ModeA) +{ + unsigned int FiveHundreds = 0; + unsigned int OneHundreds = 0; if ((ModeA & 0xFFFF8889) != 0 || // check zero bits are zero, D1 set is illegal (ModeA & 0x000000F0) == 0) { // C1,,C4 cannot be Zero @@ -100,7 +144,7 @@ void decodeModeAMessage(struct modesMessage *mm, int ModeA) // Decode an altitude if this looks like a possible mode C if (!mm->spi) { - int modeC = ModeAToModeC(ModeA); + int modeC = modeAToModeC(ModeA); if (modeC != INVALID_ALTITUDE) { mm->altitude = modeC * 100; mm->altitude_unit = UNIT_FEET; diff --git a/mode_s.c b/mode_s.c index e4ada73..0ea822c 100644 --- a/mode_s.c +++ b/mode_s.c @@ -134,7 +134,7 @@ static int decodeAC13Field(int AC13Field, altitude_unit_t *unit) { return ((n * 25) - 1000); } else { // N is an 11 bit Gillham coded altitude - int n = ModeAToModeC(decodeID13Field(AC13Field)); + int n = modeAToModeC(decodeID13Field(AC13Field)); if (n < -12) { return INVALID_ALTITUDE; } @@ -167,7 +167,7 @@ static int decodeAC12Field(int AC12Field, altitude_unit_t *unit) { // Make N a 13 bit Gillham coded altitude by inserting M=0 at bit 6 int n = ((AC12Field & 0x0FC0) << 1) | (AC12Field & 0x003F); - n = ModeAToModeC(decodeID13Field(n)); + n = modeAToModeC(decodeID13Field(n)); if (n < -12) { return INVALID_ALTITUDE; } diff --git a/track.h b/track.h index 9326f10..5761621 100644 --- a/track.h +++ b/track.h @@ -200,4 +200,16 @@ struct aircraft *trackUpdateFromMessage(struct modesMessage *mm); /* Call periodically */ void trackPeriodicUpdate(); +/* Convert from a (hex) mode A value to a 0-4095 index */ +static inline unsigned modeAToIndex(unsigned modeA) +{ + return (modeA & 0x0007) | ((modeA & 0x0070) >> 1) | ((modeA & 0x0700) >> 2) | ((modeA & 0x7000) >> 3); +} + +/* Convert from a 0-4095 index to a (hex) mode A value */ +static inline unsigned indexToModeA(unsigned index) +{ + return (index & 0007) | ((index & 0070) << 1) | ((index & 0700) << 2) | ((index & 07000) << 3); +} + #endif diff --git a/view1090.c b/view1090.c index 3b26d05..38b2fc4 100644 --- a/view1090.c +++ b/view1090.c @@ -112,6 +112,7 @@ void view1090Init(void) { // Prepare error correction tables modesChecksumInit(Modes.nfix_crc); icaoFilterInit(); + modeACInit(); } //