diff --git a/src/config b/src/config
index b606002103..d279f4dec3 160000
--- a/src/config
+++ b/src/config
@@ -1 +1 @@
-Subproject commit b60600210384d1da4621cc35a0632d9cca8a62b7
+Subproject commit d279f4dec311175f312213e987b11ceda5877ef9
diff --git a/src/main/blackbox/blackbox.c b/src/main/blackbox/blackbox.c
index 7ece9940ca..1e4b2725fc 100644
--- a/src/main/blackbox/blackbox.c
+++ b/src/main/blackbox/blackbox.c
@@ -1050,6 +1050,9 @@ void blackboxValidateConfig(void)
#endif
#ifdef USE_SDCARD
case BLACKBOX_DEVICE_SDCARD:
+#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
#endif
case BLACKBOX_DEVICE_SERIAL:
// Device supported, leave the setting alone
diff --git a/src/main/blackbox/blackbox.h b/src/main/blackbox/blackbox.h
index 6738f37d45..b65e67db67 100644
--- a/src/main/blackbox/blackbox.h
+++ b/src/main/blackbox/blackbox.h
@@ -29,7 +29,8 @@ typedef enum BlackboxDevice {
BLACKBOX_DEVICE_NONE = 0,
BLACKBOX_DEVICE_FLASH = 1,
BLACKBOX_DEVICE_SDCARD = 2,
- BLACKBOX_DEVICE_SERIAL = 3
+ BLACKBOX_DEVICE_SERIAL = 3,
+ BLACKBOX_DEVICE_VIRTUAL = 4,
} BlackboxDevice_e;
typedef enum BlackboxMode {
diff --git a/src/main/blackbox/blackbox_io.c b/src/main/blackbox/blackbox_io.c
index b981c2840d..cef7be8036 100644
--- a/src/main/blackbox/blackbox_io.c
+++ b/src/main/blackbox/blackbox_io.c
@@ -59,6 +59,8 @@
#include "drivers/sdcard.h"
#endif
+#include "blackbox_virtual.h"
+
#define BLACKBOX_SERIAL_PORT_MODE MODE_TX
// How many bytes can we transmit per loop iteration when writing headers?
@@ -124,6 +126,11 @@ void blackboxWrite(uint8_t value)
case BLACKBOX_DEVICE_SDCARD:
afatfs_fputc(blackboxSDCard.logFile, value);
break;
+#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxVirtualPutChar(value);
+ break;
#endif
case BLACKBOX_DEVICE_SERIAL:
default:
@@ -185,6 +192,13 @@ int blackboxWriteString(const char *s)
break;
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ length = strlen(s);
+ blackboxVirtualWrite((const uint8_t*) s, length);
+ break;
+#endif
+
case BLACKBOX_DEVICE_SERIAL:
default:
pos = (uint8_t*) s;
@@ -217,6 +231,11 @@ void blackboxDeviceFlush(void)
flashfsFlushAsync(false);
break;
#endif // USE_FLASHFS
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxVirtualFlush();
+ break;
+#endif
default:
;
@@ -249,6 +268,10 @@ bool blackboxDeviceFlushForce(void)
// been physically written to the SD card yet.
return afatfs_flush();
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return blackboxVirtualFlush();
+#endif
default:
return false;
@@ -269,6 +292,11 @@ bool blackboxDeviceFlushForceComplete(void)
return false;
}
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxVirtualFlush();
+ return true;
+#endif
default:
return blackboxDeviceFlushForce();
@@ -360,6 +388,11 @@ bool blackboxDeviceOpen(void)
return true;
break;
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return blackboxVirtualOpen();
+
+#endif
default:
return false;
}
@@ -428,6 +461,11 @@ void blackboxDeviceClose(void)
// Some flash device, e.g., NAND devices, require explicit close to flush internally buffered data.
flashfsClose();
break;
+#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxVirtualClose();
+ break;
#endif
default:
;
@@ -564,6 +602,10 @@ bool blackboxDeviceBeginLog(void)
case BLACKBOX_DEVICE_SDCARD:
return blackboxSDCardBeginLog();
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return blackboxVirtualBeginLog();
+#endif
default:
return true;
}
@@ -598,6 +640,13 @@ bool blackboxDeviceEndLog(bool retainLog)
}
return false;
#endif // USE_SDCARD
+
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxVirtualEndLog();
+ return true;
+#endif
+
default:
return true;
}
@@ -640,6 +689,11 @@ bool isBlackboxDeviceWorking(void)
return flashfsIsReady();
#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return true;
+#endif
+
default:
return false;
}
@@ -653,6 +707,12 @@ int32_t blackboxGetLogNumber(void)
return blackboxSDCard.largestLogFileNumber;
#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return blackboxVirtualLogFileNumber();
+ break;
+#endif
+
default:
return -1;
}
@@ -679,6 +739,11 @@ void blackboxReplenishHeaderBudget(void)
case BLACKBOX_DEVICE_SDCARD:
freeSpace = afatfs_getFreeBufferSpace();
break;
+#endif
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ blackboxHeaderBudget = 1024*8;
+ return;
#endif
default:
freeSpace = 0;
@@ -745,6 +810,12 @@ blackboxBufferReserveStatus_e blackboxDeviceReserveBufferSpace(int32_t bytes)
return BLACKBOX_RESERVE_TEMPORARY_FAILURE;
#endif // USE_SDCARD
+#ifdef USE_BLACKBOX_VIRTUAL
+ case BLACKBOX_DEVICE_VIRTUAL:
+ return BLACKBOX_RESERVE_TEMPORARY_FAILURE;
+#endif
+
+
default:
return BLACKBOX_RESERVE_PERMANENT_FAILURE;
}
@@ -752,7 +823,6 @@ blackboxBufferReserveStatus_e blackboxDeviceReserveBufferSpace(int32_t bytes)
int8_t blackboxGetLogFileNo(void)
{
-#ifdef USE_BLACKBOX
#ifdef USE_SDCARD
// return current file number or -1
if (blackboxSDCard.state == BLACKBOX_SDCARD_READY_TO_LOG) {
@@ -764,6 +834,5 @@ int8_t blackboxGetLogFileNo(void)
// will be implemented later for flash based storage
return -1;
#endif
-#endif
}
#endif // BLACKBOX
diff --git a/src/main/blackbox/blackbox_virtual.c b/src/main/blackbox/blackbox_virtual.c
new file mode 100644
index 0000000000..d607e6f125
--- /dev/null
+++ b/src/main/blackbox/blackbox_virtual.c
@@ -0,0 +1,117 @@
+/*
+ * This file is part of Betaflight.
+ *
+ * Betaflight is 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 is distributed in the hope that it 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 .
+ */
+
+#include "platform.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define LOGFILE_PREFIX "LOG"
+#define LOGFILE_SUFFIX "BFL"
+
+static FILE *blackboxVirtualFile = NULL;
+static int32_t largestLogFileNumber = 0;
+
+bool blackboxVirtualOpen(void)
+{
+ const size_t log_name_length = strlen(LOGFILE_PREFIX) + 5 + strlen(LOGFILE_SUFFIX) + 1; //file name template: LOG00001.BFL
+ DIR *dir = opendir(".");
+ if (!dir) {
+ return false; // Failed to open directory
+ }
+
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ if (strlen(entry->d_name) == log_name_length
+ && strncmp(entry->d_name, LOGFILE_PREFIX, strlen(LOGFILE_PREFIX)) == 0
+ && strncmp(entry->d_name + 9, LOGFILE_SUFFIX, strlen(LOGFILE_SUFFIX)) == 0) {
+
+ char logSequenceNumberString[6];
+ memcpy(logSequenceNumberString, entry->d_name + 3, 5);
+ logSequenceNumberString[5] = '\0';
+ largestLogFileNumber = MAX((int32_t)atoi(logSequenceNumberString), largestLogFileNumber);
+ }
+ }
+ closedir(dir);
+ return true;
+}
+
+void blackboxVirtualPutChar(uint8_t value)
+{
+ if (blackboxVirtualFile != NULL) {
+ fputc(value, blackboxVirtualFile);
+ }
+}
+
+void blackboxVirtualWrite(const uint8_t *buffer, uint32_t len)
+{
+ if (blackboxVirtualFile != NULL) {
+ fwrite(buffer, len, 1, blackboxVirtualFile);
+ }
+}
+
+bool blackboxVirtualFlush(void)
+{
+ if (blackboxVirtualFile != NULL) {
+ fflush(blackboxVirtualFile);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool blackboxVirtualBeginLog(void)
+{
+ if (blackboxVirtualFile != NULL) {
+ return false;
+ }
+ const size_t name_buffer_length = strlen(LOGFILE_PREFIX) + 5 + strlen(LOGFILE_SUFFIX) + 2; //file name template: LOG00001.BFL
+ char filename[name_buffer_length];
+ sprintf(filename, "%s%05i.%s", LOGFILE_PREFIX, largestLogFileNumber + 1, LOGFILE_SUFFIX);
+ blackboxVirtualFile = fopen(filename, "w");
+ if (blackboxVirtualFile != NULL) {
+ largestLogFileNumber++;
+ }
+ return blackboxVirtualFile != NULL;
+}
+
+bool blackboxVirtualEndLog(void)
+{
+ if (blackboxVirtualFile != NULL) {
+ fclose(blackboxVirtualFile);
+ blackboxVirtualFile = NULL;
+ }
+ return true;
+}
+
+void blackboxVirtualClose(void)
+{
+ blackboxVirtualEndLog();
+}
+
+uint32_t blackboxVirtualLogFileNumber(void)
+{
+ return largestLogFileNumber;
+}
diff --git a/src/main/blackbox/blackbox_virtual.h b/src/main/blackbox/blackbox_virtual.h
new file mode 100644
index 0000000000..7f2eb0ee71
--- /dev/null
+++ b/src/main/blackbox/blackbox_virtual.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of Betaflight.
+ *
+ * Betaflight is 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 is distributed in the hope that it 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
+
+#if defined(USE_BLACKBOX_VIRTUAL) && !defined(SIMULATOR_BUILD)
+#error "USE_BLACKBOX_VIRTUAL valid for SITL build only"
+#endif
+
+bool blackboxVirtualOpen(void);
+void blackboxVirtualPutChar(uint8_t value);
+void blackboxVirtualWrite(const uint8_t *buffer, uint32_t len);
+bool blackboxVirtualFlush(void);
+bool blackboxVirtualBeginLog(void);
+bool blackboxVirtualEndLog(void);
+void blackboxVirtualClose(void);
+uint32_t blackboxVirtualLogFileNumber(void);
diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c
index e1b9bdd91e..96df532868 100644
--- a/src/main/cli/settings.c
+++ b/src/main/cli/settings.c
@@ -268,7 +268,13 @@ static const char * const lookupTableGimbalMode[] = {
#ifdef USE_BLACKBOX
static const char * const lookupTableBlackboxDevice[] = {
- "NONE", "SPIFLASH", "SDCARD", "SERIAL"
+ "NONE",
+ "SPIFLASH",
+ "SDCARD",
+ "SERIAL",
+#ifdef USE_BLACKBOX_VIRTUAL
+ "VIRTUAL",
+#endif
};
static const char * const lookupTableBlackboxMode[] = {
diff --git a/src/platform/AT32/platform_mcu.h b/src/platform/AT32/platform_mcu.h
index dc2e81e248..2c55895061 100644
--- a/src/platform/AT32/platform_mcu.h
+++ b/src/platform/AT32/platform_mcu.h
@@ -139,7 +139,7 @@ typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
#define CHECK_SPI_RX_DATA_AVAILABLE(instance) LL_SPI_IsActiveFlag_RXNE(instance)
#define SPI_RX_DATA_REGISTER(base) ((base)->DR)
-#define MAX_SPI_PIN_SEL 4
+#define MAX_SPI_PIN_SEL 5
#define UART_TX_BUFFER_ATTRIBUTE // NONE
#define UART_RX_BUFFER_ATTRIBUTE // NONE
diff --git a/src/platform/SIMULATOR/target/SITL/target.h b/src/platform/SIMULATOR/target/SITL/target.h
index 6fee3baee9..01f6518613 100644
--- a/src/platform/SIMULATOR/target/SITL/target.h
+++ b/src/platform/SIMULATOR/target/SITL/target.h
@@ -105,6 +105,9 @@
#define USE_PWM_OUTPUT
#endif
+#define USE_BLACKBOX
+#define USE_BLACKBOX_VIRTUAL
+
#undef USE_STACK_CHECK // I think SITL don't need this
#undef USE_DASHBOARD
#undef USE_TELEMETRY_LTM
diff --git a/src/platform/SIMULATOR/target/SITL/target.mk b/src/platform/SIMULATOR/target/SITL/target.mk
index 23d7794138..d46536b9a2 100644
--- a/src/platform/SIMULATOR/target/SITL/target.mk
+++ b/src/platform/SIMULATOR/target/SITL/target.mk
@@ -7,7 +7,8 @@ TARGET_SRC = \
drivers/barometer/barometer_virtual.c \
drivers/compass/compass_virtual.c \
drivers/serial_tcp.c \
- io/gps_virtual.c
+ io/gps_virtual.c \
+ blackbox/blackbox_virtual.c
SIZE_OPTIMISED_SRC += \
drivers/serial_tcp.c
diff --git a/src/platform/common/stm32/bus_spi_pinconfig.c b/src/platform/common/stm32/bus_spi_pinconfig.c
index ee59d7cd24..59c68b214a 100644
--- a/src/platform/common/stm32/bus_spi_pinconfig.c
+++ b/src/platform/common/stm32/bus_spi_pinconfig.c
@@ -403,6 +403,7 @@ const spiHardware_t spiHardware[] = {
{ DEFIO_TAG_E(PC11), GPIO_MUX_6},
},
.mosiPins = {
+ { DEFIO_TAG_E(PB0), GPIO_MUX_7},
{ DEFIO_TAG_E(PB2), GPIO_MUX_7},
{ DEFIO_TAG_E(PB5), GPIO_MUX_6},
{ DEFIO_TAG_E(PC12), GPIO_MUX_6},