Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relay Mode #123

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
790c96c
1st
olliw42 Sep 15, 2023
a0297bb
small modification to allow chain of more than two pairs, add ToO
olliw42 Sep 16, 2023
98f9952
enable ortho for 2.4GHz
olliw42 Sep 18, 2023
caba98a
precompiled binaries
olliw42 Sep 18, 2023
fff6bbe
Merge branch 'main' into dev-relay
olliw42 Sep 20, 2023
1d08e67
Merge branch 'dev-relay' into merge-main
olliw42 Sep 21, 2023
6f0e306
streamline with v0.3.38
olliw42 Sep 21, 2023
60083c0
Merge branch 'dev-relay' into merge-main
olliw42 Oct 15, 2023
d55bdc1
needs to be adapted
olliw42 Oct 15, 2023
72d4d96
Merge branch 'dev-relay' into merge-main
olliw42 Oct 15, 2023
34ff88e
pre release firmwares
olliw42 Oct 15, 2023
279bf5f
Merge branch 'main' into dev-relay
olliw42 Oct 17, 2023
a14ceb1
Merge branch 'dev-relay' into merge-main
olliw42 Jan 19, 2024
55ae702
Merge branch 'dev-relay' into merge-main
olliw42 Apr 17, 2024
659aa59
Merge branch 'main' into dev-relay
olliw42 Apr 17, 2024
15078f1
some tidy
olliw42 Apr 17, 2024
7b3d0b5
more tidy
olliw42 Apr 17, 2024
2cc31b5
pre-compiled binaries & more tidy
olliw42 Apr 17, 2024
93526b1
Merge branch 'main' into dev-relay
olliw42 Apr 24, 2024
89d0e45
update precompiled binaries
olliw42 Apr 24, 2024
b6b972d
Merge branch 'dev-relay' into merge-main (compiles)
olliw42 Feb 16, 2025
c3b57cb
ups
olliw42 Feb 16, 2025
1f9cbda
Merge branch 'main' into dev-relay
olliw42 Mar 5, 2025
63fc3cb
Merge branch 'dev-relay' into main-merge
olliw42 Mar 8, 2025
576de6c
Merge branch 'main' into dev-relay
olliw42 Mar 8, 2025
7c3ddeb
Merge branch 'main' into dev-relay
olliw42 Mar 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions mLRS/Common/mavlink/olliw_dev.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,22 @@
<field type="uint8_t" name="rx_used_ser_bandwidth" units="c%" invalid="UINT8_MAX">Receive bandwidth consumption. Values: 0..100, UINT8_MAX: invalid/unknown.</field>
<field type="uint8_t" name="txbuf" units="c%" invalid="UINT8_MAX">For compatibility with legacy method. UINT8_MAX: unknown.</field>
</message>
<message id="60049" name="MLRS_MAIN_RADIO_STATS">
<wip/>
<!-- WIP -->
<description>mLRS specific.</description>
<field type="uint8_t" name="uplink_rssi">crsf_cvt_rssi_tx(stats.received_rssi); OpenTX -> 1RSS</field>
<field type="uint8_t" name="uplink_LQ">stats.received_LQ; OpenTx -> RQly</field>
<field type="uint8_t" name="active_antenna">stats.received_antenna; OpenTx -> ANT</field>
<field type="uint8_t" name="mode">crsf_cvt_mode(Config.Mode); OpenTx -> RFMD</field>
<field type="uint8_t" name="uplink_transmit_power_enum">crsf_cvt_power(sx.RfPower_dbm()); OpenTx -> TPw2</field>
<field type="uint8_t" name="downlink_rssi">crsf_cvt_rssi_tx(stats.GetLastRssi()); OpenTx -> TRSS</field>
<field type="uint8_t" name="downlink_LQ">txstats.GetLQ(); OpenTx -> TQly</field>
<field type="int8_t" name="downlink_snr">stats.GetLastSnr(); OpenTx -> TSNR</field>
<field type="uint8_t" name="uplink_rssi_percent">crsf_cvt_rssi_percent(stats.GetLastRssi()); OpenTx -> TRSP</field>
<field type="uint8_t" name="uplink_fps">crsf_cvt_fps(Config.Mode); // *10 in OpenTx OpenTx -> TFPS</field>
<field type="uint8_t" name="downlink_rssi_percent">crsf_cvt_rssi_percent(stats.received_rssi); OpenTx -> RRSP</field>
<field type="uint8_t" name="uplink_transmit_power_dbm">sx.RfPower_dbm(); OpenTx -> TPWR</field>
</message>
</messages>
</mavlink>
9 changes: 5 additions & 4 deletions mLRS/Common/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,14 @@ void setup_configure_metadata(void)
SetupMetaData.Rx_Diversity_allowed_mask = 0b00010; // antenna1, not editable
#endif

