changeset 788:4abfb8a2a435

Define explicit setpoints for low / high / deco. Add an option to delay the switch to SPlow until all decompression has been cleared. (mikeller)
author heinrichsweikamp
date Tue, 04 Jul 2023 14:39:06 +0200
parents aeb72882f30a
children b7cd0c5c8e43
files Common/Inc/data_central.h Common/Inc/settings.h Discovery/Inc/check_warning.h Discovery/Inc/tMenuEdit.h Discovery/Inc/tMenuEditSetpoint.h Discovery/Inc/tMenuSetpoint.h Discovery/Inc/tStructure.h Discovery/Inc/text_multilanguage.h Discovery/Src/check_warning.c Discovery/Src/data_central.c Discovery/Src/settings.c Discovery/Src/t3.c Discovery/Src/t7.c Discovery/Src/tMenu.c Discovery/Src/tMenuEdit.c Discovery/Src/tMenuEditSetpoint.c Discovery/Src/tMenuSetpoint.c Discovery/Src/text_multilanguage.c
diffstat 18 files changed, 484 insertions(+), 317 deletions(-) [+]
line wrap: on
line diff
--- a/Common/Inc/data_central.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Common/Inc/data_central.h	Tue Jul 04 14:39:06 2023 +0200
@@ -214,6 +214,8 @@
 
 	uint8_t lastDiluent_GasIdInSettings;
     float lastSetpointChangeDepthM;
+    bool setpointDecoActivated;
+    bool setpointLowDelayed;
 
 	/* calculated by DataEX_copy_to_LifeData()
 			bottle_bar array size is made like this to have multiples of 32bit
@@ -506,4 +508,6 @@
 
 bool isCompassCalibrated(void);
 void setCompassHeading(uint16_t heading);
+
+const SDecoinfo *getDecoInfo(void);
 #endif // DATA_CENTRAL_H
--- a/Common/Inc/settings.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Common/Inc/settings.h	Tue Jul 04 14:39:06 2023 +0200
@@ -27,6 +27,9 @@
 #ifndef SETTINGS_H
 #define SETTINGS_H
 
+#include <stdint.h>
+#include <stdbool.h>
+
 // From Common/Inc:
 #include "FirmwareData.h"
 
@@ -39,8 +42,6 @@
 
 #include "configuration.h"
 
-#include <stdint.h>
-
 
 #define NUM_GASES 5
 #define NUM_OFFSET_DILUENT 5
@@ -86,7 +87,7 @@
 
 #define UART_MAX_PROTOCOL		(2u)
 
-#define FUTURE_SPARE_SIZE		(3u)		/* Applied for reuse of old, not used, scooter block (was 32 bytes)*/
+#define FUTURE_SPARE_SIZE		(2u)		/* Applied for reuse of old, not used, scooter block (was 32 bytes)*/
 
 typedef enum
 {
@@ -168,6 +169,13 @@
 	RTC_DateTypeDef lastDive;
 } SScrubberData;
 
+enum {
+    SETPOINT_INDEX_CUSTOM = 0,
+    SETPOINT_INDEX_AUTO_LOW,
+    SETPOINT_INDEX_AUTO_HIGH,
+    SETPOINT_INDEX_AUTO_DECO,
+};
+
 
 /* SSettings
 	 * gas[0] and setpoint[0] are the special ones configurable during the dive
@@ -237,7 +245,8 @@
 	SScrubberData scrubberData[2];
 	uint8_t ext_sensor_map[5];
 	uint8_t buttonLockActive;										/* redefined in 0xFFFF0025 */
-	int8_t compassDeclinationDeg;										/* redefined in 0xFFFF0026 */
+	int8_t compassDeclinationDeg;
+    uint8_t delaySetpointLow;                                         /* redefined in 0xFFFF0026 */
 	uint8_t Future_SPARE[FUTURE_SPARE_SIZE];					/* redefined in 0xFFFF0020 (old scooter Block was 32 byte)*/
 	// new in 0xFFFF0006
 	uint8_t ppo2sensors_deactivated;
@@ -373,4 +382,5 @@
 void reset_SettingWarning();
 uint8_t isSettingsWarning();
 
+bool checkAndFixSetpointSettings(void);
 #endif // SETTINGS_H
--- a/Discovery/Inc/check_warning.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/check_warning.h	Tue Jul 04 14:39:06 2023 +0200
@@ -44,4 +44,5 @@
 
 uint8_t getSetpointHighId(void);
 uint8_t getSetpointLowId(void);
+uint8_t getSetpointDecoId(void);
 #endif // CHECK_WARNING_H
--- a/Discovery/Inc/tMenuEdit.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/tMenuEdit.h	Tue Jul 04 14:39:06 2023 +0200
@@ -40,6 +40,7 @@
 #define ME_Y_LINE5					(ME_Y_LINE1 + (4 * ME_Y_LINE_STEP))
 #define ME_Y_LINE6					(ME_Y_LINE1 + (5 * ME_Y_LINE_STEP))
 
+#define EXIT_TO_NEXT_MENU   		(246)
 #define EXIT_TO_INFO_SENSOR 		(247)
 #define EXIT_TO_INFO_COMPASS 		(248)
 #define EXIT_TO_MENU_WITH_LOGO		(249)
--- a/Discovery/Inc/tMenuEditSetpoint.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/tMenuEditSetpoint.h	Tue Jul 04 14:39:06 2023 +0200
@@ -32,6 +32,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#include "settings.h"
+
 void openEdit_Setpoint(uint8_t line);
 void openEdit_DiveSelectBetterSetpoint(bool useLastDiluent);
 
@@ -39,4 +41,5 @@
 bool findSwitchToSetpoint(void);
 uint8_t getSwitchToSetpointCbar(void);
 void checkSwitchSetpoint(void);
+int printSetpointName(char *text, uint8_t setpointId, SSettings *settings, bool useSmallFont);
 #endif /* TMENU_EDIT_SETPOINT_H */
--- a/Discovery/Inc/tMenuSetpoint.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/tMenuSetpoint.h	Tue Jul 04 14:39:06 2023 +0200
@@ -34,6 +34,5 @@
 
 /* Exported functions --------------------------------------------------------*/
 
-uint32_t tMSP_refresh(uint8_t line, char *text, uint16_t *tab, char *subtext);
-
+uint32_t tMSP_refresh(char *text, uint16_t *tab, char *subtext);
 #endif /* TMENU_SETPOINT_H */
--- a/Discovery/Inc/tStructure.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/tStructure.h	Tue Jul 04 14:39:06 2023 +0200
@@ -181,10 +181,8 @@
 
 /* PAGE 3 EDIT FIELD CONTENT */
 #define StMSP_ppo2_setting	_MB(2,3,255,1,0)
-#define StMSP_Depth					_MB(2,3,255,2,0)
 #define StMSP_Active				_MB(2,3,255,3,0)
-#define StMSP_First					_MB(2,3,255,4,0)
-#define StMSP_Select				_MB(2,3,255,5,0)
+
 #define StMSP_Sensor1				_MB(2,3,255,6,0)
 #define StMSP_Sensor2				_MB(2,3,255,7,0)
 #define StMSP_Sensor3				_MB(2,3,255,8,0)
--- a/Discovery/Inc/text_multilanguage.h	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Inc/text_multilanguage.h	Tue Jul 04 14:39:06 2023 +0200
@@ -358,6 +358,13 @@
         TXT2BYTE_LoopShort,
         TXT2BYTE_SetpointShort,
 
+        TXT2BYTE_SetpointLow,
+        TXT2BYTE_SetpointHigh,
+        TXT2BYTE_SetpointDeco,
+        TXT2BYTE_SetpointDelayed,
+
+        TXT2BYTE_Enabled,
+
         TXT2BYTE_Set,
         TXT2BYTE_Clear,
         TXT2BYTE_Reset,
