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 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3,195 changes: 3,195 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

3,207 changes: 3,207 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

2,635 changes: 2,635 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Binary file added firmware/dev-relay/[email protected]
Binary file not shown.
3,042 changes: 3,042 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

2,939 changes: 2,939 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Binary file added firmware/dev-relay/[email protected]
Binary file not shown.
2,915 changes: 2,915 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Binary file added firmware/dev-relay/[email protected]
Binary file not shown.
2,991 changes: 2,991 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

3,085 changes: 3,085 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

3,236 changes: 3,236 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

4,861 changes: 4,861 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

4,932 changes: 4,932 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

4,875 changes: 4,875 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

4,945 changes: 4,945 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

6,030 changes: 6,030 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

5,163 changes: 5,163 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Binary file added firmware/dev-relay/[email protected]
Binary file not shown.
4,809 changes: 4,809 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Binary file added firmware/dev-relay/[email protected]
Binary file not shown.
3,374 changes: 3,374 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

4,930 changes: 4,930 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

5,002 changes: 5,002 additions & 0 deletions firmware/dev-relay/[email protected]

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions mLRS/Common/common_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,19 @@ uint8_t crsf_cvt_rssi_tx(int8_t rssi_i8)
}


uint8_t crsf_cvt_rssi_percent(int8_t rssi_i8, int16_t receiver_sensitivity_dbm)
{
if (rssi_i8 == RSSI_INVALID) return 255;
if (rssi_i8 >= -50) return 100;
if (rssi_i8 <= receiver_sensitivity_dbm) return 0;

int32_t r = (int32_t)rssi_i8 - receiver_sensitivity_dbm;
int32_t m = (int32_t)(-50) - receiver_sensitivity_dbm;

return (100 * r + 49)/m;
}


// CRSF crc8 is CRC-8/DVB-S2
// check 0xBC, poly 0xD5, init 0x00, not inverted, xor out 0x00
// see https://crccalc.com/
Expand Down
1 change: 1 addition & 0 deletions mLRS/Common/common_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ uint8_t crsf_cvt_mode(uint8_t mode);
uint8_t crsf_cvt_fps(uint8_t mode);
uint8_t crsf_cvt_rssi_rx(int8_t rssi_i8);
uint8_t crsf_cvt_rssi_tx(int8_t rssi_i8);
uint8_t crsf_cvt_rssi_percent(int8_t rssi_i8, int16_t receiver_sensitivity_dbm);

uint8_t crsf_crc8_calc(uint8_t crc, uint8_t data);
uint8_t crsf_crc8_update(uint8_t crc, const void* buf, uint16_t len);
Expand Down
17 changes: 17 additions & 0 deletions mLRS/Common/mavlink/olliw_dev.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,22 @@
<field type="uint8_t" name="tx_receive_sensitivity" invalid="0">Receive sensitivity of Tx in inverted dBm. 1..255 represents -1..-255 dBm, 0: ignore.</field>
<field type="uint8_t" name="rx_receive_sensitivity" invalid="0">Receive sensitivity of Rx in inverted dBm. 1..255 represents -1..-255 dBm, 0: ignore.</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 @@ -146,13 +146,14 @@ void setup_configure_metadata(void)
SetupMetaData.Rx_Diversity_allowed_mask = 0b00010; // only 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
2 changes: 1 addition & 1 deletion mLRS/Common/setup_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
X( Setup.Rx.Power, LIST, "Rx Power", "RX_POWER", 0,0,0,"", SETUP_OPT_RX_POWER, MSK_ALL )\
X( Setup.Rx.Diversity, LIST, "Rx Diversity", "RX_DIVERSITY", 0,0,0,"", SETUP_OPT_DIVERSITY, SETUP_MSK_RX_DIVERSITY )\
X( Setup.Rx.ChannelOrder, LIST, "Rx Ch Order", "RX_CH_ORDER", 0,0,0,"", SETUP_OPT_CH_ORDER, MSK_ALL )\
X( Setup.Rx.OutMode, LIST, "Rx Out Mode", "RX_OUT_MODE", 0,0,0,"", "sbus,crsf,sbus inv", SETUP_MSK_RX_OUT_MODE )\
X( Setup.Rx.OutMode, LIST, "Rx Out Mode", "RX_OUT_MODE", 0,0,0,"", "sbus,crsf,sbus inv,crsf tx", SETUP_MSK_RX_OUT_MODE )\
X( Setup.Rx.FailsafeMode, LIST, "Rx FailSafe Mode", "RX_FAILSAFE_MODE", 0,0,0,"", "no sig,low thr,by cnf,low thr cnt,ch1ch4 cnt", MSK_ALL )\
X( Setup.Rx.SerialBaudrate, LIST, "Rx Ser Baudrate", "RX_SER_BAUD", 0,0,0,"", SETUP_OPT_RX_SERIAL_BAUDRATE, MSK_ALL )\
X( Setup.Rx.SerialLinkMode, LIST, "Rx Ser Link Mode", "RX_SER_LNK_MODE", 0,0,0,"", SETUP_OPT_SERIAL_LINK_MODE, MSK_ALL )\
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 @@ -184,6 +184,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 @@ -237,6 +237,8 @@ void tRxMavlink::Do(void)
}
#endif

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 @@ -346,6 +348,7 @@ void tRxMavlink::putc(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 MAVLINK_OPT_FAKE_PARAMFTP > 1
bool force_param_list = true;
Expand Down Expand Up @@ -374,6 +377,7 @@ void tRxMavlink::putc(char c)
}
}
#endif
}

send_msg_serial_out();
}
Expand Down
72 changes: 72 additions & 0 deletions mLRS/CommonRx/out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ void OutBase::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 OutBase::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 OutBase::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 OutBase::SendRcData(tRcData* rc_orig, bool frame_missed, bool failsafe, int
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 OutBase::SendRcData(tRcData* rc_orig, bool frame_missed, bool failsafe, int
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 OutBase::SendLinkStatistics(tOutLinkStats* 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 OutBase::SendLinkStatisticsDisconnected(void)
link_stats_available = true;
link_stats_set_tstart = true;
break;
case OUT_CONFIG_CRSF_TX_JRPIN5:
break;
}
}

Expand Down Expand Up @@ -355,6 +376,57 @@ void OutBase::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 OutBase::send_crsf_tx_rcdata(tRcData* rc)
{
tCrsfChannelBuffer crsf_buf;

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

uint8_t crc = 0;

putc(CRSF_ADDRESS_RECEIVER); // this allows main tx module to detect relay mode
putc(CRSF_CHANNELPACKET_SIZE + 2);

putc(CRSF_FRAME_ID_CHANNELS);
crc = crsf_crc8_calc(crc, CRSF_FRAME_ID_CHANNELS);

putbuf(crsf_buf.c, CRSF_CHANNELPACKET_SIZE);
crc = crsf_crc8_update(crc, crsf_buf.c, CRSF_CHANNELPACKET_SIZE);

putc(crc);
}


void OutBase::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 OutBase

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

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

private:
void send_sbus_rcdata(tRcData* rc, bool frame_lost, bool failsafe);
void send_crsf_rcdata(tRcData* rc);
Expand All @@ -84,6 +86,12 @@ class OutBase
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 @@ -67,6 +67,17 @@ class tOut : public OutBase
}
#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 putc(char c) override { uart_putc(c); }

void SendLinkStatistics(void)
Expand Down
Loading