CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_ADSB/sagetech-sdk/sgDecodeMSR.c
Views: 1799
1
/**
2
* @copyright Copyright (c) 2020 Sagetech, Inc. All rights reserved.
3
*
4
* @file sgDecodeMSR.c
5
* @author jim.billmeyer
6
*
7
* @date Mar 17, 2021
8
*/
9
10
#include "sg.h"
11
#include <stdbool.h>
12
#include <stdint.h>
13
#include <string.h>
14
#include "sgUtil.h"
15
16
#define MS_PARAM_TOA (1 << 3)
17
#define MS_PARAM_ADSBVER (1 << 2)
18
#define MS_PARAM_CALLSIGN (1 << 1)
19
#define MS_PARAM_CATEMITTER (1 << 0)
20
21
#define MS_PARAM_AVLEN (1 << 7)
22
#define MS_PARAM_PRIORITY (1 << 6)
23
#define MS_PARAM_CAPCODES (1 << 5)
24
#define MS_PARAM_OPMODE (1 << 4)
25
#define MS_PARAM_NACP (1 << 3)
26
#define MS_PARAM_NACV (1 << 2)
27
#define MS_PARAM_SDA (1 << 1)
28
#define MS_PARAM_GVA (1 << 0)
29
30
#define MS_PARAM_NIC (1 << 7)
31
#define MS_PARAM_HEADING (1 << 6)
32
#define MS_PARAM_VRATE (1 << 5)
33
34
#define MS_CAP_B2LOW (1 << 3)
35
#define MS_CAP_UAT (1 << 1)
36
#define MS_CAP_TCR ((1 << 2) | (1 << 3))
37
#define MS_CAP_TSR (1 << 4)
38
#define MS_CAP_ARV (1 << 5)
39
#define MS_CAP_ADSB (1 << 6)
40
#define MS_CAP_TCAS (1 << 7)
41
42
#define MS_OP_GPS_LATFMT (1 << 7)
43
#define MS_OP_GPS_LONFMT (1 << 6)
44
#define MS_OP_TCAS_RA (1 << 5)
45
#define MS_OP_IDENT (1 << 4)
46
#define MS_OP_SINGLE_ANT (1 << 2)
47
48
/// the payload offset.
49
#define PBASE 4
50
51
/*
52
* Documented in the header file.
53
*/
54
bool sgDecodeMSR(uint8_t *buffer, sg_msr_t *msr)
55
{
56
memset(msr, 0, sizeof(sg_msr_t));
57
58
uint8_t fields[3];
59
memcpy(fields, &buffer[PBASE + 0], 3);
60
61
if (buffer[PBASE + 1] == 0x6E && buffer[PBASE + 2] == 0x60)
62
{
63
msr->type = msrTypeV0;
64
}
65
else if (buffer[PBASE + 1] == 0x7E && buffer[PBASE + 2] == 0xE0)
66
{
67
msr->type = msrTypeV1Airborne;
68
}
69
else if (buffer[PBASE + 1] == 0xFE && buffer[PBASE + 2] == 0xE0)
70
{
71
msr->type = msrTypeV1Surface;
72
}
73
else if (buffer[PBASE + 1] == 0x7F && buffer[PBASE + 2] == 0xE0)
74
{
75
msr->type = msrTypeV2Airborne;
76
}
77
else if (buffer[PBASE + 1] == 0xFF && buffer[PBASE + 2] == 0xE0)
78
{
79
msr->type = msrTypeV2Surface;
80
}
81
82
msr->flags = buffer[PBASE + 3];
83
msr->addr = toInt32(&buffer[PBASE + 4]) & 0xFFFFFF;
84
msr->addrType = buffer[PBASE + 7] & 0xFF;
85
86
uint8_t ofs = 8;
87
88
if (fields[0] & MS_PARAM_TOA)
89
{
90
msr->toa = toTOA(&buffer[PBASE + ofs]);
91
ofs += 2;
92
}
93
94
if (fields[0] & MS_PARAM_ADSBVER)
95
{
96
msr->version = buffer[PBASE + ofs];
97
ofs++;
98
}
99
100
if (fields[0] & MS_PARAM_CALLSIGN)
101
{
102
memset(msr->callsign, 0, 9);
103
memcpy(msr->callsign, &buffer[PBASE + ofs], 8);
104
ofs += 8;
105
}
106
107
if (fields[0] & MS_PARAM_CATEMITTER)
108
{
109
msr->emitter = buffer[PBASE + ofs];
110
ofs++;
111
}
112
113
if (fields[1] & MS_PARAM_AVLEN)
114
{
115
msr->size = buffer[PBASE + ofs];
116
ofs++;
117
}
118
119
if (fields[1] & MS_PARAM_PRIORITY)
120
{
121
msr->priority = buffer[PBASE + ofs];
122
ofs++;
123
}
124
125
if (fields[1] & MS_PARAM_CAPCODES)
126
{
127
uint8_t cap = buffer[PBASE + ofs + 0];
128
msr->capability.b2low = cap & MS_CAP_B2LOW;
129
130
cap = buffer[PBASE + ofs + 1];
131
msr->capability.uat = cap & MS_CAP_UAT;
132
msr->capability.tcr = (cap & MS_CAP_TCR) >> 2;
133
msr->capability.tsr = cap & MS_CAP_TSR;
134
msr->capability.arv = cap & MS_CAP_ARV;
135
msr->capability.adsb = cap & MS_CAP_ADSB;
136
msr->capability.tcas = cap & MS_CAP_TCAS;
137
138
ofs += 3;
139
}
140
141
if (fields[1] & MS_PARAM_OPMODE)
142
{
143
uint8_t op = buffer[PBASE + ofs + 0];
144
msr->opMode.gpsLatFmt = (op & MS_OP_GPS_LATFMT) == 0;
145
msr->opMode.gpsLonFmt = (op & MS_OP_GPS_LONFMT) == 0;
146
msr->opMode.tcasRA = op & MS_OP_TCAS_RA;
147
msr->opMode.ident = op & MS_OP_IDENT;
148
msr->opMode.singleAnt = op & MS_OP_SINGLE_ANT;
149
150
op = buffer[PBASE + ofs + 1];
151
msr->opMode.gpsLatOfs = op >> 5;
152
msr->opMode.gpsLonOfs = op & 0x17;
153
154
ofs += 2;
155
}
156
157
if (fields[1] & MS_PARAM_NACP)
158
{
159
msr->svQuality.nacp = buffer[PBASE + ofs];
160
ofs++;
161
}
162
163
if (fields[1] & MS_PARAM_NACV)
164
{
165
msr->svQuality.nacv = buffer[PBASE + ofs];
166
ofs++;
167
}
168
169
if (fields[1] & MS_PARAM_SDA)
170
{
171
uint8_t sda = buffer[PBASE + ofs];
172
msr->svQuality.sda = (sda & 0x18) >> 3;
173
msr->svQuality.silSupp = (sda & 0x04);
174
msr->svQuality.sil = (sda & 0x03);
175
ofs++;
176
}
177
178
if (fields[1] & MS_PARAM_GVA)
179
{
180
msr->svQuality.gva = buffer[PBASE + ofs];
181
ofs++;
182
}
183
184
if (fields[2] & MS_PARAM_NIC)
185
{
186
msr->svQuality.nicBaro = buffer[PBASE + ofs];
187
ofs++;
188
}
189
190
if (fields[2] & MS_PARAM_HEADING)
191
{
192
msr->trackHeading = buffer[PBASE + ofs];
193
ofs++;
194
}
195
196
if (fields[2] & MS_PARAM_VRATE)
197
{
198
msr->vrateType = buffer[PBASE + ofs];
199
ofs++;
200
}
201
202
return true;
203
}
204
205