--- a/Discovery/Src/check_warning.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/check_warning.c	Tue Jul 04 14:39:06 2023 +0200
@@ -39,10 +39,13 @@
 #include "settings.h"
 #include "decom.h"
 #include "tCCR.h"
+#include "tHome.h"
 
 
 #define DEBOUNCE_FALLBACK_TIME_MS	(5000u)		/* set warning after 5 seconds of pending error condition */
 
+#define SETPOINT_DECO_START_RANGE_M 3.0
+#define SWITCH_DEPTH_LOW_MINIMUM_M 1.0
 
 /* Private variables with access ----------------------------------------------*/
 static uint8_t betterGasId = 0;
@@ -289,6 +292,12 @@
 
 uint8_t getSetpointLowId(void)
 {
+    SSettings *settings = settingsGetPointer();
+
+    if (settings->autoSetpoint) {
+        return SETPOINT_INDEX_AUTO_LOW;
+    }
+
     uint8_t setpointLowId = 0;
     uint8_t setpointLowDepthM = UINT8_MAX;
     for (unsigned i = 1; i <= NUM_GASES; i++) {
@@ -304,6 +313,12 @@
 
 uint8_t getSetpointHighId(void)
 {
+    SSettings *settings = settingsGetPointer();
+
+    if (settings->autoSetpoint) {
+        return SETPOINT_INDEX_AUTO_HIGH;
+    }
+
     uint8_t setpointHighId = 0;
     uint8_t setpointHighDepthM = 0;
     for (unsigned i = 1; i <= NUM_GASES; i++) {
@@ -317,6 +332,18 @@
 }
 
 
+uint8_t getSetpointDecoId(void)
+{
+    SSettings *settings = settingsGetPointer();
+
+    if (settings->autoSetpoint && stateUsed->diveSettings.setpoint[SETPOINT_INDEX_AUTO_DECO].note.ub.active) {
+        return SETPOINT_INDEX_AUTO_DECO;
+    }
+
+    return 0;
+}
+
+
 /* check for better travel!!! setpoint hw 151210
  */
 static int8_t check_BetterSetpoint(SDiveState *diveState)
@@ -332,24 +359,70 @@
     SSettings *settings = settingsGetPointer();
 
     float currentDepthM = diveState->lifeData.depth_meter;
-    if (settings->dive_mode == DIVEMODE_CCR && diveState->lifeData.lastSetpointChangeDepthM != currentDepthM) {
-        float lastChangeDepthM = diveState->lifeData.lastSetpointChangeDepthM;
+    float lastChangeDepthM = diveState->lifeData.lastSetpointChangeDepthM;
+    if (settings->dive_mode == DIVEMODE_CCR && lastChangeDepthM != currentDepthM) {
         bool descending = currentDepthM > lastChangeDepthM;
-        uint8_t setpointLowId = getSetpointLowId();
-        uint8_t setpointHighId = getSetpointHighId();
         uint8_t betterSetpointIdLocal = 0;
-        uint8_t betterSetpointSwitchDepthM = descending ? 0 : UINT8_MAX;
 
-        for (unsigned i = 1; i <= NUM_GASES; i++) {
-            uint8_t switchDepthM = diveState->diveSettings.setpoint[i].depth_meter;
-            if (!switchDepthM || (descending && i == setpointLowId) || (!descending && i == setpointHighId)) {
-                continue;
+        if (settings->autoSetpoint) {
+            bool decoSetpointEnabled = diveState->diveSettings.setpoint[SETPOINT_INDEX_AUTO_DECO].note.ub.active;
+            const SDecoinfo *decoInfo = getDecoInfo();
+            uint8_t nextDecoStopDepthM;
+            uint16_t nextDecoStopTimeRemainingS;
+            tHome_findNextStop(decoInfo->output_stop_length_seconds, &nextDecoStopDepthM, &nextDecoStopTimeRemainingS);
+
+            if (decoSetpointEnabled && nextDecoStopDepthM && currentDepthM < nextDecoStopDepthM + SETPOINT_DECO_START_RANGE_M && !diveState->lifeData.setpointDecoActivated) {
+                betterSetpointIdLocal = SETPOINT_INDEX_AUTO_DECO;
+                diveState->lifeData.setpointDecoActivated = true;
             }
 
-            if ((descending && lastChangeDepthM < switchDepthM && switchDepthM < currentDepthM && switchDepthM > betterSetpointSwitchDepthM)
-                || (!descending && lastChangeDepthM > switchDepthM && switchDepthM > currentDepthM && switchDepthM <= betterSetpointSwitchDepthM)) {
-                betterSetpointIdLocal = i;
-                betterSetpointSwitchDepthM = switchDepthM;
+            if (descending) {
+                uint8_t switchDepthHighM = diveState->diveSettings.setpoint[SETPOINT_INDEX_AUTO_HIGH].depth_meter;
+
+                if (lastChangeDepthM < switchDepthHighM && switchDepthHighM < currentDepthM && !diveState->lifeData.setpointDecoActivated) {
+                    betterSetpointIdLocal = SETPOINT_INDEX_AUTO_HIGH;
+                }
+            } else {
+                uint8_t switchDepthLowM = diveState->diveSettings.setpoint[SETPOINT_INDEX_AUTO_LOW].depth_meter;
+
+                if (lastChangeDepthM > SWITCH_DEPTH_LOW_MINIMUM_M && SWITCH_DEPTH_LOW_MINIMUM_M > currentDepthM) {
+                    // Avoid draining the oxygen supply by surfacing with a setpoint >= 1.0
+                    betterSetpointIdLocal = SETPOINT_INDEX_AUTO_LOW;
+                    diveState->lifeData.setpointLowDelayed = false;
+                } else if (lastChangeDepthM > switchDepthLowM && switchDepthLowM > currentDepthM) {
+                    if (nextDecoStopDepthM && settings->delaySetpointLow) {
+                        diveState->lifeData.setpointLowDelayed = true;
+                    } else {
+                        betterSetpointIdLocal = SETPOINT_INDEX_AUTO_LOW;
+                    }
+                }
+            }
+
+            if (!nextDecoStopDepthM) {
+                // Update the state when the decompression obligation ends
+                diveState->lifeData.setpointDecoActivated = false;
+
+                if (diveState->lifeData.setpointLowDelayed) {
+                    betterSetpointIdLocal = SETPOINT_INDEX_AUTO_LOW;
+                    diveState->lifeData.setpointLowDelayed = false;
+                }
+            }
+        } else {
+            uint8_t setpointLowId = getSetpointLowId();
+            uint8_t setpointHighId = getSetpointHighId();
+            uint8_t betterSetpointSwitchDepthM = descending ? 0 : UINT8_MAX;
+
+            for (unsigned i = 1; i <= NUM_GASES; i++) {
+                uint8_t switchDepthM = diveState->diveSettings.setpoint[i].depth_meter;
+                if (!switchDepthM || (descending && i == setpointLowId) || (!descending && i == setpointHighId)) {
+                    continue;
+                }
+
+                if ((descending && lastChangeDepthM < switchDepthM && switchDepthM < currentDepthM && switchDepthM > betterSetpointSwitchDepthM)
+                    || (!descending && lastChangeDepthM > switchDepthM && switchDepthM > currentDepthM && switchDepthM <= betterSetpointSwitchDepthM)) {
+                    betterSetpointIdLocal = i;
+                    betterSetpointSwitchDepthM = switchDepthM;
+                }
             }
         }
 
--- a/Discovery/Src/data_central.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/data_central.c	Tue Jul 04 14:39:06 2023 +0200
@@ -409,8 +409,6 @@
 }
 
 
-
-
 void updateSetpointStateUsed(void)
 {
 	if(!isLoopMode(stateUsed->diveSettings.diveMode))
@@ -470,6 +468,9 @@
 		}
 	}
 	setActualGas(lifeData, gasId, setpoint_cbar);
+
+    lifeData->setpointDecoActivated = false;
+    lifeData->setpointLowDelayed = false;
 }
 
 void setActualGasAir(SLifeData *lifeData)
@@ -875,3 +876,16 @@
 
     stateUsedWrite->diveSettings.compassHeading =  ((heading - 360) % 360) + 360;
 }
+
+
+const SDecoinfo *getDecoInfo(void)
+{
+    const SDecoinfo *decoInfo;
+    if (stateUsed->diveSettings.deco_type.ub.standard == GF_MODE) {
+        decoInfo = &stateUsed->decolistBuehlmann;
+    } else {
+        decoInfo = &stateUsed->decolistVPM;
+    }
+
+    return decoInfo;
+}
--- a/Discovery/Src/settings.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/settings.c	Tue Jul 04 14:39:06 2023 +0200
@@ -27,7 +27,6 @@
 //////////////////////////////////////////////////////////////////////////////
 
 #include <string.h>
-#include <stdbool.h>
 
 #include "settings.h"
 #include "firmwareEraseProgram.h" // for HARDWAREDATA_ADDRESS
@@ -334,6 +333,7 @@
 	.ext_sensor_map[4] = SENSOR_NONE,
 	.buttonLockActive = 0,
     .compassDeclinationDeg = 0,
+    .delaySetpointLow = false,
 };
 
 /* Private function prototypes -----------------------------------------------*/
@@ -537,6 +537,7 @@
     	// no break;
     case 0xFFFF0025:
         pSettings->compassDeclinationDeg = pStandard->compassDeclinationDeg;
+        pSettings->delaySetpointLow = pStandard->delaySetpointLow;
 
     	// no break;
     default:
@@ -592,6 +593,52 @@
 }
 
 
+bool checkAndFixSetpointSettings(void)
+{
+    SSettings *settings = settingsGetPointer();
+
+    bool fixed = false;
+    if (settings->autoSetpoint) {
+        SSetpointLine *setpointLow = &settings->setpoint[SETPOINT_INDEX_AUTO_LOW];
+        if (setpointLow->setpoint_cbar >= 100) {
+            setpointLow->setpoint_cbar = 70;
+
+            fixed = true;
+        }
+        if (setpointLow->depth_meter == 0 || setpointLow->depth_meter > 100) {
+            setpointLow->depth_meter = 2;
+
+            fixed = true;
+        }
+        SSetpointLine *setpointHigh = &settings->setpoint[SETPOINT_INDEX_AUTO_HIGH];
+        if (setpointHigh->setpoint_cbar <= setpointLow->setpoint_cbar) {
+            setpointHigh->setpoint_cbar = 130;
+
+            fixed = true;
+        }
+        if (setpointHigh->depth_meter <= setpointLow->depth_meter) {
+            setpointHigh->depth_meter = setpointLow->depth_meter + 6;
+
+            fixed = true;
+        }
+
+        SSetpointLine *setpointDeco = &settings->setpoint[SETPOINT_INDEX_AUTO_DECO];
+        if (setpointDeco->note.ub.active) {
+            if (setpointDeco->setpoint_cbar == setpointHigh->setpoint_cbar || setpointDeco->setpoint_cbar == setpointLow->setpoint_cbar) {
+                setpointDeco->setpoint_cbar = 10 * (setpointHigh->setpoint_cbar / 10) - 10;
+                if (setpointDeco->setpoint_cbar == setpointLow->setpoint_cbar) {
+                    setpointDeco->setpoint_cbar += 5;
+                }
+
+                fixed = true;
+            }
+        }
+    }
+
+    return fixed;
+}
+
+
 uint8_t check_and_correct_settings(void)
 {
     uint32_t corrections = 0;
@@ -766,52 +813,12 @@
             Settings.setpoint[i].depth_meter = 250;
             corrections++;
         }
-        if(Settings.setpoint[i].note.ub.deco)
-        {
-            if(Settings.setpoint[i].note.ub.active != 1)
-            {
-                Settings.setpoint[i].note.ub.active = 1;
-                corrections++;
-            }
-            if(Settings.setpoint[i].note.ub.travel == 1)
-            {
-                Settings.setpoint[i].note.ub.travel = 0;
-                corrections++;
-            }
-        }
-        if(Settings.setpoint[i].note.ub.travel)
-        {
-            if(Settings.setpoint[i].note.ub.active != 1)
-            {
-                Settings.setpoint[i].note.ub.active = 1;
-                corrections++;
-            }
-            if(Settings.setpoint[i].note.ub.deco == 1)
-            {
-                Settings.setpoint[i].note.ub.deco = 0;
-                corrections++;
-            }
-        }
-        if(Settings.setpoint[i].note.ub.first)
-        {
-            if(Settings.setpoint[i].note.ub.active != 1)
-            {
-                Settings.setpoint[i].note.ub.active = 1;
-                corrections++;
-            }
-            if(Settings.setpoint[i].note.ub.travel == 1)
-            {
-                Settings.setpoint[i].note.ub.travel = 0;
-                corrections++;
-            }
-            if(Settings.setpoint[i].note.ub.deco == 1)
-            {
-                Settings.setpoint[i].note.ub.deco = 0;
-                corrections++;
-            }
-        }
     }	// for(int i=1; i<=NUM_GASES;i++)
 
+    if (checkAndFixSetpointSettings()) {
+        corrections++;
+    }
+
 /*	uint8_t CCR_Mode;
  */
     if(	(Settings.CCR_Mode != CCRMODE_Sensors) &&
@@ -3070,4 +3077,3 @@
 {
 	return settingsWarning;
 }
-
--- a/Discovery/Src/t3.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/t3.c	Tue Jul 04 14:39:06 2023 +0200
@@ -258,20 +258,10 @@
     char text[TEXTSIZE];
     point_t start, stop;
     uint16_t diveMinutes = 0;
-    const SDecoinfo * pDecoinfo;
 
 	SSettings* pSettings;
 	pSettings = settingsGetPointer();
 
-    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
-    {
-        pDecoinfo = &stateUsed->decolistBuehlmann;
-    }
-    else
-    {
-        pDecoinfo = &stateUsed->decolistVPM;
-    }
-
    	wintemp.top = 479 - BigFontSeperationTopBottom + 5;
    	wintemp.bottom = 479 - 5;
 
@@ -333,6 +323,7 @@
     	wasDecoDive = 0;
     }
 
+    const SDecoinfo * pDecoinfo = getDecoInfo();
     if((pDecoinfo->output_time_to_surface_seconds) || (wasDecoDive))		/* draw deco data first => will be overlayed by all other informations */
     {
     	wasDecoDive = 1;
@@ -920,11 +911,7 @@
 	pSettings = settingsGetPointer();
 
     // CVIEW_T3_Decostop and CVIEW_T3_TTS
-    const SDecoinfo * pDecoinfo;
-    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
-        pDecoinfo = &stateUsed->decolistBuehlmann;
-    else
-        pDecoinfo = &stateUsed->decolistVPM;
+    const SDecoinfo * pDecoinfo = getDecoInfo();
 
     // CVIEW_T3_Decostop
     uint16_t 	nextstopLengthSeconds = 0;
@@ -1687,12 +1674,6 @@
 
 void t3_basics_change_customview(uint8_t *tX_selection_customview,const uint8_t *tX_customviews, uint8_t action)
 {
-    const SDecoinfo * pDecoinfo;
-    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
-        pDecoinfo = &stateUsed->decolistBuehlmann;
-    else
-        pDecoinfo = &stateUsed->decolistVPM;
-
     uint8_t curViewIdx = 0xff;
     uint8_t index = 0;
     uint8_t indexOverrun = 0;
@@ -1762,6 +1743,7 @@
 		{
 			if(settingsGetPointer()->MotionDetection != MOTION_DETECT_SECTOR)		/* no hiding in case of active sector view option (fixed mapping would change during dive) */
 			{
+                const SDecoinfo * pDecoinfo = getDecoInfo();
 				/* Skip TTS if value is 0 */
 				if((tX_customviews[index] == CVIEW_T3_TTS) && (!pDecoinfo->output_time_to_surface_seconds))
 				{
--- a/Discovery/Src/t7.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/t7.c	Tue Jul 04 14:39:06 2023 +0200
@@ -1762,6 +1762,16 @@
 }
 
 
+static bool setpointIsActive(SSettings *settings, unsigned setpointIndex)
+{
+    if (settings->autoSetpoint && setpointIndex == SETPOINT_INDEX_AUTO_DECO) {
+        return settings->setpoint[setpointIndex].note.ub.active;
+    }
+
+    return true;
+}
+
+
 static void t7_CcrSummary(SSettings *settings)
 {
     unsigned numLines = 1; // CCR Mode
@@ -1790,31 +1800,27 @@
     unsigned offset;
     SSetpointLine *setpointsToShow[MAX_NUM_SUMMARY_LINES - 1] = { NULL };
     if (settings->CCR_Mode == CCRMODE_FixedSetpoint || settings->fallbackToFixedSetpoint) {
-        // Add setpoint at start of dive
         offset = numLines;
-        i = 1;
-        while (i <= NUM_GASES) {
-            if (settings->setpoint[i].note.ub.active && settings->setpoint[i].note.ub.first) {
-                setpointsToShow[numLines - offset] = &settings->setpoint[i];
-                numLines++;
-
-                break;
+        if (settings->autoSetpoint) {
+            setpointsToShow[numLines++ - offset] = &settings->setpoint[SETPOINT_INDEX_AUTO_LOW];
+            setpointsToShow[numLines++ - offset] = &settings->setpoint[SETPOINT_INDEX_AUTO_HIGH];
+            if (setpointIsActive(settings, SETPOINT_INDEX_AUTO_DECO)) {
+                setpointsToShow[numLines++ - offset] = &settings->setpoint[SETPOINT_INDEX_AUTO_DECO];
             }
-
-            i++;
-        }
-
-        if (settings->autoSetpoint) {
+        } else {
+            // Add setpoint at start of dive
             i = 1;
-            while (i <= NUM_GASES && numLines < MAX_NUM_SUMMARY_LINES) {
-                if (settings->setpoint[i].note.ub.active && !settings->setpoint[i].note.ub.first && settings->setpoint[i].depth_meter) {
+            while (i <= NUM_GASES) {
+                if (setpointIsActive(settings, i) && settings->setpoint[i].note.ub.first) {
                     setpointsToShow[numLines - offset] = &settings->setpoint[i];
                     numLines++;
+
+                    break;
                 }
 
                 i++;
             }
-        } else {
+
             showManualSetpoints = true;
         }
     }
@@ -1842,7 +1848,7 @@
         }
         i = 2;
         while (i <= NUM_GASES && numLines < MAX_NUM_SUMMARY_LINES) {
-            if (settings->setpoint[i].note.ub.active && !settings->setpoint[i].note.ub.first) {
+            if (setpointIsActive(settings, i) && !settings->setpoint[i].note.ub.first) {
                 setpointsToShow[numLines - offset] = &settings->setpoint[i];
                 numLines++;
             }
@@ -1879,7 +1885,11 @@
     while (setpointsToShow[i] != NULL && i < MAX_NUM_SUMMARY_LINES - 1) {
         heading[headingIndex++] = '\n';
         heading[headingIndex++] = '\r';
-        if (i == 0) {
+        if (settings->autoSetpoint) {
+            heading[headingIndex++] = TXT_2BYTE;
+            heading[headingIndex++] = TXT2BYTE_SetpointShort;
+            headingIndex += printSetpointName(&heading[headingIndex], i + 1, settings, true);
+        } else if (i == 0) {
             heading[headingIndex++] = TXT_2BYTE;
             heading[headingIndex++] = TXT2BYTE_Setpoint;
         }
@@ -1888,8 +1898,9 @@
         data[dataIndex++] = '\r';
         data[dataIndex++] = '\t';
         dataIndex += snprintf(&data[dataIndex], 10, "\020%01.2f", setpointsToShow[i]->setpoint_cbar / 100.0);
-        if (settings->autoSetpoint) {
-            dataIndex += snprintf(&data[dataIndex], 10, "\016\016 %um\017", setpointsToShow[i]->depth_meter);
+        if (setpointsToShow[i]->depth_meter && !(settings->autoSetpoint && i + 1 == SETPOINT_INDEX_AUTO_DECO)) {
+            bool setpointDelayed = settings->autoSetpoint && i + 1 == SETPOINT_INDEX_AUTO_LOW && settings->delaySetpointLow;
+            dataIndex += snprintf(&data[dataIndex], 10, "\016\016 %um%s\017", setpointsToShow[i]->depth_meter, setpointDelayed ? "(d)" : "");
         }
 
         i++;
@@ -2448,14 +2459,8 @@
         snprintf(text,100,"\032\f\001 %c%c", TXT_2BYTE, TXT2BYTE_Decolist);
         GFX_write_string(&FontT42,&t7cH,text,0);
 
-        const SDecoinfo * pDecoinfo;
         uint8_t depthNext, depthLast, depthSecond, depthInc;
 
-        if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
-            pDecoinfo = &stateUsed->decolistBuehlmann;
-        else
-            pDecoinfo = &stateUsed->decolistVPM;
-
         depthLast 		= (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10);
         depthSecond 	= (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10);
         depthInc 			= (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10);
@@ -2467,6 +2472,7 @@
             depthInc 		= (uint8_t)unit_depth_integer(depthInc);
         }
 
+        const SDecoinfo * pDecoinfo = getDecoInfo();
         for(start=DECOINFO_STRUCT_MAX_STOPS-1; start>0; start--)
             if(pDecoinfo->output_stop_length_seconds[start]) break;
         start -= 6;
@@ -2538,7 +2544,6 @@
     SDivetime SafetyStopTime = {0,0,0,0};
     SDivetime TimeoutTime = {0,0,0,0};
     uint8_t  customview_warnings = 0;
-    const SDecoinfo * pDecoinfo;
 
 	SSettings* pSettings;
 	pSettings = settingsGetPointer();
@@ -2559,11 +2564,7 @@
     TimeoutTime.Minutes = TimeoutTime.Total / 60;
     TimeoutTime.Seconds = TimeoutTime.Total - (TimeoutTime.Minutes * 60);
 
-    if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
-        pDecoinfo = &stateUsed->decolistBuehlmann;
-    else
-        pDecoinfo = &stateUsed->decolistVPM;
-
+    const SDecoinfo * pDecoinfo = getDecoInfo();
     if(pDecoinfo->output_time_to_surface_seconds)
     {
         tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &nextstopDepthMeter, &nextstopLengthSeconds);
--- a/Discovery/Src/tMenu.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/tMenu.c	Tue Jul 04 14:39:06 2023 +0200
@@ -557,7 +557,7 @@
     id = tMCG_refresh(0, text, &tabPosition, subtext);
     tM_build_page(id, text, tabPosition, subtext);
 
-    id = tMSP_refresh(0, text, &tabPosition, subtext);
+    id = tMSP_refresh(text, &tabPosition, subtext);
     tM_build_page(id, text, tabPosition, subtext);
 
     id = tMXtra_refresh(0, text, &tabPosition, subtext);
@@ -675,7 +675,7 @@
         update_content_with_new_frame(page, text, tabPosition, subtext);
         break;
     case StMSP:
-        tMSP_refresh(0, text, &tabPosition, subtext);
+        tMSP_refresh(text, &tabPosition, subtext);
         update_content_with_new_frame(page, text, tabPosition, subtext);
         break;
     default:
@@ -710,7 +710,7 @@
         update_content_with_new_frame(page, text, tabPosition, subtext);
         break;
     case StMSP:
-        tMSP_refresh(0, text, &tabPosition, subtext);
+        tMSP_refresh(text, &tabPosition, subtext);
         update_content_with_new_frame(page, text, tabPosition, subtext);
         break;
     case StMXTRA:
--- a/Discovery/Src/tMenuEdit.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/tMenuEdit.c	Tue Jul 04 14:39:06 2023 +0200
@@ -573,7 +573,6 @@
     block = 0;
     subBlockPosition = 0;
 
-
     if(ident[id].maintype == FIELD_NUMBERS)
     {
         change_CLUT_entry(CLUT_MenuEditLineSelected, CLUT_MenuEditCursor);
@@ -668,10 +667,9 @@
         }
         break;
     case FIELD_BUTTON:
-        set_globalState(menuID);
-        break;
     case FIELD_ON_OFF:
         set_globalState(menuID);
+
         break;
     case FIELD_SYMBOL:
         ident[id].input[0] += 1;
@@ -681,6 +679,10 @@
         write_content_of_actual_Id();
         set_globalState(menuID);
         break;
+    case FIELD_SELECT:
+        write_buttonTextline(TXT2BYTE_ButtonMinus, TXT2BYTE_ButtonEnter, TXT2BYTE_ButtonPlus);
+
+        break;
     }
 }
 
@@ -726,6 +728,15 @@
 
 }
 
+
+static void startNextEdit(void)
+{
+    EnterPressed = 1;
+    nextMenuEditField();
+    enterMenuEditField();
+}
+
+
 void nextMenuEditFieldDigit(void)
 {
     uint8_t action;
@@ -768,6 +779,12 @@
             exitMenuEdit_to_Home();
             return;
         }
+
+        if (newContent == EXIT_TO_NEXT_MENU) {
+            startNextEdit();
+
+            return;
+        }
     }
 
     if((ident[id].maintype == FIELD_NUMBERS) && (ident[id].subtype == FIELD_3DIGIT) && (action == ACTION_BUTTON_ENTER) &&(newContent >= '0') && (newContent <= '0' + 99))
@@ -1676,6 +1693,7 @@
     enterMenuEditField();
 }
 
+
 void exitEditWithUpdate(void)
 {
     createDiveSettings();
--- a/Discovery/Src/tMenuEditSetpoint.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/tMenuEditSetpoint.c	Tue Jul 04 14:39:06 2023 +0200
@@ -33,6 +33,7 @@
 #include "gfx_fonts.h"
 #include "tMenuEdit.h"
 #include "unit.h"
+#include "tHome.h"
 
 /* Private types -------------------------------------------------------------*/
 typedef struct
@@ -67,15 +68,72 @@
 }
 
 
+static uint8_t OnAction_SP_SetpointActive (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+    switch (action) {
+    case ACTION_BUTTON_ENTER:
+
+        return digitContent;
+    case ACTION_BUTTON_ENTER_FINAL:
+
+        checkAndFixSetpointSettings();
+
+        return UPDATE_AND_EXIT_TO_MENU;
+    case ACTION_BUTTON_NEXT:
+    case ACTION_BUTTON_BACK:
+        editSetpointPage.pSetpointLine[editSetpointPage.spID].note.ub.active = (editSetpointPage.pSetpointLine[editSetpointPage.spID].note.ub.active + 1) % 2;
+
+        tMenuEdit_newInput(editId, editSetpointPage.pSetpointLine[editSetpointPage.spID].note.ub.active, 0, 0, 0);
+
+        return UNSPECIFIC_RETURN;
+    default:
+
+        break;
+    }
+
+    return EXIT_TO_MENU;
+}
+
+
+int printSetpointName(char *text, uint8_t setpointId, SSettings *settings, bool useSmallFont)
+{
+    int charsPrinted = 0;
+    if (settings->autoSetpoint) {
+        switch (setpointId) {
+        case SETPOINT_INDEX_AUTO_LOW:
+            charsPrinted = snprintf(text, 10, "%s%c%c%s", useSmallFont ? "\016\016" : "", TXT_2BYTE, TXT2BYTE_SetpointLow, useSmallFont ? "\017" : "");
+
+            break;
+        case SETPOINT_INDEX_AUTO_HIGH:
+            charsPrinted = snprintf(text, 10, "%s%c%c%s", useSmallFont ? "\016\016" : "", TXT_2BYTE, TXT2BYTE_SetpointHigh, useSmallFont ? "\017" : "");
+
+            break;
+        case SETPOINT_INDEX_AUTO_DECO:
+            charsPrinted = snprintf(text, 10, "%s%c%c%s", useSmallFont ? "\016\016" : "", TXT_2BYTE, TXT2BYTE_SetpointDeco, useSmallFont ? "\017" : "");
+
+            break;
+        default:
+
+            break;
+        }
+    } else {
+        charsPrinted = snprintf(text, 10, "%d", setpointId);
+    }
+
+    return charsPrinted;
+}
+
+
 void openEdit_Setpoint(uint8_t line)
 {
+	SSettings *settings = settingsGetPointer();
+
     uint8_t useSensorSubMenu = 0;
     char text[20];
     uint8_t sensorActive[3];
 
     /* dive mode */
-    if(actual_menu_content != MENU_SURFACE)
-    {
+    if (actual_menu_content != MENU_SURFACE) {
         uint8_t setpointCbar, actualGasID;
         setpointCbar = 100;
 
@@ -90,48 +148,33 @@
             actualGasID = stateUsedWrite->lifeData.actualGas.GasIdInSettings;
 
         // setpointCbar, CCR_Mode and sensor menu
-        if((line < 6) && (stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR))		/* setpoints inactive in PSCR mode */
-        {
+        if (line < 6 && stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR) {
+            /* setpoints inactive in PSCR mode */
+
+            if (settings->autoSetpoint && line > SETPOINT_INDEX_AUTO_DECO) {
+                return;
+            }
+
             setpointCbar = stateUsedWrite->diveSettings.setpoint[line].setpoint_cbar;
             stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint;
-
-            // BetterSetpoint warning only once
-            if(actualBetterSetpointId() == line)
-            {
-                uint8_t depth;
-                depth = stateUsedWrite->diveSettings.setpoint[line].depth_meter;
-                // BetterSetpoint warning only once -> clear active
-                for(int i=0; i<=NUM_GASES; i++)
-                {
-                	stateUsedWrite->diveSettings.setpoint[i].note.ub.first = 0;
-                    if(stateUsedWrite->diveSettings.setpoint[i].depth_meter <= depth)
-                    	stateUsedWrite->diveSettings.setpoint[i].note.ub.active = 0;
-                }
-                stateUsedWrite->diveSettings.setpoint[line].note.ub.first = 1;
-            }
-        }
-        else	/* menu item not pointing to setpoint selection => use sensor or ppo2 simulation */
-        {
-        	if((stateUsedWrite->diveSettings.diveMode == DIVEMODE_PSCR) && (line == 2))
+        } else if (stateUsedWrite->diveSettings.diveMode == DIVEMODE_PSCR && line == 2) {
+            /* menu item not pointing to setpoint selection => use sensor or ppo2 simulation */
+            stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation;
+		} else if (line == 6) {
+            /* => use sensor */
+			if(stateUsedWrite->diveSettings.CCR_Mode != CCRMODE_Sensors)
 			{
-        		stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation;
+				/* setpoint_cbar will be written by updateSetpointStateUsed() in main.c loop */
+				setpointCbar = 255;
+				stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Sensors;
 			}
-			else	/* => use sensor */
+			else
 			{
-				if(stateUsedWrite->diveSettings.CCR_Mode != CCRMODE_Sensors)
-				{
-					/* setpoint_cbar will be written by updateSetpointStateUsed() in main.c loop */
-					setpointCbar = 255;
-					stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Sensors;
-				}
-				else
-				{
-					useSensorSubMenu = 1;
-				}
+				useSensorSubMenu = 1;
 			}
         }
 
-        setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar);
+        setActualGas_DM(&stateUsedWrite->lifeData,actualGasID, setpointCbar);
 
         checkSwitchToLoop();
 
@@ -193,89 +236,65 @@
             setEvent(StMSP_Sensor2, (uint32_t)OnAction_SP_DM_Sensor2);
             setEvent(StMSP_Sensor3, (uint32_t)OnAction_SP_DM_Sensor3);
         }
-        return;
-    }
-    else
-    {
+    } else {
         /* surface mode */
-        uint8_t spId, setpoint_cbar, sp_high, depthDeco, first;
-        // uint8_t active,
+        uint8_t spId, setpoint_cbar, depthDeco, first;
         char text[70];
         uint8_t textPointer;
         uint16_t y_line;
 
-        if(line < 6)
-        {
+        if ((!settings->autoSetpoint && line <= 5) || line <= SETPOINT_INDEX_AUTO_DECO) {
 			set_globalState_Menu_Line(line);
 
 			resetMenuEdit(CLUT_MenuPageGasSP);
 
 			spId = line;
 			editSetpointPage.spID = spId;
-			SSettings *data = settingsGetPointer();
-			editSetpointPage.pSetpointLine = data->setpoint;
+			editSetpointPage.pSetpointLine = settings->setpoint;
 
 			setpoint_cbar = editSetpointPage.pSetpointLine[spId].setpoint_cbar;
 			depthDeco = editSetpointPage.pSetpointLine[spId].depth_meter;
-			//active = editSetpointPage.pSetpointLine[spId].note.ub.active;
 			first = editSetpointPage.pSetpointLine[spId].note.ub.first;
 
-			sp_high = setpoint_cbar / 100;
+			uint8_t setpointBar = setpoint_cbar / 100;
 
-			strcpy(text, "\001" "Setpoint #0 X");
-			text[11] += spId;
-			text[13] = TXT_Setpoint_Edit;
+			textPointer = snprintf(text, 20, "\001%c%c ", TXT_2BYTE, TXT2BYTE_Setpoint);
+            textPointer += printSetpointName(&text[textPointer], line, settings, false);
+            snprintf(&text[textPointer], 20, " %c", TXT_Setpoint_Edit);
 			write_topline(text);
 
-
 			y_line = ME_Y_LINE_BASE + (line * ME_Y_LINE_STEP);
 
-			textPointer = 0;
-			text[textPointer++] = 'S';
-			text[textPointer++] = 'P';
-			text[textPointer++] = '0' + spId;
-			text[textPointer++] = ' ';
-			text[textPointer++] = ' ';
+			textPointer = snprintf(text, 4, "%c%c", TXT_2BYTE, TXT2BYTE_SetpointShort);
+            textPointer += printSetpointName(&text[textPointer], line, settings, true);
+            textPointer += snprintf(&text[textPointer], 60, "  %s*        \016\016 bar\017", first ? "" : "\177");
 
-			if(first == 0)
-				strcpy(&text[textPointer++],"\177");
+            if (settings->autoSetpoint && line == SETPOINT_INDEX_AUTO_DECO) {
+                textPointer += snprintf(&text[textPointer], 4, "\n\r");
+			    write_label_var(20, 800, y_line, &FontT48, text);
+
+			    write_field_udigit(StMSP_ppo2_setting, 160, 800, y_line, &FontT48, "#.##", (uint32_t)setpointBar, (uint32_t)(setpoint_cbar - (100 * setpointBar)), settings->setpoint[line].note.ub.active, 0);
 
-			textPointer += snprintf(&text[textPointer], 60,\
-				"* "
-				"       "
-				"\016\016"
-				" bar"
-				"\017"
-				"\034"
-				"   "
-				"\016\016"
-				" "
-				"\017"
-				"           "
-				"\016\016"
-				"meter"
-				"\017"
-				"\035"
-				"\n\r"
-			);
-			write_label_var(  20, 800, y_line, &FontT48, text);
+                snprintf(text, 60, "\034        \035%c%c\n\r", TXT_2BYTE, TXT2BYTE_Enabled);
+			    write_label_var(20, 800, y_line + ME_Y_LINE_STEP, &FontT48, text);
+                write_field_select(StMSP_Active, 160, 800, y_line + ME_Y_LINE_STEP, &FontT48, "#", settings->setpoint[line].note.ub.active, 0, 0, 0);
+            } else {
+                textPointer += snprintf(&text[textPointer], 40, "\034   \016\016 \017           \016\016meter\017\035\n\r");
+			    write_label_var(20, 800, y_line, &FontT48, text);
+			    write_field_udigit(StMSP_ppo2_setting,	160, 800, y_line, &FontT48, "#.##            ###", (uint32_t)setpointBar, (uint32_t)(setpoint_cbar - (100 * setpointBar)), depthDeco, 0);
+            }
+			setEvent(StMSP_ppo2_setting, (uint32_t)OnAction_SP_Setpoint);
+			setEvent(StMSP_Active, (uint32_t)OnAction_SP_SetpointActive);
+			startEdit();
+		} else if (line == 5) {
+            settings->delaySetpointLow = !settings->delaySetpointLow;
 
-			write_field_udigit(StMSP_ppo2_setting,	160, 800, y_line, &FontT48, "#.##            ###", (uint32_t)sp_high, (uint32_t)(setpoint_cbar - (100 * sp_high)), depthDeco, 0);
-			setEvent(StMSP_ppo2_setting,	(uint32_t)OnAction_SP_Setpoint);
-			startEdit();
-		}
-        else
-        {
-            SSettings *pSettings = settingsGetPointer();
+            exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only();
+        } else if (line == 6) {
+            settings->autoSetpoint = (settings->autoSetpoint + 1) % 2;
 
-            if(pSettings->autoSetpoint == 0)
-            {
-                pSettings->autoSetpoint = 1;
-            }
-            else
-            {
-                pSettings->autoSetpoint = 0;
-            }
+            checkAndFixSetpointSettings();
+
             exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only();
         }
     }
@@ -283,6 +302,8 @@
 
 static uint8_t OnAction_SP_Setpoint(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
+	SSettings *settings = settingsGetPointer();
+
     int8_t digitContentNew;
     uint32_t new_integer_part, new_fractional_part, new_cbar, newDepth;
 
@@ -306,12 +327,22 @@
 
         editSetpointPage.pSetpointLine[editSetpointPage.spID].setpoint_cbar = new_cbar;
 
-        if(newDepth > 255)
-            newDepth = 255;
+        if (settings->autoSetpoint && editSetpointPage.spID == SETPOINT_INDEX_AUTO_DECO) {
+            tMenuEdit_newInput(editId, new_integer_part, new_fractional_part, newDepth, 0);
+
+            checkAndFixSetpointSettings();
 
-        editSetpointPage.pSetpointLine[editSetpointPage.spID].depth_meter = newDepth;
+            return EXIT_TO_NEXT_MENU;
+        } else {
+            if (newDepth > 255) {
+                newDepth = 255;
+            }
 
-        return UPDATE_AND_EXIT_TO_MENU;
+            editSetpointPage.pSetpointLine[editSetpointPage.spID].depth_meter = newDepth;
+            checkAndFixSetpointSettings();
+
+            return UPDATE_AND_EXIT_TO_MENU;
+        }
     }
 
     if(action == ACTION_BUTTON_NEXT)
@@ -340,25 +371,11 @@
 void openEdit_DiveSelectBetterSetpoint(bool useLastDiluent)
 {
     uint8_t spId;
-    uint8_t depth;
 
     if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR)		/* no setpoints in PSCR mode */
     {
 		spId = actualBetterSetpointId();
 
-		depth = stateUsedWrite->diveSettings.setpoint[spId].depth_meter;
-
-		// BetterSetpoint warning only once -> clear active
-		for(int i=0; i<=NUM_GASES; i++)
-		{
-			stateUsedWrite->diveSettings.setpoint[i].note.ub.first = 0;
-			if(stateUsedWrite->diveSettings.setpoint[i].depth_meter <= depth)
-				stateUsedWrite->diveSettings.setpoint[i].note.ub.active = 0;
-		}
-
-		// new setpoint
-		stateUsedWrite->diveSettings.setpoint[spId].note.ub.first = 1;
-
         uint8_t gasId;
         if (useLastDiluent) {
             gasId = stateUsed->lifeData.lastDiluent_GasIdInSettings;
@@ -375,12 +392,36 @@
 bool findSwitchToSetpoint(void)
 {
     uint8_t setpointLowId = getSetpointLowId();
+    uint8_t setpointLowCBar = 0;
+    if (setpointLowId) {
+        setpointLowCBar = stateUsed->diveSettings.setpoint[setpointLowId].setpoint_cbar;
+    }
+
     uint8_t setpointHighId = getSetpointHighId();
+    uint8_t setpointHighCBar = 0;
+    if (setpointHighId) {
+        setpointHighCBar = stateUsed->diveSettings.setpoint[setpointHighId].setpoint_cbar;
+    }
+
+    uint8_t setpointDecoId = getSetpointDecoId();
+    uint8_t setpointDecoCBar = 0;
+    if (setpointDecoId) {
+        setpointDecoCBar = stateUsed->diveSettings.setpoint[setpointDecoId].setpoint_cbar;
+    }
+    uint8_t nextDecoStopDepthM;
+    uint16_t nextDecoStopTimeRemainingS;
+    const SDecoinfo *decoInfo = getDecoInfo();
+    tHome_findNextStop(decoInfo->output_stop_length_seconds, &nextDecoStopDepthM, &nextDecoStopTimeRemainingS);
+
     uint8_t setpointCurrentCbar = stateUsed->lifeData.actualGas.setPoint_cbar;
-    if (setpointLowId && setpointCurrentCbar != stateUsed->diveSettings.setpoint[setpointLowId].setpoint_cbar && ((!setpointHighId || setpointCurrentCbar == stateUsed->diveSettings.setpoint[setpointHighId].setpoint_cbar) || stateUsed->lifeData.depth_meter < stateUsed->diveSettings.setpoint[setpointLowId].depth_meter)) {
-        switchToSetpointCbar = stateUsed->diveSettings.setpoint[setpointLowId].setpoint_cbar;
-    } else if (setpointHighId && setpointCurrentCbar != stateUsed->diveSettings.setpoint[setpointHighId].setpoint_cbar) {
-        switchToSetpointCbar = stateUsed->diveSettings.setpoint[setpointHighId].setpoint_cbar;
+
+    // We cycle SPdeco => SPhigh => SPlow => SPdeco when we have a decompression obligation
+    if (setpointDecoCBar && setpointCurrentCbar != setpointDecoCBar && nextDecoStopDepthM && setpointCurrentCbar != setpointHighCBar) {
+        switchToSetpointCbar = setpointDecoCBar;
+    } else if (setpointLowCBar && setpointCurrentCbar != setpointLowCBar && (!setpointHighCBar || setpointCurrentCbar == setpointHighCBar || stateUsed->lifeData.depth_meter < stateUsed->diveSettings.setpoint[setpointLowId].depth_meter)) {
+        switchToSetpointCbar = setpointLowCBar;
+    } else if (setpointHighCBar && setpointCurrentCbar != setpointHighCBar) {
+        switchToSetpointCbar = setpointHighCBar;
     } else {
         // We don't have a setpoint to switch to
         switchToSetpointCbar = 0;
--- a/Discovery/Src/tMenuSetpoint.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/tMenuSetpoint.c	Tue Jul 04 14:39:06 2023 +0200
@@ -28,6 +28,7 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "tMenu.h"
+#include "tMenuEditSetpoint.h"
 #include "tMenuSetpoint.h"
 #include "unit.h"
 
@@ -35,17 +36,16 @@
 
 /* Exported functions --------------------------------------------------------*/
 
-uint32_t tMSP_refresh(uint8_t line,
-                      char *text,
-                      uint16_t *tab,
-                      char *subtext)
+uint32_t tMSP_refresh(char *text, uint16_t *tab, char *subtext)
 {
+    SSettings *settings = settingsGetPointer();
+
     const SSetpointLine * pSetpointLine;
 
-    uint8_t textPointer, setpoint_cbar, sp_high, depthUp, first; //  active
+    uint8_t textPointer, setpoint_cbar, depthUp, first;
 
     if(actual_menu_content == MENU_SURFACE)
-        pSetpointLine = settingsGetPointer()->setpoint;
+        pSetpointLine = settings->setpoint;
     else
         pSetpointLine = stateUsed->diveSettings.setpoint;
 
@@ -57,78 +57,50 @@
     {
 		for(int spId=1;spId<=NUM_GASES;spId++)
 		{
-			if(line && (line != spId))
-			{
-					first = pSetpointLine[spId].note.ub.first;
-					if(first == 0)
-					{
-						strcpy(&text[textPointer],
-							"\t"
-							"\177"
-							"*"
-							"\n\r"
-						);
-						textPointer += 5;
-					}
-					else
-					{
-						strcpy(&text[textPointer],"\n\r");
-						textPointer += 2;
-					}
-			}
-			else
-			{
-				setpoint_cbar = pSetpointLine[spId].setpoint_cbar;
-				depthUp = pSetpointLine[spId].depth_meter;
-				//active = pSetpointLine[spId].note.ub.active;
-				first = pSetpointLine[spId].note.ub.first;
+            if (settings->autoSetpoint) {
+                if (actual_menu_content == MENU_SURFACE && spId == 5) {
+                    textPointer += snprintf(&text[textPointer], 40, "\020%c%c\016\016%c%c\017 %c%c\002%c\n\r", TXT_2BYTE, TXT2BYTE_SetpointShort, TXT_2BYTE, TXT2BYTE_SetpointLow, TXT_2BYTE, TXT2BYTE_SetpointDelayed, settings->delaySetpointLow ? '\005' : '\006');
+                    continue;
+                } else if (spId > SETPOINT_INDEX_AUTO_DECO) {
+                    textPointer += snprintf(&text[textPointer], 3, "\n\r");
 
-				strcpy(&text[textPointer],"\020"); // if(active) always active
-				textPointer += 1;
+                    continue;
+                }
+            }
 
-				sp_high = setpoint_cbar / 100;
+			setpoint_cbar = pSetpointLine[spId].setpoint_cbar;
+			depthUp = pSetpointLine[spId].depth_meter;
+			first = pSetpointLine[spId].note.ub.first;
+
+            if (settings->autoSetpoint && spId == SETPOINT_INDEX_AUTO_DECO  && !pSetpointLine[spId].note.ub.active) {
+			    strcpy(&text[textPointer++],"\031");
+            } else {
+			    strcpy(&text[textPointer++],"\020");
+            }
 
-				text[textPointer++] = 'S';
-				text[textPointer++] = 'P';
-				text[textPointer++] = '0' + spId;
-				text[textPointer++] = '\t';
+			uint8_t setpointBar = setpoint_cbar / 100;
 
-				if((first == 0) || (actual_menu_content != MENU_SURFACE))
-					strcpy(&text[textPointer++],"\177");
+            textPointer += snprintf(&text[textPointer], 4, "%c%c", TXT_2BYTE, TXT2BYTE_SetpointShort);
+            textPointer += printSetpointName(&text[textPointer], spId, settings, true);
+			text[textPointer++] = '\t';
 
-				char color = '\031';
-				if(depthUp)
-					color = '\020';
+			if (first == 0 || actual_menu_content != MENU_SURFACE) {
+				strcpy(&text[textPointer++],"\177");
+            }
 
-				textPointer += snprintf(&text[textPointer], 57,
-					"* "
-					"%u.%02u"
-					"\016\016"
-					" bar"
-					"\017"
-					"\034"
-					"   "
-					"\016\016"
-					" "
-					"\017"
-					"%c"
-					"%3u"
-					"\016\016"
-					" %c%c"
-					"\017"
-					"\035"
-					"\n\r",
-					sp_high, setpoint_cbar - (100 * sp_high),
-					color,
-					unit_depth_integer(depthUp),
-					unit_depth_char1(),
-					unit_depth_char2()
-				);
-			}
+			textPointer += snprintf(&text[textPointer], 40, "* %u.%02u\016\016 bar\017\034   \016\016 \017", setpointBar, setpoint_cbar - (100 * setpointBar));
+            if (!settings->autoSetpoint || spId < SETPOINT_INDEX_AUTO_DECO) {
+			    char color = '\031';
+			    if(depthUp)
+				    color = '\020';
+
+			    textPointer += snprintf(&text[textPointer], 40, "%c%3u\016\016 %c%c\017\035\n\r", color, unit_depth_integer(depthUp), unit_depth_char1(), unit_depth_char2());
+            } else {
+			    textPointer += snprintf(&text[textPointer], 3, "\n\r");
+            }
 		}
     }
-    if((actual_menu_content != MENU_SURFACE) /*&& (line == 0)*/)
-    {
+    if (actual_menu_content != MENU_SURFACE) {
         text[textPointer++] = '\020';
         text[textPointer++] = TXT_2BYTE;
         text[textPointer++] = TXT2BYTE_UseSensor;
@@ -138,7 +110,7 @@
 
         if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR)
         {
-        	textPointer += snprintf(&text[textPointer], 20,"\020%c", TXT_SimPpo2);
+            textPointer += snprintf(&text[textPointer], 20,"\020%c", TXT_SimPpo2);
         }
         text[textPointer++] = 0;
     }
@@ -148,7 +120,7 @@
         text[textPointer++] = TXT_2BYTE;
         text[textPointer++] = TXT2BYTE_AutomaticSP;
         text[textPointer++] = '\002';
-        if(settingsGetPointer()->autoSetpoint)
+        if (settings->autoSetpoint)
                     text[textPointer++] = '\005';
                 else
                     text[textPointer++] = '\006';
--- a/Discovery/Src/text_multilanguage.c	Sun Jun 04 21:59:26 2023 +0200
+++ b/Discovery/Src/text_multilanguage.c	Tue Jul 04 14:39:06 2023 +0200
@@ -1847,6 +1847,36 @@
 static uint8_t text_IT_SetpointShort[] = "SP";
 static uint8_t text_ES_SetpointShort[] = "SP";
 
+static uint8_t text_EN_SetpointLow[] = "low";
+static uint8_t text_DE_SetpointLow[] = "tief";
+static uint8_t text_FR_SetpointLow[] = "low";
+static uint8_t text_IT_SetpointLow[] = "low";
+static uint8_t text_ES_SetpointLow[] = "low";
+
+static uint8_t text_EN_SetpointHigh[] = "high";
+static uint8_t text_DE_SetpointHigh[] = "hoch";
+static uint8_t text_FR_SetpointHigh[] = "high";
+static uint8_t text_IT_SetpointHigh[] = "high";
+static uint8_t text_ES_SetpointHigh[] = "high";
+
+static uint8_t text_EN_SetpointDeco[] = "deco";
+static uint8_t text_DE_SetpointDeco[] = "deko";
+static uint8_t text_FR_SetpointDeco[] = "deco";
+static uint8_t text_IT_SetpointDeco[] = "deco";
+static uint8_t text_ES_SetpointDeco[] = "deco";
+
+static uint8_t text_EN_SetpointDelayed[] = "delayed until deco clear";
+static uint8_t text_DE_SetpointDelayed[] = "erst wenn Deko beendet";
+static uint8_t text_FR_SetpointDelayed[] = "delayed until deco clear";
+static uint8_t text_IT_SetpointDelayed[] = "delayed until deco clear";
+static uint8_t text_ES_SetpointDelayed[] = "delayed until deco clear";
+
+static uint8_t text_EN_Enabled[] = "enabled";
+static uint8_t text_DE_Enabled[] = "aktiv";
+static uint8_t text_FR_Enabled[] = "activé";
+static uint8_t text_IT_Enabled[] = "abilitato";
+static uint8_t text_ES_Enabled[] = "activado";
+
 /* Lookup Table -------------------------------------------------------------*/
 
 const tText text_array[] =
@@ -2120,6 +2150,13 @@
 	{(uint8_t)TXT2BYTE_LoopShort, 	{text_EN_LoopShort, text_DE_LoopShort, text_FR_LoopShort, text_IT_LoopShort, text_ES_LoopShort}},
 	{(uint8_t)TXT2BYTE_SetpointShort, 	{text_EN_SetpointShort, text_DE_SetpointShort, text_FR_SetpointShort, text_IT_SetpointShort, text_ES_SetpointShort}},
 
+	{(uint8_t)TXT2BYTE_SetpointLow, 	{text_EN_SetpointLow, text_DE_SetpointLow, text_FR_SetpointLow, text_IT_SetpointLow, text_ES_SetpointLow}},
+	{(uint8_t)TXT2BYTE_SetpointHigh, 	{text_EN_SetpointHigh, text_DE_SetpointHigh, text_FR_SetpointHigh, text_IT_SetpointHigh, text_ES_SetpointHigh}},
+	{(uint8_t)TXT2BYTE_SetpointDeco, 	{text_EN_SetpointDeco, text_DE_SetpointDeco, text_FR_SetpointDeco, text_IT_SetpointDeco, text_ES_SetpointDeco}},
+	{(uint8_t)TXT2BYTE_SetpointDelayed, 	{text_EN_SetpointDelayed, text_DE_SetpointDelayed, text_FR_SetpointDelayed, text_IT_SetpointDelayed, text_ES_SetpointDelayed}},
+
+	{(uint8_t)TXT2BYTE_Enabled, 	{text_EN_Enabled, text_DE_Enabled, text_FR_Enabled, text_IT_Enabled, text_ES_Enabled}},
+
 	{(uint8_t)TXT2BYTE_Set, 	{text_EN_Set, text_DE_Set, text_FR_Set, text_IT_Set, text_ES_Set}},
 	{(uint8_t)TXT2BYTE_Clear, 	{text_EN_Clear, text_DE_Clear, text_FR_Clear, text_IT_Clear, text_ES_Clear}},
 	{(uint8_t)TXT2BYTE_Reset, 	{text_EN_Reset, text_DE_Reset, text_FR_Reset, text_IT_Reset, text_ES_Reset}},