Add skeletal BDS0,5 decoding.

These messages duplicate ADS-B messages so it's not clear why
they are being interrogated for, and we don't really trust them
enough to do anything with the position information. But
recognizing/decoding them where possible does let us exclude other
Comm-B message types, avoiding some false positives.
This commit is contained in:
Oliver Jowett 2021-07-29 19:04:52 +08:00
parent c148fdca84
commit 825f959e4d
3 changed files with 55 additions and 2 deletions

View File

@ -32,6 +32,7 @@ static int decodeBDS40(struct modesMessage *mm, bool store);
static int decodeBDS44(struct modesMessage *mm, bool store);
static int decodeBDS50(struct modesMessage *mm, bool store);
static int decodeBDS60(struct modesMessage *mm, bool store);
static int decodeBDS05(struct modesMessage *mm, bool store);
static CommBDecoderFn comm_b_decoders[] = {
&decodeEmptyResponse,
@ -42,7 +43,8 @@ static CommBDecoderFn comm_b_decoders[] = {
&decodeBDS40,
&decodeBDS50,
&decodeBDS60,
&decodeBDS44
&decodeBDS44,
&decodeBDS05
};
void decodeCommB(struct modesMessage *mm)
@ -908,3 +910,51 @@ static int decodeBDS44(struct modesMessage *mm, bool store)
return score;
}
// BDS0,5 extended squitter airborne position
// (apparently this gets queried via comm-b sometimes??)
// We don't try to _use_ this as a position, but we can
// at least try to recognize it, to exclude other
// comm-b types (in particular they can be mistaken for MRAR)
static int decodeBDS05(struct modesMessage *mm, bool store)
{
// We recognize these by matching the position altitude against
// the altitude in the surrounding message, so we need a
// DF20 not a DF21
if (mm->msgtype != 20)
return 0;
unsigned char *msg = mm->MB;
unsigned typecode = getbits(msg, 1, 5);
if (typecode < 9 || typecode > 18)
return 0; // only consider typecodes that could be an airborne position with baro altitude
unsigned t_bit = getbit(msg, 21);
if (t_bit) // unlikely
return 0;
unsigned ac12 = getbits(msg, 9, 20);
if (!ac12)
return 0;
// Insert M=0 to make an AC13 value, match against the
// AC13 value in the surrounding message
unsigned ac13 = ((ac12 & 0x0FC0) << 1) | (ac12 & 0x003F);
if (mm->AC != ac13)
return 0; // no altitude match
unsigned lat = getbits(msg, 23, 39);
unsigned lon = getbits(msg, 40, 56);
if (lat == 0 || lon == 0) // unlikely position
return 0;
if (store) {
mm->commb_format = COMMB_AIRBORNE_POSITION;
// No further decoding done, we don't really trust this
// enough to use as real input to CPR
}
// Score this high enough to override everything else
return 100;
}

View File

@ -211,7 +211,8 @@ typedef enum {
COMMB_VERTICAL_INTENT,
COMMB_TRACK_TURN,
COMMB_HEADING_SPEED,
COMMB_MRAR
COMMB_MRAR,
COMMB_AIRBORNE_POSITION
} commb_format_t;
typedef enum {

View File

@ -1699,6 +1699,8 @@ static const char *commb_format_to_string(commb_format_t format) {
return "BDS6,0 Heading and speed report";
case COMMB_MRAR:
return "BDS4,4 Meterological routine air report";
case COMMB_AIRBORNE_POSITION:
return "BDS0,5 Extended squitter airborne position";
default:
return "unknown format";
}