Skip to content

Commit 26ace5e

Browse files
MUSTARDTIGERFPVpkendall64
authored andcommitted
Make MAVLink WiFi mode also emit ESPNOW CRSF GPS frames (which should be enough to make antenna trackers work)
# Conflicts: # src/Tx_main.cpp
1 parent b376d05 commit 26ace5e

11 files changed

Lines changed: 181 additions & 75 deletions

File tree

include/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#pragma once
2+
#include <cstdint>
23

34
typedef enum
45
{
@@ -11,3 +12,4 @@ typedef enum
1112

1213
extern connectionState_e connectionState;
1314
extern unsigned long bindingStart;
15+
static const uint8_t bindingAddress[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

lib/CRSF/CRSF.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "CRSF.h"
2+
#include <crc.h>
3+
4+
GENERIC_CRC8 crsf_crc(CRSF_CRC_POLY);
5+
6+
void CRSF::SetHeaderAndCrc(uint8_t *frame, crsf_frame_type_e frameType, uint8_t frameSize, crsf_addr_e destAddr)
7+
{
8+
auto *header = (crsf_header_t *)frame;
9+
header->sync_byte = destAddr;
10+
header->frame_size = frameSize;
11+
header->type = frameType;
12+
13+
uint8_t crc = crsf_crc.calc(&frame[CRSF_FRAME_NOT_COUNTED_BYTES], frameSize - 1, 0);
14+
frame[frameSize + CRSF_FRAME_NOT_COUNTED_BYTES - 1] = crc;
15+
}

lib/CRSF/CRSF.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdint.h>
2+
#include "crsf_protocol.h"
3+
4+
class CRSF {
5+
public:
6+
static void SetHeaderAndCrc(uint8_t *frame, crsf_frame_type_e frameType, uint8_t frameSize, crsf_addr_e destAddr);
7+
};
8+

lib/CrsfProtocol/crsf_protocol.h

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
#define CRSF_CRC_POLY 0xd5
44
#define CRSF_SYNC_BYTE 0xc8
5-
6-
#define CRSF_FRAMETYPE_GPS 0x02
7-
#define CRSF_FRAMETYPE_LINK_STATISTICS 0x14
8-
#define CRSF_FRAMETYPE_BATTERY_SENSOR 0x08
5+
#define CRSF_FRAME_NOT_COUNTED_BYTES 2
96

107
#define CRSF_CHANNEL_VALUE_1000 191
118
#define CRSF_CHANNEL_VALUE_MID 992
@@ -23,6 +20,57 @@ typedef struct crsf_header_s
2320
uint8_t type; // from crsf_frame_type_e
2421
} PACKED crsf_header_t;
2522

23+
typedef enum : uint8_t
24+
{
25+
CRSF_FRAMETYPE_GPS = 0x02,
26+
CRSF_FRAMETYPE_VARIO = 0x07,
27+
CRSF_FRAMETYPE_BATTERY_SENSOR = 0x08,
28+
CRSF_FRAMETYPE_BARO_ALTITUDE = 0x09,
29+
CRSF_FRAMETYPE_LINK_STATISTICS = 0x14,
30+
CRSF_FRAMETYPE_OPENTX_SYNC = 0x10,
31+
CRSF_FRAMETYPE_RADIO_ID = 0x3A,
32+
CRSF_FRAMETYPE_RC_CHANNELS_PACKED = 0x16,
33+
CRSF_FRAMETYPE_ATTITUDE = 0x1E,
34+
CRSF_FRAMETYPE_FLIGHT_MODE = 0x21,
35+
// Extended Header Frames, range: 0x28 to 0x96
36+
CRSF_FRAMETYPE_DEVICE_PING = 0x28,
37+
CRSF_FRAMETYPE_DEVICE_INFO = 0x29,
38+
CRSF_FRAMETYPE_PARAMETER_SETTINGS_ENTRY = 0x2B,
39+
CRSF_FRAMETYPE_PARAMETER_READ = 0x2C,
40+
CRSF_FRAMETYPE_PARAMETER_WRITE = 0x2D,
41+
42+
//CRSF_FRAMETYPE_ELRS_STATUS = 0x2E, ELRS good/bad packet count and status flags
43+
44+
CRSF_FRAMETYPE_COMMAND = 0x32,
45+
// KISS frames
46+
CRSF_FRAMETYPE_KISS_REQ = 0x78,
47+
CRSF_FRAMETYPE_KISS_RESP = 0x79,
48+
// MSP commands
49+
CRSF_FRAMETYPE_MSP_REQ = 0x7A, // response request using msp sequence as command
50+
CRSF_FRAMETYPE_MSP_RESP = 0x7B, // reply with 58 byte chunked binary
51+
CRSF_FRAMETYPE_MSP_WRITE = 0x7C, // write with 8 byte chunked binary (OpenTX outbound telemetry buffer limit)
52+
// Ardupilot frames
53+
CRSF_FRAMETYPE_ARDUPILOT_RESP = 0x80,
54+
} crsf_frame_type_e;
55+
56+
typedef enum : uint8_t
57+
{
58+
CRSF_ADDRESS_BROADCAST = 0x00,
59+
CRSF_ADDRESS_USB = 0x10,
60+
CRSF_ADDRESS_TBS_CORE_PNP_PRO = 0x80,
61+
CRSF_ADDRESS_RESERVED1 = 0x8A,
62+
CRSF_ADDRESS_CURRENT_SENSOR = 0xC0,
63+
CRSF_ADDRESS_GPS = 0xC2,
64+
CRSF_ADDRESS_TBS_BLACKBOX = 0xC4,
65+
CRSF_ADDRESS_FLIGHT_CONTROLLER = 0xC8,
66+
CRSF_ADDRESS_RESERVED2 = 0xCA,
67+
CRSF_ADDRESS_RACE_TAG = 0xCC,
68+
CRSF_ADDRESS_RADIO_TRANSMITTER = 0xEA,
69+
CRSF_ADDRESS_CRSF_RECEIVER = 0xEC,
70+
CRSF_ADDRESS_CRSF_TRANSMITTER = 0xEE,
71+
CRSF_ADDRESS_ELRS_LUA = 0xEF
72+
} crsf_addr_e;
73+
2674
#define CRSF_MK_FRAME_T(payload) struct payload##_frame_s { crsf_header_t h; payload p; uint8_t crc; } PACKED
2775

2876
typedef struct crsf_sensor_gps_s {

lib/ESPNOW/ESPNOW_Helpers.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include "ESPNOW_Helpers.h"
2+
#include <options.h>
3+
#include <common.h>
4+
#include "devLED.h"
5+
#if defined(PLATFORM_ESP8266)
6+
#include <espnow.h>
7+
#elif defined(PLATFORM_ESP32)
8+
#include <esp_now.h>
9+
#endif
10+
11+
extern MSP msp;
12+
extern connectionState_e connectionState; // from Vrx_main.cpp
13+
14+
void ESPNOW::sendMSPViaEspnow(mspPacket_t *packet)
15+
{
16+
// Do not send while in binding mode. The currently used firmwareOptions.uid may be garbage.
17+
if (connectionState == binding)
18+
return;
19+
20+
uint8_t packetSize = msp.getTotalPacketSize(packet);
21+
uint8_t nowDataOutput[packetSize];
22+
23+
uint8_t result = msp.convertToByteArray(packet, nowDataOutput);
24+
25+
if (!result)
26+
{
27+
// packet could not be converted to array, bail out
28+
return;
29+
}
30+
if (packet->function == MSP_ELRS_BIND)
31+
{
32+
esp_now_send((uint8_t*)bindingAddress, (uint8_t *) &nowDataOutput, packetSize); // Send Bind packet with the broadcast address
33+
}
34+
else
35+
{
36+
esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize);
37+
}
38+
blinkLED();
39+
}

lib/ESPNOW/ESPNOW_Helpers.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "msp.h"
2+
#include "msptypes.h"
3+
4+
class ESPNOW {
5+
public:
6+
static void sendMSPViaEspnow(mspPacket_t *packet);
7+
};

lib/MAVLink/MAVLink.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
#include <Arduino.h>
33
#include "MAVLink.h"
44
#include <config.h>
5+
#include <crsf_protocol.h>
6+
#include <msp.h>
7+
#include <msptypes.h>
8+
#include <CRSF.h>
9+
#include <ESPNOW_Helpers.h>
510

611
void
712
MAVLink::ProcessMAVLinkFromTX(uint8_t c)
@@ -40,6 +45,35 @@ MAVLink::ProcessMAVLinkFromTX(uint8_t c)
4045
mavlink_to_gcs_buf[mavlink_to_gcs_buf_count] = msg;
4146
mavlink_to_gcs_buf_count++;
4247
mavlink_stats.packets_downlink++;
48+
49+
// Look for GPS packets - convert them to CRSF
50+
if (msg.msgid == MAVLINK_MSG_ID_GPS_RAW_INT)
51+
{
52+
mavlink_gps_raw_int_t gps_int;
53+
mavlink_msg_gps_raw_int_decode(&msg, &gps_int);
54+
CRSF_MK_FRAME_T(crsf_sensor_gps_t) crsfgps = {0};
55+
56+
crsfgps.p.speed = htobe16(gps_int.vel * 36 / 100);
57+
crsfgps.p.lat = htobe32(gps_int.lat);
58+
crsfgps.p.lon = htobe32(gps_int.lon);
59+
crsfgps.p.heading = htobe16(gps_int.cog);
60+
crsfgps.p.satcnt = gps_int.satellites_visible;
61+
crsfgps.p.altitude = htobe16(gps_int.alt / 1000 + 1000);
62+
63+
CRSF::SetHeaderAndCrc((uint8_t *)&crsfgps, CRSF_FRAMETYPE_GPS, sizeof(crsf_sensor_gps_t), CRSF_ADDRESS_CRSF_TRANSMITTER);
64+
65+
// Wrap in MSP
66+
mspPacket_t packet;
67+
packet.reset();
68+
packet.makeCommand();
69+
packet.function = MSP_ELRS_BACKPACK_CRSF_TLM;
70+
for (size_t i = 0; i < sizeof(crsfgps); i++)
71+
{
72+
packet.addByte(((uint8_t *)&crsfgps)[i]);
73+
}
74+
// Send it out ESPNOW
75+
ESPNOW::sendMSPViaEspnow(&packet);
76+
}
4377
}
4478
}
4579