// Rx OutMode: "sbus,crsf,sbus inv"
// Rx OutMode: "sbus,crsf,sbus inv,crsf tx"
#ifdef DEVICE_HAS_OUT
SetupMetaData.Rx_OutMode_allowed_mask = 0b111; // all
SetupMetaData.Rx_OutMode_allowed_mask = 0b1111; // all
//SetupMetaData.Rx_OutMode_allowed_mask = 0b0111; // sbus,crsf,sbus inv
#elif defined DEVICE_HAS_OUT_NORMAL
SetupMetaData.Rx_OutMode_allowed_mask = 0b110; // crsf,sbus inv
SetupMetaData.Rx_OutMode_allowed_mask = 0b0110; // crsf,sbus inv
#elif defined DEVICE_HAS_OUT_INVERTED
SetupMetaData.Rx_OutMode_allowed_mask = 0b001; // sbus, not editable
SetupMetaData.Rx_OutMode_allowed_mask = 0b0001; // sbus, not editable
#else
SetupMetaData.Rx_OutMode_allowed_mask = 0; // not available, do not display
#endif
Expand Down
1 change: 1 addition & 0 deletions mLRS/Common/setup_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ typedef enum {
OUT_CONFIG_SBUS = 0,
OUT_CONFIG_CRSF,
OUT_CONFIG_SBUS_INVERTED,
OUT_CONFIG_CRSF_TX_JRPIN5,
OUT_CONFIG_NUM,
} RX_OUT_CONFIG_ENUM;

Expand Down
102 changes: 102 additions & 0 deletions mLRS/Common/theory_of_operation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//*******************************************************
// Copyright (c) MLRS project
// GPL3
// https://www.gnu.org/licenses/gpl-3.0.de.html
// OlliW @ www.olliw.eu
//*******************************************************
// Theory of Operation
//*******************************************************
// Documents the operation and functioning of certain mechanisms.
/*




==============================
Relay Mode
==============================

Two pairs of tx module and receiver are daisy chained. It may be more than two pairs, but let's stick
to only two for the sake of the discussion.

For notation:

radio <-CRSF-> secondary <- air -> secondary <-CRSF,serial-> main <- air -> main <-CRSF,serial-> flight
tx module receiver tx module receiver controller

The relay mode is enabled by setting Rx_Out_Mode = "crsf tx" in the secondary receiver. This has a chain
of consequences in the operation of the secondary receiver and the two tx modules.

Secondary Receiver:

Relay mode is enabled by Rx_Out_Mode = "crsf tx".

- OUT port is configured to use tx inverted, and 400k baud
- rc data is send with address CRSF_ADDRESS_RECEIVER (instead of CRSF_ADDRESS_FLIGHT_CONTROLLER)
- rc data is adjusted by the channel order, but no other modifications are done (like failsafe, rssi, etc)
- no other CRSF frames are send (like link statistics)
- injection of mavlink frames into the outgoing stream (serial tx) is disabled
(no flow control via RADIO_STATUS, no RC_CHANNELS_OVERRIDE, etc)
- mavlink mavftp fakery is disabled

Main Tx Module:

It determines its relay mode from the address of the received CRSF frames. When it receives a CRSF frame
with address CRSF_ADDRESS_FLIGHT_CONTROLLER (or CRSF_ADDRESS_BROADCAST) it assumes business as usual. If
it receives a CRSF frame with address CRSF_ADDRESS_RECEIVER it however determines that it is the main tx module
in a relay setup.

- function crsf.IsRelayMain() returns true
- all emission of CRSF frames is disabled. This implies that the IN pin is never becoming Tx and remains all
time in Rx configuration. This is to ensure that there are no electrical shorts with the receiver's Tx output.
- any received CRSF frame except of the rc date (CRSF_FRAME_ID_CHANNELS) are ignored
- handling of telemetry mavlink messages is disabled, i.e., the mavlink stream is not processed and CRSF telemetry
data are not extracted (reduced cpu load)
- the mavlink message MLRS_MAIN_RADIO_STATS is injected into the outgoing mavlink stream, with 10 Hz rate
(it has a size of 24 bytes, so this additional data increases data rate by 10*24 = 240 bytes/sec)

Secondary Tx Module:

It determines its relay mode as follows: When it receives MLRS_MAIN_RADIO_STATS mavlink messages it determines
that it is the secondary tx module in a relay module, otherwise it assumes business as usual.

- function crsf.IsRelaySecondary() returns true
- the CRSF link statistic frames (CRSF_FRAME_ID_LINK_STATISTICS, CRSF_FRAME_ID_LINK_STATISTICS_TX,
CRSF_FRAME_ID_LINK_STATISTICS_RX) send the info obtained from the MLRS_MAIN_RADIO_STATS mavlink
messages (instead of that of the secondary tx module and receiver pair).
- if enabled, the RADIO_STATUS mavlink message is emitted with sysid and compid of 51, 69 (instead of
51, 68), to distinguish them.

Inner Tx Modules:

In a chain of three or more pairs, the inner tx modules will be both in state crsf.IsRelayMain() == true
and crsf.IsRelaySecondary() == true. This can be used to identify them as inner tx modules.

- emission of MLRS_MAIN_RADIO_STATS messages is disabled. This ensures that the secondary tx module connected to
the radio receives the correct link statistics, namely that of the main tx module.























*/


