diff --git a/make/source.mk b/make/source.mk
index 9e1452511..3ea53967c 100644
--- a/make/source.mk
+++ b/make/source.mk
@@ -126,6 +126,7 @@ COMMON_SRC = \
cms/cms_menu_misc.c \
cms/cms_menu_osd.c \
cms/cms_menu_power.c \
+ cms/cms_menu_saveexit.c \
cms/cms_menu_vtx_rtc6705.c \
cms/cms_menu_vtx_smartaudio.c \
cms/cms_menu_vtx_tramp.c \
@@ -302,6 +303,7 @@ SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \
cms/cms_menu_misc.c \
cms/cms_menu_osd.c \
cms/cms_menu_power.c \
+ cms/cms_menu_saveexit.c \
cms/cms_menu_vtx_rtc6705.c \
cms/cms_menu_vtx_smartaudio.c \
cms/cms_menu_vtx_tramp.c \
diff --git a/src/main/cms/cms.c b/src/main/cms/cms.c
index 11f453e60..a90fa6fb5 100644
--- a/src/main/cms/cms.c
+++ b/src/main/cms/cms.c
@@ -42,6 +42,7 @@
#include "cms/cms.h"
#include "cms/cms_menu_builtin.h"
+#include "cms/cms_menu_saveexit.h"
#include "cms/cms_types.h"
#include "common/maths.h"
@@ -743,11 +744,22 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
switch (exitType) {
case CMS_EXIT_SAVE:
case CMS_EXIT_SAVEREBOOT:
+ case CMS_POPUP_SAVE:
+ case CMS_POPUP_SAVEREBOOT:
cmsTraverseGlobalExit(&menuMain);
if (currentCtx.menu->onExit)
currentCtx.menu->onExit((OSD_Entry *)NULL); // Forced exit
+
+ if ((exitType == CMS_POPUP_SAVE) || (exitType == CMS_POPUP_SAVEREBOOT)) {
+ // traverse through the menu stack and call their onExit functions
+ for (int i = menuStackIdx - 1; i >= 0; i--) {
+ if (menuStack[i].menu->onExit) {
+ menuStack[i].menu->onExit((OSD_Entry *)NULL);
+ }
+ }
+ }
saveConfigAndNotify();
break;
@@ -761,7 +773,7 @@ long cmsMenuExit(displayPort_t *pDisplay, const void *ptr)
displayRelease(pDisplay);
currentCtx.menu = NULL;
- if (exitType == CMS_EXIT_SAVEREBOOT) {
+ if ((exitType == CMS_EXIT_SAVEREBOOT) || (exitType == CMS_POPUP_SAVEREBOOT)) {
displayClearScreen(pDisplay);
displayWrite(pDisplay, 5, 3, "REBOOTING...");
@@ -810,6 +822,12 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, cms_key_e key)
return BUTTON_PAUSE;
}
+ if (key == CMS_KEY_SAVEMENU) {
+ osdElementEditing = false;
+ cmsMenuChange(pDisplay, &cmsx_menuSaveExit);
+ return BUTTON_PAUSE;
+ }
+
if ((key == CMS_KEY_DOWN) && (!osdElementEditing)) {
if (currentCtx.cursorRow < pageMaxRow) {
currentCtx.cursorRow++;
@@ -1089,10 +1107,14 @@ void cmsUpdate(uint32_t currentTimeUs)
else if (IS_HI(ROLL)) {
key = CMS_KEY_RIGHT;
}
- else if (IS_HI(YAW) || IS_LO(YAW))
+ else if (IS_LO(YAW))
{
key = CMS_KEY_ESC;
}
+ else if (IS_HI(YAW))
+ {
+ key = CMS_KEY_SAVEMENU;
+ }
if (key == CMS_KEY_NONE) {
// No 'key' pressed, reset repeat control
diff --git a/src/main/cms/cms.h b/src/main/cms/cms.h
index 99d4b8b54..779a11849 100644
--- a/src/main/cms/cms.h
+++ b/src/main/cms/cms.h
@@ -32,6 +32,7 @@ typedef enum {
CMS_KEY_RIGHT,
CMS_KEY_ESC,
CMS_KEY_MENU,
+ CMS_KEY_SAVEMENU,
} cms_key_e;
extern bool cmsInMenu;
@@ -60,3 +61,6 @@ void cmsSetExternKey(cms_key_e extKey);
#define CMS_EXIT (0)
#define CMS_EXIT_SAVE (1)
#define CMS_EXIT_SAVEREBOOT (2)
+#define CMS_POPUP_SAVE (3)
+#define CMS_POPUP_SAVEREBOOT (4)
+
diff --git a/src/main/cms/cms_menu_saveexit.c b/src/main/cms/cms_menu_saveexit.c
new file mode 100644
index 000000000..1fdd4f2d0
--- /dev/null
+++ b/src/main/cms/cms_menu_saveexit.c
@@ -0,0 +1,55 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight 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.
+ *
+ * Cleanflight and Betaflight 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 .
+ */
+
+#include
+#include
+#include
+#include
+
+#include "platform.h"
+
+#ifdef USE_CMS
+#include "cms/cms.h"
+#include "cms/cms_types.h"
+#include "cms/cms_menu_saveexit.h"
+
+#include "config/feature.h"
+
+#include "fc/config.h"
+
+static OSD_Entry cmsx_menuSaveExitEntries[] =
+{
+ { "-- SAVE/EXIT --", OME_Label, NULL, NULL, 0},
+ {"EXIT", OME_OSD_Exit, cmsMenuExit, (void *)CMS_EXIT, 0},
+ {"SAVE&EXIT", OME_OSD_Exit, cmsMenuExit, (void *)CMS_POPUP_SAVE, 0},
+ {"SAVE&REBOOT", OME_OSD_Exit, cmsMenuExit, (void *)CMS_POPUP_SAVEREBOOT, 0},
+ { "BACK", OME_Back, NULL, NULL, 0 },
+ { NULL, OME_END, NULL, NULL, 0 }
+};
+
+CMS_Menu cmsx_menuSaveExit = {
+#ifdef CMS_MENU_DEBUG
+ .GUARD_text = "MENUSAVE",
+ .GUARD_type = OME_MENU,
+#endif
+ .entries = cmsx_menuSaveExitEntries
+};
+
+#endif
diff --git a/src/main/cms/cms_menu_saveexit.h b/src/main/cms/cms_menu_saveexit.h
new file mode 100644
index 000000000..48dec5308
--- /dev/null
+++ b/src/main/cms/cms_menu_saveexit.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of Cleanflight and Betaflight.
+ *
+ * Cleanflight and Betaflight 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.
+ *
+ * Cleanflight and Betaflight 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
+
+extern CMS_Menu cmsx_menuSaveExit;
diff --git a/src/test/Makefile b/src/test/Makefile
index f2842a8c9..3606a4d63 100644
--- a/src/test/Makefile
+++ b/src/test/Makefile
@@ -106,6 +106,7 @@ cli_unittest_DEFINES := \
cms_unittest_SRC := \
$(USER_DIR)/cms/cms.c \
+ $(USER_DIR)/cms/cms_menu_saveexit.c \
$(USER_DIR)/common/typeconversion.c \
$(USER_DIR)/drivers/display.c