src/Tx_main.cpp

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "msp.h"
1313
#include "msptypes.h"
14+
#include "ESPNOW_Helpers.h"
1415
#include "logging.h"
1516
#include "config.h"
1617
#include "common.h"
@@ -28,8 +29,6 @@
2829

2930
/////////// GLOBALS ///////////
3031

31-
uint8_t bindingAddress[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
32-
3332
const uint8_t version[] = {LATEST_VERSION};
3433

3534
connectionState_e connectionState = starting;
@@ -63,7 +62,6 @@ MAVLink mavlink;
6362

6463
/////////// FUNCTION DEFS ///////////
6564

66-
void sendMSPViaEspnow(mspPacket_t *packet);
6765
void sendMSPViaWiFiUDP(mspPacket_t *packet);
6866

6967
/////////////////////////////////////
@@ -198,12 +196,12 @@ void ProcessMSPPacketFromTX(mspPacket_t *packet)
198196
cachedVTXPacket = *packet;
199197
cacheFull = true;
200198
// transparently forward MSP packets via espnow to any subscribers
201-
sendMSPViaEspnow(packet);
199+
ESPNOW::sendMSPViaEspnow(packet);
202200
break;
203201

204202
case MSP_ELRS_SET_VRX_BACKPACK_WIFI_MODE:
205203
DBGLN("Processing MSP_ELRS_SET_VRX_BACKPACK_WIFI_MODE...");
206-
sendMSPViaEspnow(packet);
204+
ESPNOW::sendMSPViaEspnow(packet);
207205
break;
208206

209207
case MSP_ELRS_SET_TX_BACKPACK_WIFI_MODE:
@@ -220,7 +218,7 @@ void ProcessMSPPacketFromTX(mspPacket_t *packet)
220218
DBGLN("Processing MSP_ELRS_BACKPACK_SET_HEAD_TRACKING...");
221219
cachedHTPacket = *packet;
222220
cacheFull = true;
223-
sendMSPViaEspnow(packet);
221+
ESPNOW::sendMSPViaEspnow(packet);
224222
break;
225223

226224
case MSP_ELRS_BACKPACK_CRSF_TLM:
@@ -231,7 +229,7 @@ void ProcessMSPPacketFromTX(mspPacket_t *packet)
231229
}
232230
if (config.GetTelemMode() != BACKPACK_TELEM_MODE_OFF)
233231
{
234-
sendMSPViaEspnow(packet);
232+
ESPNOW::sendMSPViaEspnow(packet);
235233
}
236234
break;
237235

