You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
5.5 KiB
242 lines
5.5 KiB
/** |
|
* @copyright Copyright (c) 2021 Sagetech, Inc. All rights reserved. |
|
* |
|
* @file sgDecodeSVR.c |
|
* @author jimb |
|
* |
|
* @date Feb 10, 2021 |
|
* |
|
* This file receives a raw ADS-B target state vector report message buffer and |
|
* parses the payload into a data struct. |
|
*/ |
|
|
|
#include <string.h> |
|
#include <stdbool.h> |
|
#include <string.h> |
|
#include <math.h> |
|
|
|
#include "sg.h" |
|
#include "sgUtil.h" |
|
#include "target.h" |
|
|
|
// airborne surface |
|
// -------- -------- |
|
#define SV_PARAM_TOA_EPOS (1 << 3) // x |
|
#define SV_PARAM_TOA_POS (1 << 2) // x x |
|
#define SV_PARAM_TOA_VEL (1 << 1) // x x |
|
#define SV_PARAM_LATLON (1 << 0) // x x |
|
|
|
#define SV_PARAM_GEOALT (1 << 7) // x |
|
#define SV_PARAM_VEL (1 << 6) // x |
|
#define SV_PARAM_SURF_GS (1 << 5) // x |
|
#define SV_PARAM_SURF_HEAD (1 << 4) // x |
|
#define SV_PARAM_BAROALT (1 << 3) // x |
|
#define SV_PARAM_VRATE (1 << 2) // x |
|
#define SV_PARAM_NIC (1 << 1) // x x |
|
#define SV_PARAM_ESTLAT (1 << 0) // x |
|
|
|
#define SV_PARAM_ESTLON (1 << 7) // x |
|
#define SV_PARAM_ESTNVEL (1 << 6) |
|
#define SV_PARAM_ESTEVAL (1 << 5) |
|
#define SV_PARAM_SURV (1 << 4) // x x |
|
#define SV_PARAM_REPORT (1 << 3) // x x |
|
|
|
/// the payload offset. |
|
#define PBASE 4 |
|
|
|
/* |
|
* Documented in the header file. |
|
*/ |
|
bool sgDecodeSVR(uint8_t *buffer, sg_svr_t *svr) |
|
{ |
|
// memset(svr, 0, sizeof(sg_svr_t)); |
|
|
|
uint8_t fields[3]; |
|
memcpy(&fields, &buffer[PBASE + 0], 3); |
|
|
|
svr->type = buffer[PBASE + 0] == 0x1F ? svrAirborne : svrSurface; |
|
svr->flags = buffer[PBASE + 3]; |
|
svr->eflags = buffer[PBASE + 4]; |
|
svr->addr = toInt32(&buffer[PBASE + 5]) & 0xFFFFFF; |
|
svr->addrType = buffer[PBASE + 8] & 0xFF; |
|
|
|
uint8_t ofs = 9; |
|
|
|
if (fields[0] & SV_PARAM_TOA_EPOS) |
|
{ |
|
svr->toaEst = toTOA(&buffer[PBASE + ofs]); |
|
ofs += 2; |
|
} |
|
if (fields[0] & SV_PARAM_TOA_POS) |
|
{ |
|
svr->toaPosition = toTOA(&buffer[PBASE + ofs]); |
|
ofs += 2; |
|
} |
|
if (fields[0] & SV_PARAM_TOA_VEL) |
|
{ |
|
svr->toaSpeed = toTOA(&buffer[PBASE + ofs]); |
|
ofs += 2; |
|
} |
|
|
|
if (fields[0] & SV_PARAM_LATLON) |
|
{ |
|
if (svr->validity.position) |
|
{ |
|
svr->lat = toLatLon(&buffer[PBASE + ofs + 0]); |
|
svr->lon = toLatLon(&buffer[PBASE + ofs + 3]); |
|
} |
|
else |
|
{ |
|
svr->lat = 0.0; |
|
svr->lon = 0.0; |
|
} |
|
|
|
ofs += 6; |
|
} |
|
|
|
if (svr->type == svrAirborne) |
|
{ |
|
if (fields[1] & SV_PARAM_GEOALT) |
|
{ |
|
if (svr->validity.geoAlt) |
|
{ |
|
svr->airborne.geoAlt = toAlt(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->airborne.geoAlt = 0; |
|
} |
|
|
|
ofs += 3; |
|
} |
|
|
|
if (fields[1] & SV_PARAM_VEL) |
|
{ |
|
if (svr->validity.airSpeed) |
|
{ |
|
int16_t nvel = toVel(&buffer[PBASE + ofs + 0]); |
|
int16_t evel = toVel(&buffer[PBASE + ofs + 2]); |
|
|
|
svr->airborne.heading = toHeading2((double)nvel, (double)evel); |
|
svr->airborne.speed = sqrt(nvel * nvel + evel * evel); |
|
svr->airborne.velEW = evel; |
|
svr->airborne.velNS = nvel; |
|
} |
|
else |
|
{ |
|
svr->airborne.heading = 0; |
|
svr->airborne.speed = 0; |
|
svr->airborne.velEW = 0; |
|
svr->airborne.velNS = 0; |
|
} |
|
|
|
ofs += 4; |
|
} |
|
|
|
if (fields[1] & SV_PARAM_BAROALT) |
|
{ |
|
if (svr->validity.baroAlt) |
|
{ |
|
svr->airborne.baroAlt = toAlt(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->airborne.baroAlt = 0; |
|
} |
|
|
|
ofs += 3; |
|
} |
|
|
|
if (fields[1] & SV_PARAM_VRATE) |
|
{ |
|
if (svr->validity.baroVRate || svr->validity.geoVRate) |
|
{ |
|
svr->airborne.vrate = toInt16(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->airborne.vrate = 0; |
|
} |
|
|
|
ofs += 2; |
|
} |
|
} |
|
else |
|
{ |
|
if (fields[1] & SV_PARAM_SURF_GS) |
|
{ |
|
if (svr->validity.surfSpeed) |
|
{ |
|
svr->surface.speed = toGS(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->surface.speed = 0; |
|
} |
|
|
|
ofs += 1; |
|
} |
|
|
|
if (fields[1] & SV_PARAM_SURF_HEAD) |
|
{ |
|
if (svr->validity.surfHeading) |
|
{ |
|
svr->surface.heading = toHeading(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->surface.heading = 0; |
|
} |
|
|
|
ofs += 1; |
|
} |
|
} |
|
|
|
if (fields[1] & SV_PARAM_NIC) |
|
{ |
|
svr->nic = buffer[PBASE + ofs]; |
|
|
|
ofs += 1; |
|
} |
|
|
|
if (fields[1] & SV_PARAM_ESTLAT) |
|
{ |
|
if (svr->evalidity.estPosition) |
|
{ |
|
svr->airborne.estLat = toLatLon(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->airborne.estLat = 0; |
|
} |
|
|
|
ofs += 3; |
|
} |
|
|
|
if (fields[2] & SV_PARAM_ESTLON) |
|
{ |
|
if (svr->evalidity.estPosition) |
|
{ |
|
svr->airborne.estLon = toLatLon(&buffer[PBASE + ofs]); |
|
} |
|
else |
|
{ |
|
svr->airborne.estLon = 0; |
|
} |
|
|
|
ofs += 3; |
|
} |
|
|
|
if (fields[2] & SV_PARAM_SURV) |
|
{ |
|
svr->survStatus = buffer[PBASE + ofs]; |
|
ofs += 1; |
|
} |
|
|
|
if (fields[2] & SV_PARAM_REPORT) |
|
{ |
|
svr->mode = buffer[PBASE + ofs]; |
|
} |
|
|
|
return true; |
|
}
|
|
|