mirror of https://github.com/ArduPilot/ardupilot
243 lines
5.5 KiB
C
243 lines
5.5 KiB
C
|
/**
|
||
|
* @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;
|
||
|
}
|