4 changes: 4 additions & 0 deletions mLRS/CommonRx/mavlink_interface_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ void tRxMavlink::Do(void)
// parse serial in -> link out
parse_serial_in_link_out();

if (out.IsRelaySecondary()) return; // don't inject anything in this case

if (Setup.Rx.SendRadioStatus && connected()) {
// we currently know that if we determine inject_radio_status here it will be executed immediately
switch (Setup.Rx.SendRadioStatus) {
Expand Down Expand Up @@ -404,6 +406,7 @@ void tRxMavlink::parse_link_in_serial_out(char c)
if (result.res == FASTMAVLINK_PARSE_RESULT_OK) {
fmav_frame_buf_to_msg(&msg_serial_out, &result, buf_link_in); // requires RESULT_OK

if (!out.IsRelaySecondary()) { // don't do mavftp faking in this case
#if MAVLINK_OPT_FAKE_PARAMFTP > 0
// if it's a mavftp call to @PARAM/param.pck we fake the url
// this will make ArduPilot to response with a NACK:FileNotFound
Expand Down Expand Up @@ -434,6 +437,7 @@ void tRxMavlink::parse_link_in_serial_out(char c)
}
}
#endif
}

#ifdef DEVICE_HAS_DRONECAN
// Two issues, which have been resolved but are present in some versions of
Expand Down
67 changes: 67 additions & 0 deletions mLRS/CommonRx/out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ void tOutBase::Configure(uint8_t new_config)
case OUT_CONFIG_CRSF:
config_crsf(false);
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
config_crsf_tx_jrpin5(false);
break;
}

initialized = false;
Expand All @@ -69,6 +72,9 @@ void tOutBase::Configure(uint8_t new_config)
case OUT_CONFIG_CRSF:
initialized = config_crsf(true);
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
initialized = config_crsf_tx_jrpin5(true);
break;
}
}

Expand All @@ -85,6 +91,9 @@ void tOutBase::Do(void)
case OUT_CONFIG_CRSF:
do_crsf();
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
do_crsf_tx_jrpin5();
break;
}
}

Expand All @@ -100,6 +109,10 @@ void tOutBase::SendRcData(tRcData* const rc_orig, bool frame_missed, bool failsa
memcpy(&rc, rc_orig, sizeof(tRcData)); // copy rc data, to not modify it !!
channel_order.Apply(&rc);

if (config == OUT_CONFIG_CRSF_TX_JRPIN5) { // send it straight out
send_crsf_tx_rcdata(&rc);
}

uint8_t failsafe_mode = setup->FailsafeMode;

if (failsafe) {
Expand Down Expand Up @@ -165,6 +178,9 @@ void tOutBase::SendRcData(tRcData* const rc_orig, bool frame_missed, bool failsa
case OUT_CONFIG_CRSF:
send_crsf_rcdata(&rc);
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
// done in the above
break;
}
}

Expand All @@ -181,6 +197,9 @@ void tOutBase::SendLinkStatistics(tOutLinkStats* const lstats)
link_stats_available = true;
link_stats_set_tstart = true;
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
// do not send since irrelevant
break;
}
}