@@ -258,41 +256,16 @@ void ProcessMSPPacketFromTX(mspPacket_t *packet)
258256
rebootTime = millis(); // restart to set SetSoftMACAddress
259257
return;
260258
}
261-
sendMSPViaEspnow(packet);
259+
ESPNOW::sendMSPViaEspnow(packet);
262260
break;
263261

264262
default:
265263
// transparently forward MSP packets via espnow to any subscribers
266-
sendMSPViaEspnow(packet);
264+
ESPNOW::sendMSPViaEspnow(packet);
267265
break;
268266
}
269267
}
270268

271-
void sendMSPViaEspnow(mspPacket_t *packet)
272-
{
273-
uint8_t packetSize = msp.getTotalPacketSize(packet);
274-
uint8_t nowDataOutput[packetSize];
275-
276-
uint8_t result = msp.convertToByteArray(packet, nowDataOutput);
277-
278-
if (!result)
279-
{
280-
// packet could not be converted to array, bail out
281-
return;
282-
}
283-
284-
if (packet->function == MSP_ELRS_BIND)
285-
{
286-
esp_now_send(bindingAddress, (uint8_t *) &nowDataOutput, packetSize); // Send Bind packet with the broadcast address
287-
}
288-
else
289-
{
290-
esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize);
291-
}
292-
293-
blinkLED();
294-
}
295-
296269
void sendMSPViaWiFiUDP(mspPacket_t *packet)
297270
{
298271
uint8_t packetSize = msp.getTotalPacketSize(packet);
@@ -317,11 +290,11 @@ void SendCachedMSP()
317290

318291
if (cachedVTXPacket.type != MSP_PACKET_UNKNOWN)
319292
{
320-
sendMSPViaEspnow(&cachedVTXPacket);
293+
ESPNOW::sendMSPViaEspnow(&cachedVTXPacket);
321294
}
322295
if (cachedHTPacket.type != MSP_PACKET_UNKNOWN)
323296
{
324-
sendMSPViaEspnow(&cachedHTPacket);
297+
ESPNOW::sendMSPViaEspnow(&cachedHTPacket);
325298
}
326299
}
327300

