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/AP_ADSB_Sagetech_MXS.h
Views: 1798
1
/*
2
* Copyright (C) 2022 Sagetech Avionics Inc. All rights reserved.
3
*
4
* This file is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation, either version 3 of the License, or
7
* (at your option) any later version.
8
*
9
* This file is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
* See the GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
16
*
17
* SDK specification
18
* https://github.com/Sagetech-Avionics/sagetech-mxs-sdk/blob/main/doc/pdf/ICD02373_MXS_Host_ICD.pdf
19
*
20
* Authors: Chuck Faber, Tom Pittenger
21
*/
22
23
#pragma once
24
25
#include "AP_ADSB_Backend.h"
26
27
#if HAL_ADSB_SAGETECH_MXS_ENABLED
28
29
#include "sagetech-sdk/sagetech_mxs.h"
30
31
class AP_ADSB_Sagetech_MXS : public AP_ADSB_Backend {
32
public:
33
using AP_ADSB_Backend::AP_ADSB_Backend;
34
35
/**
36
* @brief Performs required initialization for this instance
37
*
38
* @return true if initialization successful
39
*/
40
bool init() override;
41
42
/**
43
* @brief The main callback function (Called with freq of 10Hz) that sends
44
* appropriate message types at specific times.
45
*
46
* Read Byte from Serial Port Buffer (10Hz)
47
* Send installation message (every 5 seconds)
48
* Send Flight ID (every 8.2 s)
49
* Send Operating Message (every second)
50
* Send GPS data (flying: 5Hz, not flying: 1Hz)
51
*
52
*/
53
void update() override;
54
55
/**
56
* @brief Detect if a port is configured as Sagetech
57
*
58
* @return true
59
* @return false
60
*/
61
static bool detect();
62
63
private:
64
65
static const uint32_t PAYLOAD_MXS_MAX_SIZE = 255;
66
static const uint8_t START_BYTE = 0xAA;
67
static const uint8_t rf_capable_flags_default =
68
ADSB_BITBASK_RF_CAPABILITIES_1090ES_IN |
69
ADSB_BITBASK_RF_CAPABILITIES_1090ES_OUT;
70
71
72
enum class MsgType : uint8_t {
73
Installation = SG_MSG_TYPE_HOST_INSTALL,
74
FlightID = SG_MSG_TYPE_HOST_FLIGHT,
75
Operating = SG_MSG_TYPE_HOST_OPMSG,
76
GPS_Data = SG_MSG_TYPE_HOST_GPS,
77
Data_Request = SG_MSG_TYPE_HOST_DATAREQ,
78
// RESERVED 0x06 - 0x0A
79
Target_Request = SG_MSG_TYPE_HOST_TARGETREQ,
80
Mode = SG_MSG_TYPE_HOST_MODE,
81
// RESERVED 0x0D - 0xC1
82
ACK = SG_MSG_TYPE_XPNDR_ACK,
83
Installation_Response = SG_MSG_TYPE_XPNDR_INSTALL,
84
FlightID_Response = SG_MSG_TYPE_XPNDR_FLIGHT,
85
Status_Response = SG_MSG_TYPE_XPNDR_STATUS,
86
RESERVED_0x84 = 0x84,
87
RESERVED_0x85 = 0x85,
88
Mode_Settings = SG_MSG_TYPE_XPNDR_MODE,
89
RESERVED_0x8D = 0x8D,
90
Version_Response = SG_MSG_TYPE_XPNDR_VERSION,
91
Serial_Number_Response = SG_MSG_TYPE_XPNDR_SERIALNUM,
92
Target_Summary_Report = SG_MSG_TYPE_ADSB_TSUMMARY,
93
94
ADSB_StateVector_Report = SG_MSG_TYPE_ADSB_SVR,
95
ADSB_ModeStatus_Report = SG_MSG_TYPE_ADSB_MSR,
96
ADSB_Target_State_Report= SG_MSG_TYPE_ADSB_TSTATE,
97
ADSB_Air_Ref_Vel_Report = SG_MSG_TYPE_ADSB_ARVR,
98
};
99
100
enum class ParseState {
101
WaitingFor_Start,
102
WaitingFor_MsgType,
103
WaitingFor_MsgId,
104
WaitingFor_PayloadLen,
105
WaitingFor_PayloadContents,
106
WaitingFor_Checksum,
107
};
108
109
struct __attribute__((packed)) Packet {
110
const uint8_t start = SG_MSG_START_BYTE;
111
MsgType type;
112
uint8_t id;
113
uint8_t payload_length;
114
uint8_t payload[PAYLOAD_MXS_MAX_SIZE];
115
};
116
117
struct {
118
ParseState state;
119
uint8_t index;
120
Packet packet;
121
uint8_t checksum;
122
} message_in;
123
124
/**
125
* @brief Given the dataReqType, send the appropriate data request message
126
*
127
* @param dataReqType
128
*/
129
void send_data_req(const sg_datatype_t dataReqType);
130
131
/**
132
* @brief Takes incoming packets, gets their message type, and
133
* appropriately handles them with the correct callbacks.
134
*
135
* @param msg Message packet received, cast into Packet type.
136
*/
137
void handle_packet(const Packet &msg);
138
139
/**
140
* @brief Sends data received from ADSB State Vector Report to AutoPilot
141
*
142
* @param svr
143
*/
144
void handle_svr(const sg_svr_t svr);
145
146
/**
147
* @brief Handle a received ADSB mode status report and updates the vehicle list
148
*
149
* @param msr Sagetech SDK Mode Status Report type
150
*/
151
void handle_msr(const sg_msr_t msr);
152
153
154
/**
155
* @brief Handles an incoming byte and processes it through the state
156
* machine to determine if end of message is reached.
157
*
158
* @param data : incoming byte
159
* @return false : if not yet reached packet termination
160
*/
161
bool parse_byte(const uint8_t data);
162
163
/**
164
* @brief Takes a raw buffer and writes it out to the device port.
165
*
166
* @param data : pointer to data buffer
167
* @param len : number of bytes to write
168
*/
169
void msg_write(const uint8_t *data, const uint16_t len) const;
170
171
172
/**
173
* @brief Callback for sending an installation message.
174
*
175
*/
176
void send_install_msg();
177
178
/**
179
* @brief Callback for sending a FlightID message
180
*
181
*/
182
void send_flight_id_msg();
183
184
/**
185
* @brief Callback for sending an operating message.
186
*
187
*/
188
void send_operating_msg();
189
190
/**
191
* @brief Callback for sending a GPS data message
192
*
193
*/
194
void send_gps_msg();
195
196
/**
197
* @brief Callback for sending a Target Request message
198
*
199
*/
200
void send_targetreq_msg();
201
202
/**
203
* @brief Convert the AP_ADSB uint8_t Emitter Type to the Sagetech Emitter Type definition
204
*
205
* @param emitterType
206
* @return sg_emitter_t
207
*/
208
sg_emitter_t convert_emitter_type_to_sg(const uint8_t emitterType) const;
209
210
/**
211
* @brief Convert the float maxAirSpeed value to the Sagetech Max Airspeed Type
212
*
213
* @param maxAirSpeed
214
* @return sg_airspeed_t
215
*/
216
sg_airspeed_t convert_airspeed_knots_to_sg(const float maxAirSpeed) const;
217
218
/**
219
* @brief Converts a Sagetech Emitter type value to the values used by ADSB.
220
*
221
* @return uint8_t
222
*/
223
uint8_t convert_sg_emitter_type_to_adsb(const sg_emitter_t sgEmitterType) const;
224
225
void auto_config_operating();
226
void auto_config_installation();
227
void auto_config_flightid();
228
void handle_ack(const sg_ack_t ack);
229
230
struct {
231
// timers for each out-bound packet
232
uint32_t packet_initialize_ms;
233
uint32_t packet_PreFlight_ms;
234
uint32_t packet_GPS_ms;
235
uint32_t packet_Operating_ms;
236
uint32_t packet_targetReq;
237
238
// cached variables to compare against params so we can send msg on param change.
239
uint16_t operating_squawk;
240
int32_t operating_alt;
241
uint8_t operating_rf_select;
242
bool modeAEnabled;
243
bool modeCEnabled;
244
bool modeSEnabled;
245
bool failXpdr;
246
bool failSystem;
247
uint8_t callsign[8];
248
struct {
249
uint8_t id;
250
uint8_t type;
251
} msg;
252
} last;
253
254
struct {
255
bool init;
256
bool init_failed;
257
sg_operating_t op;
258
sg_install_t inst;
259
sg_targetreq_t treq;
260
sg_flightid_t fid;
261
sg_ack_t ack;
262
} mxs_state;
263
264
// helper functions for populating the operating message:
265
void populate_op_altitude(const struct AP_ADSB::Loc &loc);
266
void populate_op_climbrate(const struct AP_ADSB::Loc &loc);
267
void populate_op_airspeed_and_heading(const struct AP_ADSB::Loc &loc);
268
269
// last course-over-ground calculated from groundspeed vector.
270
// This is cached so we don't flip to a COG of 90-degrees when
271
// we stop moving.
272
float cog;
273
};
274
#endif // HAL_ADSB_SAGETECH_MXS_ENABLED
275
276
277