diff --git a/mk/source.mk b/mk/source.mk
index 7f6ecb36431..f1536360c83 100644
--- a/mk/source.mk
+++ b/mk/source.mk
@@ -235,6 +235,7 @@ COMMON_SRC = \
drivers/light_ws2811strip.c \
drivers/rangefinder/rangefinder_hcsr04.c \
drivers/rangefinder/rangefinder_lidartf.c \
+ drivers/rangefinder/rangefinder_lidarmt.c \
drivers/serial_escserial.c \
drivers/vtx_common.c \
drivers/vtx_table.c \
diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c
index cfff706cb75..67cd4386614 100644
--- a/src/main/cli/settings.c
+++ b/src/main/cli/settings.c
@@ -166,7 +166,7 @@ const char * const lookupTableMagHardware[] = {
#endif
#if defined(USE_SENSOR_NAMES) || defined(USE_RANGEFINDER)
const char * const lookupTableRangefinderHardware[] = {
- "NONE", "HCSR04", "TFMINI", "TF02"
+ "NONE", "HCSR04", "TFMINI", "TF02", "MTF01", "MTF02", "MTF01P", "MTF02P"
};
#endif
diff --git a/src/main/drivers/rangefinder/rangefinder_lidarmt.c b/src/main/drivers/rangefinder/rangefinder_lidarmt.c
new file mode 100644
index 00000000000..f11380e092c
--- /dev/null
+++ b/src/main/drivers/rangefinder/rangefinder_lidarmt.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of Betaflight and INAV
+ *
+ * Betaflight and INAV are free software. You can
+ * redistribute this software and/or modify this software under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * Betaflight and INAV are distributed in the hope that
+ * they will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+/*
+ * This is a bridge driver between a sensor reader that operates at high level (i.e. on top of UART)
+ */
+
+#include
+#include
+#include
+
+#include "platform.h"
+
+#ifdef USE_RANGEFINDER_MT
+
+#include "build/build_config.h"
+
+#include "common/utils.h"
+
+#include "drivers/rangefinder/rangefinder_lidarmt.h"
+#include "sensors/rangefinder.h"
+
+static bool hasNewData = false;
+static int32_t sensorData = RANGEFINDER_NO_NEW_DATA;
+
+// Initialize the table with values for each rangefinder type
+static const MTRangefinderConfig rangefinderConfigs[] = {
+ { .deviceType = RANGEFINDER_MTF01, .delayMs = 10, .maxRangeCm = 800 },
+ { .deviceType = RANGEFINDER_MTF02, .delayMs = 20, .maxRangeCm = 250 },
+ { .deviceType = RANGEFINDER_MTF01P, .delayMs = 10, .maxRangeCm = 1200 },
+ { .deviceType = RANGEFINDER_MTF02P, .delayMs = 20, .maxRangeCm = 600 },
+};
+
+typedef struct __attribute__((packed)) {
+ uint8_t quality; // [0;255]
+ int32_t distanceMm; // Negative value for out of range
+} mspSensorRangefinderLidarMtDataMessage_t;
+
+static void mtRangefinderInit(rangefinderDev_t * dev) {
+ UNUSED(dev);
+}
+
+static void mtRangefinderUpdate(rangefinderDev_t * dev) {
+ UNUSED(dev);
+}
+
+static int32_t mtRangefinderGetDistance(rangefinderDev_t * dev) {
+ UNUSED(dev);
+ if (hasNewData) {
+ hasNewData = false;
+ return (sensorData >= 0.0f) ? sensorData : RANGEFINDER_OUT_OF_RANGE;
+ } else {
+ return RANGEFINDER_NO_NEW_DATA;
+ }
+}
+
+bool mtRangefinderDetect(rangefinderDev_t * dev, rangefinderType_e mtRangefinderToUse) {
+ const MTRangefinderConfig* deviceConf = getMTRangefinderDeviceConf(mtRangefinderToUse);
+ if (!deviceConf) {
+ return false;
+ }
+ dev->delayMs = deviceConf->delayMs;
+ dev->maxRangeCm = deviceConf->maxRangeCm;
+
+ dev->detectionConeDeciDegrees = RANGEFINDER_MT_DETECTION_CONE_DECIDEGREES;
+ dev->detectionConeExtendedDeciDegrees = RANGEFINDER_MT_DETECTION_CONE_DECIDEGREES;
+
+ dev->init = &mtRangefinderInit;
+ dev->update = &mtRangefinderUpdate;
+ dev->read = &mtRangefinderGetDistance;
+
+ return true;
+}
+
+void mtRangefinderReceiveNewData(const uint8_t * bufferPtr) {
+ const mspSensorRangefinderLidarMtDataMessage_t * pkt = (const mspSensorRangefinderLidarMtDataMessage_t *)bufferPtr;
+
+ sensorData = pkt->distanceMm / 10;
+ hasNewData = true;
+}
+
+const MTRangefinderConfig* getMTRangefinderDeviceConf(rangefinderType_e mtRangefinderToUse){
+ for (const MTRangefinderConfig* cfg = rangefinderConfigs; cfg < ARRAYEND(rangefinderConfigs); cfg++) {
+ if (cfg->deviceType == mtRangefinderToUse) {
+ return cfg;
+ }
+ }
+ return NULL;
+}
+
+#endif // USE_RANGEFINDER_MT
diff --git a/src/main/drivers/rangefinder/rangefinder_lidarmt.h b/src/main/drivers/rangefinder/rangefinder_lidarmt.h
new file mode 100644
index 00000000000..009c9f2b0b0
--- /dev/null
+++ b/src/main/drivers/rangefinder/rangefinder_lidarmt.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of Betaflight and INAV
+ *
+ * Betaflight and INAV are free software. You can
+ * redistribute this software and/or modify this software under
+ * the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * Betaflight and INAV are distributed in the hope that
+ * they will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software.
+ *
+ * If not, see .
+ */
+
+#pragma once
+
+#include "drivers/rangefinder/rangefinder.h"
+#include "sensors/rangefinder.h"
+
+#define RANGEFINDER_MT_DETECTION_CONE_DECIDEGREES 900
+
+typedef struct {
+ rangefinderType_e deviceType;
+ uint8_t delayMs;
+ uint16_t maxRangeCm;
+} MTRangefinderConfig;
+
+bool mtRangefinderDetect(rangefinderDev_t * dev, rangefinderType_e mtRangefinderToUse);
+void mtRangefinderReceiveNewData(const uint8_t * bufferPtr);
+const MTRangefinderConfig* getMTRangefinderDeviceConf(rangefinderType_e mtRangefinderToUse);
diff --git a/src/main/msp/msp.c b/src/main/msp/msp.c
index bf520e0d6af..996b57e8760 100644
--- a/src/main/msp/msp.c
+++ b/src/main/msp/msp.c
@@ -71,6 +71,7 @@
#include "drivers/usb_msc.h"
#include "drivers/vtx_common.h"
#include "drivers/vtx_table.h"
+#include "drivers/rangefinder/rangefinder_lidarmt.h"
#include "fc/board_info.h"
#include "fc/controlrate_profile.h"
@@ -3294,8 +3295,13 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
#else
sbufReadU8(src);
#endif
- break;
+#ifdef USE_RANGEFINDER
+ rangefinderConfigMutable()->rangefinder_hardware = sbufReadU8(src);
+#else
+ sbufReadU8(src); // rangefinder hardware
+#endif
+ break;
#ifdef USE_ACC
case MSP_ACC_CALIBRATION:
if (!ARMING_FLAG(ARMED))
@@ -3646,6 +3652,11 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP,
break;
#endif
+#if defined(USE_RANGEFINDER_MT)
+ case MSP2_SENSOR_RANGEFINDER_LIDARMT:
+ mtRangefinderReceiveNewData(sbufPtr(src));
+ break;
+#endif
#ifdef USE_GPS
case MSP2_SENSOR_GPS:
(void)sbufReadU8(src); // instance
diff --git a/src/main/msp/msp_protocol_v2_common.h b/src/main/msp/msp_protocol_v2_common.h
index 1f2f42a42cf..be3344c3240 100644
--- a/src/main/msp/msp_protocol_v2_common.h
+++ b/src/main/msp/msp_protocol_v2_common.h
@@ -23,3 +23,5 @@
// Sensors
#define MSP2_SENSOR_GPS 0x1F03
+// TODO: implement new, extensible rangefinder protocol
+#define MSP2_SENSOR_RANGEFINDER_LIDARMT 0x1F01
diff --git a/src/main/sensors/rangefinder.c b/src/main/sensors/rangefinder.c
index cbdce292696..db9ac81e227 100644
--- a/src/main/sensors/rangefinder.c
+++ b/src/main/sensors/rangefinder.c
@@ -41,6 +41,7 @@
#include "drivers/rangefinder/rangefinder.h"
#include "drivers/rangefinder/rangefinder_hcsr04.h"
#include "drivers/rangefinder/rangefinder_lidartf.h"
+#include "drivers/rangefinder/rangefinder_lidarmt.h"
#include "drivers/time.h"
#include "fc/runtime_config.h"
@@ -125,6 +126,18 @@ static bool rangefinderDetect(rangefinderDev_t * dev, uint8_t rangefinderHardwar
}
#endif
break;
+
+#if defined(USE_RANGEFINDER_MT)
+ case RANGEFINDER_MTF01:
+ case RANGEFINDER_MTF02:
+ case RANGEFINDER_MTF01P:
+ case RANGEFINDER_MTF02P:
+ if (mtRangefinderDetect(dev, rangefinderHardwareToUse)) {
+ rangefinderHardware = rangefinderHardwareToUse;
+ rescheduleTask(TASK_RANGEFINDER, TASK_PERIOD_MS(dev->delayMs));
+ }
+ break;
+#endif
case RANGEFINDER_NONE:
rangefinderHardware = RANGEFINDER_NONE;
diff --git a/src/main/sensors/rangefinder.h b/src/main/sensors/rangefinder.h
index cf3d49739d8..6cc9684af16 100644
--- a/src/main/sensors/rangefinder.h
+++ b/src/main/sensors/rangefinder.h
@@ -31,6 +31,10 @@ typedef enum {
RANGEFINDER_HCSR04 = 1,
RANGEFINDER_TFMINI = 2,
RANGEFINDER_TF02 = 3,
+ RANGEFINDER_MTF01 = 4,
+ RANGEFINDER_MTF02 = 5,
+ RANGEFINDER_MTF01P = 6,
+ RANGEFINDER_MTF02P = 7,
} rangefinderType_e;
typedef struct rangefinderConfig_s {