src/Vrx_main.cpp

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "msp.h"
1414
#include "msptypes.h"
15+
#include "ESPNOW_Helpers.h"
1516
#include "logging.h"
1617
#include "helpers.h"
1718
#include "common.h"
@@ -129,7 +130,6 @@ VrxBackpackConfig config;
129130
/////////// FUNCTION DEFS ///////////
130131

131132
void ProcessMSPPacket(mspPacket_t *packet);
132-
void sendMSPViaEspnow(mspPacket_t *packet);
133133
void resetBootCounter();
134134
void SetupEspNow();
135135

@@ -349,30 +349,10 @@ void RequestVTXPacket()
349349
packet.addByte(0); // empty byte
350350

351351
blinkLED();
352-
sendMSPViaEspnow(&packet);
352+
ESPNOW::sendMSPViaEspnow(&packet);
353353
#endif
354354
}
355355

356-
void sendMSPViaEspnow(mspPacket_t *packet)
357-
{
358-
// Do not send while in binding mode. The currently used firmwareOptions.uid may be garbage.
359-
if (connectionState == binding)
360-
return;
361-
362-
uint8_t packetSize = msp.getTotalPacketSize(packet);
363-
uint8_t nowDataOutput[packetSize];
364-
365-
uint8_t result = msp.convertToByteArray(packet, nowDataOutput);
366-
367-
if (!result)
368-
{
369-
// packet could not be converted to array, bail out
370-
return;
371-
}
372-
373-
esp_now_send(firmwareOptions.uid, (uint8_t *) &nowDataOutput, packetSize);
374-
}
375-
376356
void resetBootCounter()
377357
{
378358
config.SetBootCount(0);

0 commit comments

Comments
 (0)