Expand Down Expand Up @@ -208,6 +227,8 @@ void tOutBase::SendLinkStatisticsDisconnected(void)
link_stats_available = true;
link_stats_set_tstart = true;
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
break;
}
}

Expand Down Expand Up @@ -341,6 +362,52 @@ void tOutBase::do_crsf(void)
}


// for relay operation

uint16_t rc_to_crsf_tx(uint16_t rc_ch)
{
// return (((int32_t)(rc_ch) - 1024) * 1920) / 2047 + 1000;
return (((int32_t)(rc_ch) - 1024) * (1966 + 4)) / 2047 + 992;
}


void tOutBase::send_crsf_tx_rcdata(tRcData* rc)
{
tCrsfRcChannelFrame crsf_buf;

crsf_buf.ch.ch0 = rc_to_crsf_tx(rc->ch[0]);
crsf_buf.ch.ch1 = rc_to_crsf_tx(rc->ch[1]);
crsf_buf.ch.ch2 = rc_to_crsf_tx(rc->ch[2]);
crsf_buf.ch.ch3 = rc_to_crsf_tx(rc->ch[3]);
crsf_buf.ch.ch4 = rc_to_crsf_tx(rc->ch[4]);
crsf_buf.ch.ch5 = rc_to_crsf_tx(rc->ch[5]);
crsf_buf.ch.ch6 = rc_to_crsf_tx(rc->ch[6]);
crsf_buf.ch.ch7 = rc_to_crsf_tx(rc->ch[7]);
crsf_buf.ch.ch8 = rc_to_crsf_tx(rc->ch[8]);
crsf_buf.ch.ch9 = rc_to_crsf_tx(rc->ch[9]);
crsf_buf.ch.ch10 = rc_to_crsf_tx(rc->ch[10]);
crsf_buf.ch.ch11 = rc_to_crsf_tx(rc->ch[11]);
crsf_buf.ch.ch12 = rc_to_crsf_tx(rc->ch[12]);
crsf_buf.ch.ch13 = rc_to_crsf_tx(rc->ch[13]);
crsf_buf.ch.ch14 = rc_to_crsf_tx(rc->ch[14]);
crsf_buf.ch.ch15 = rc_to_crsf_tx(rc->ch[15]);

crsf_buf.address = CRSF_ADDRESS_RECEIVER; // this allows main tx module to detect relay mode
crsf_buf.len = CRSF_RCCHANNELPACKET_LEN + 2;
crsf_buf.frame_id = CRSF_FRAME_ID_RC_CHANNELS;

crsf_buf.crc = crsf_crc8_update(CRSF_CRC8_INIT, &(crsf_buf.frame_id), CRSF_RCCHANNELPACKET_LEN + 1);

putbuf((uint8_t*)&crsf_buf, CRSF_RCCHANNELPACKET_LEN + 4);
}


void tOutBase::do_crsf_tx_jrpin5(void)
{
do_crsf();
}


//-------------------------------------------------------
// FPort
//-------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions mLRS/CommonRx/out.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class tOutBase

tRcData* GetRcDataPtr(void) { return &rc; }

bool IsRelaySecondary(void) { return (config == OUT_CONFIG_CRSF_TX_JRPIN5); }

private:
void send_sbus_rcdata(tRcData* const rc, bool frame_lost, bool failsafe);
void send_crsf_rcdata(tRcData* const rc);
Expand All @@ -82,6 +84,12 @@ class tOutBase
tOutLinkStats link_stats;

tRcData rc;

// for relay operation

void send_crsf_tx_rcdata(tRcData* rc);
void do_crsf_tx_jrpin5(void);
virtual bool config_crsf_tx_jrpin5(bool enable_flag) { return false; }
};


Expand Down
11 changes: 11 additions & 0 deletions mLRS/CommonRx/out_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ class tOut : public tOutBase
}
#endif

#if defined DEVICE_HAS_OUT
bool config_crsf_tx_jrpin5(bool enable_flag) override
{
if (enable_flag) {
uart_setprotocol(400000, XUART_PARITY_NO, UART_STOPBIT_1);
out_set_inverted();
}
return true;
}
#endif

void putbuf(uint8_t* const buf, uint16_t len) override { uart_putbuf(buf, len); }

void SendLinkStatistics(void)
Expand Down
Loading