changeset 969:81049905d829 Evo_2_23

Zusammenf?hren
author heinrichsweikamp
date Sun, 19 Jan 2025 12:02:59 +0100 (3 weeks ago)
parents b9a1710522b1 (current diff) 9b418e63dbc2 (diff)
children 3123aa8723fd
files Discovery/Src/settings.c Discovery/Src/text_multilanguage.c Small_CPU/Src/baseCPU2.c
diffstat 39 files changed, 563 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/BootLoader/CPU1-F429_boot.ld	Sun Jan 19 12:00:50 2025 +0100
+++ b/BootLoader/CPU1-F429_boot.ld	Sun Jan 19 12:02:59 2025 +0100
@@ -188,7 +188,10 @@
  	KEEP( *(.bootloader_firmware_data) )
  } > ROM_BOOT
  
- 
+  .bootloader_hardware_data 0x0800A040 : {
+  	PROVIDE( bootloader_HardwareData = . );
+ 	KEEP( *(.bootloader_hardware_data) )
+ } > ROM_BOOT
  
   .text 0x08001000 :
   {
--- a/BootLoader/Src/base_bootlader.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/BootLoader/Src/base_bootlader.c	Sun Jan 19 12:02:59 2025 +0100
@@ -39,7 +39,7 @@
 	==============================================================================
 
 	151130	hw	sleep on button3
-								(MX_tell_reset_logik_alles_ok() + DataEX_call() in endlos loop)
+								(MX_tell_reset_logik_alles_ok() + DataEX_call() in endless loop)
 
 	==============================================================================
 							##### bootloader specific #####
@@ -89,7 +89,7 @@
 	==============================================================================
 							##### MainTask #####
 	==============================================================================
-	[..] For everthing slow without importance to be 'in time'.
+	[..] For everything slow without importance to be 'in time'.
 			 Like VPM and Buehlmann.
 			 No sprintf and probably no GFX_SetFramesTopBottom() stuff neither.
 			 If sprintf is called while sprintf is executed it blows up everything.
@@ -99,7 +99,7 @@
 	==============================================================================
 	[..] The SDRAM is handled by getFrame() and releaseFrame().
 			 Each frame with 800*480*2 Bytes.
-			 Be carefull to release every frame
+			 Be careful to release every frame
 			 otherwise there will be a memory leakage over time.
 			 housekeepingFrame() in the MainTask takes care of cleaning the frames.
 			 All frames are filled with 0x00. This will be transparent with color of
@@ -127,7 +127,7 @@
 						GFX_SetFrameTop() + GFX_SetFrameBottom()
 						Those do not change anything on the display but give commands to..
 				(#) GFX_change_LTDC()	The only place that changes the pointer.
-															This prevents erratic behaviour if several changes
+															This prevents erratic behavior if several changes
 															are made within one refresh rate of the screen.
 															Is called in IRQ by PD4 and HAL_GPIO_EXTI_IRQHandler
 															from VSYNC signal.
@@ -142,7 +142,7 @@
 										with automatic language switch by
 										selected_language in SSettings
 										see openEdit_Language() in tMenuEditSystem.c
-										Therefore there are differnent functions
+										Therefore there are different functions
 										for example:
 										write_label_fix() for single char multilanguage
 										write_label_var() for strings that could include
@@ -265,11 +265,11 @@
 		.versionBeta    = 1,
 
 	/* 4 bytes with trailing 0 */
-	.signature = "cw",
+	.signature = "mh",
 
-	.release_year   = 16,
-	.release_month  = 4,
-	.release_day    = 8,
+	.release_year   = 25,
+	.release_month  = 1,
+	.release_day    = 13,
 	.release_sub    = 0,
 
 	/* max 48 with trailing 0 */
@@ -282,24 +282,29 @@
 	.magic[3] = FIRMWARE_MAGIC_END
 };
 
-#if 0
-const SHardwareData HardwareData __attribute__((at(HARDWAREDATA_ADDRESS))) = {
+const SHardwareData HardwareData __attribute__((section(".bootloader_hardware_data"))) =
+{
 
 	// first 52 bytes
 	.primarySerial = 0xFFFF,
-	.primaryLicence	= 0xFF,
-	.revision8bit = 0xFF,
-	.production_year = 0xFF,
-	.production_month = 0xFF,
-	.production_day = 0xFF,
+	.primaryLicence	= 0x00,
+	.revision8bit = 0x02,
+	.production_year = 0x19,
+	.production_month = 0x01,
+	.production_day = 0x10,
 	.production_bluetooth_name_set = 0xFF,
 
 	.production_info = {
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+		0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4F,0x53,0x54,0x43,
+		0x20,0x35,0x20,0x65,0x6E,0x64,0x2D,0x32,0x30,0x32,0x34,
+		0x20,0x68,0x61,0x72,0x64,0x77,0x61,0x72,0x65,0x20,0x20,
+		0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
+
+/*		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
 		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
 		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
 		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
-
+*/
 	// other 12 bytes (64 in total)
 	.secondarySerial = 0xFFFF,
 	.secondaryLicence = 0xFF,
@@ -310,7 +315,7 @@
 	.secondary_bluetooth_name_set = 0xFF,
 	.secondary_info = {0xFF,0xFF,0xFF,0xFF}
 };
-#endif
+
 
 RTC_HandleTypeDef	RtcHandle;
 TIM_HandleTypeDef   TimHandle; /* used in stm32f4xx_it.c too */
@@ -441,12 +446,6 @@
 
 	MX_GPIO_Init();
 
-	/* feedback for the user
-	 * aber sehr unsch�n beim Warmstart
-	 * da das letzte Bild noch lange nachleuchtet */
-//	MX_GPIO_Backlight_max_static_only_Init();
-
-
 	/* button press is only 40 to 50 us low */
 	MX_GPIO_One_Button_only_Init();
 
@@ -588,7 +587,7 @@
 	/* here comes the variable upper firmware loader */
 	if((i == 0) && (status == HAL_OK))
 	{
-		tInfo_newpage("load firmware2 data");
+		tInfo_newpage("load fontpack data");
 		uint8_t* pBuffer = (uint8_t*)((uint32_t)0xD0000000); /* blocked via  GFX_init1_no_DMA */
 		firmware_load_result = ext_flash_read_firmware2(&pOffset, pBuffer,768000*2,0,0);
 
@@ -660,11 +659,11 @@
 
 	if((i == 0) && (status == HAL_OK))
 	{
-		tInfo_newpage("Done.");
-		tInfo_write("Cleaning.");
+		tInfo_newpage("done.");
+		tInfo_write("cleaning.");
 		ext_flash_erase_firmware_if_not_empty();
 		ext_flash_erase_firmware2_if_not_empty();
-		tInfo_write("Reset device.");
+		tInfo_write("reset device.");
 		reset_to_firmware_using_Watchdog();
 	}
 
@@ -709,19 +708,19 @@
 	MX_Bluetooth_PowerOn();
 	tComm_init();
 
-	tInfo_button_text("Exit","","Sleep");
-	tInfo_newpage("Bootloader 240812");
+	tInfo_button_text("exit","","sleep");
+	tInfo_newpage("bootloader 250113");
 	tInfo_write("start bluetooth");
 	tInfo_write("");
 	tInfo_write(textVersion);
 	if(tComm_Set_Bluetooth_Name(0) == 0xFF)
 	{
-		tInfo_write("Init bluetooth");
+		tInfo_write("init bluetooth");
 		tComm_StartBlueModBaseInit();
 	}
 	else
 	{
-		tInfo_write("Bluetooth set");
+		tInfo_write("bluetooth set");
 		tComm_StartBlueModConfig();
 	}
 
@@ -775,7 +774,7 @@
 		tComm_exit();
 		returnFromCommCleanUpRequest = 0;
 		GFX_hwBackgroundOn();
-		tInfo_button_text("Exit","","Sleep");
+		tInfo_button_text("exit","","sleep");
 		tInfo_newpage("bluetooth disonnected");
 		tInfo_write("");
 		tInfo_write("");
@@ -821,13 +820,13 @@
 	if(GFX_logoStatus() != 0)
 		return;
 
-	if(GPIO_Pin == BUTTON_BACK_PIN) // links
+	if(GPIO_Pin == BUTTON_BACK_PIN) // left
 		action = ACTION_BUTTON_BACK;
 	else
-	if(GPIO_Pin == BUTTON_ENTER_PIN) // mitte
+	if(GPIO_Pin == BUTTON_ENTER_PIN) // center
 		action = ACTION_BUTTON_ENTER;
 	else
-	if(GPIO_Pin == BUTTON_NEXT_PIN) // rechts
+	if(GPIO_Pin == BUTTON_NEXT_PIN) // right
 		action = ACTION_BUTTON_NEXT;
 #ifdef BUTTON_CUSTOM_PIN
 	else
@@ -1252,7 +1251,7 @@
 }
 
 /**
-	* @brief  Perform the SDRAM exernal memory inialization sequence
+	* @brief  Perform the SDRAM external memory initialization sequence
 	* @param  hsdram: SDRAM handle
 	* @param  Command: Pointer to SDRAM command structure
 	* @retval None
@@ -1316,7 +1315,7 @@
 static void DualBoot(void)
 {
 		// Set BFB2 bit to enable boot from Flash Bank2
-		// Allow Access to Flash control registers and user Falsh
+		// Allow Access to Flash control registers and user Flash
 		HAL_FLASH_Unlock();
 
 		// Allow Access to option bytes sector
@@ -1366,7 +1365,7 @@
 
 /**
 	* @brief DMA2D configuration.
-	* @note  This function Configure tha DMA2D peripheral :
+	* @note  This function Configure the DMA2D peripheral :
 	*        1) Configure the transfer mode : memory to memory W/ pixel format conversion
 	*        2) Configure the output color mode as ARGB4444
 	*        3) Configure the output memory address at SRAM memory
--- a/Common/Inc/data_central.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Common/Inc/data_central.h	Sun Jan 19 12:02:59 2025 +0100
@@ -44,6 +44,10 @@
 #define EXT_INTERFACE_SENSOR_CNT	(8u)		/* 1 MUX + 7 sensors may be connected to the external interface (1 MUX + 3 ADC + 4 UART) */
 #define EXT_INTERFACE_MUX_OFFSET	(3u)		/* the sensor struct starts with 3 ADC sensors */
 
+#define EXT_INTERFACE_BUZZER_ON_TIME_MS (2000u)		/* max time the buzzer should be active without break */
+#define EXT_INTERFACE_BUZZER_STABLE_TIME_MS (500u)	/* min time a state (ON / OFF) should be stable before it may be changed */
+
+
 /* Helper structs ------------------------------------------------------------*/
 
 //struct SGas
--- a/Common/Inc/data_exchange.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Common/Inc/data_exchange.h	Sun Jan 19 12:02:59 2025 +0100
@@ -33,11 +33,12 @@
 
 /* Command definitions for control of external interface */
 /* 1st nibble binary on/off states */
-/* 2nd nibble UART protocol selection */
-/* 3rd nibble reserve */
-/* 4th nibble command channel */
+/* 2nd nibble target sensor ID (if sensor command is active) */
+/* 3rd nibble sensor commands */
+/* 4th nibble control channel */
 #define EXT_INTERFACE_33V_ON		(0x8000u)	/* Bit set to enable 3.3V power interface */
 #define EXT_INTERFACE_ADC_ON		(0x4000u)	/* Bit set to enable ADC conversion */
+#define EXT_INTERFACE_BUZZER_ON		(0x2000u)	/* Bit set to enable the buzzer */
 
 /* Command subset */
 #define EXT_INTERFACE_AUTODETECT 	(0x0001u)	/* Start auto detection of connected sensors	*/
@@ -55,6 +56,7 @@
 
 #define GNSS_ALIVE_STATE_ALIVE		(0x01u)		/* Communication to module active */
 #define GNSS_ALIVE_STATE_TIME		(0x02u)		/* Time information valid */
+#define GNSS_ALIVE_BACKUP_POS		(0x04u)		/* Backup position not older than x hours */
 
 enum MODE
 {
--- a/Common/Inc/settings.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Common/Inc/settings.h	Sun Jan 19 12:02:59 2025 +0100
@@ -324,6 +324,7 @@
 	uint8_t slowExitTime;
 	/* new in 0xFFFF002c */
 	StimeZone timeZone;
+	uint8_t warningBuzzer;
 } SSettings;
 
 typedef struct
--- a/Discovery/Inc/check_warning.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Inc/check_warning.h	Sun Jan 19 12:02:59 2025 +0100
@@ -45,4 +45,6 @@
 uint8_t getSetpointHighId(void);
 uint8_t getSetpointLowId(void);
 uint8_t getSetpointDecoId(void);
+void requestBuzzerActivation(uint8_t active);
+uint8_t getBuzzerActivationState();
 #endif // CHECK_WARNING_H
--- a/Discovery/Inc/data_exchange_main.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Inc/data_exchange_main.h	Sun Jan 19 12:02:59 2025 +0100
@@ -56,6 +56,6 @@
 
 uint16_t DataEX_debug_data(uint16_t *dataOut20x5);
 
-void DataEX_setExtInterface_Cmd(uint16_t Cmd);
+void DataEX_setExtInterface_Cmd(uint16_t Cmd,uint8_t sensorId);
 
 #endif /* DATA_EXCHANGE_MAIN_H */
--- a/Discovery/Inc/tStructure.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Inc/tStructure.h	Sun Jan 19 12:02:59 2025 +0100
@@ -204,9 +204,10 @@
 /* DIVE MODE */
 #define StMXTRA_ResetStopwatch	_MB(2,4,1,1,0)
 #define StMXTRA_CompassHeading	_MB(2,4,2,1,0)
-#define StMXTRA_CompassHeadingClear	_MB(2,4,2,2,0)
-#define StMXTRA_CompassHeadingReset	_MB(2,4,2,3,0)
-#define StMXTRA_CompassHeadingLog	_MB(2,4,2,4,0)
+#define StMXTRA_CompassHeadingReverse	_MB(2,4,2,2,0)
+#define StMXTRA_CompassHeadingClear	_MB(2,4,2,3,0)
+#define StMXTRA_CompassHeadingReset	_MB(2,4,2,4,0)
+#define StMXTRA_CompassHeadingLog	_MB(2,4,2,5,0)
 
  /* SURFACE MODE */
 
@@ -382,12 +383,16 @@
 
 #define StMCustom4_CViewSelection1	_MB(2,9,4,1,0)
 
+#ifdef ENABLE_MOTION_CONTROL
 #define StMCustom5_CViewPortCalib	_MB(2,9,5,1,0)
 #define StMCustom5_CViewPortSpotSize _MB(2,9,5,2,0)
 #define StMCustom5_CViewPortLayout	_MB(2,9,5,3,0)
 #define StMCustom5_CViewPortAmbient	_MB(2,9,5,4,0)
 #define StMCustom5_CViewPortControl	_MB(2,9,5,5,0)
-
+#endif
+#ifdef ENABLE_GPIO_V2
+#define StMCustom5_CViewWarningBuz	_MB(2,9,5,1,0)
+#endif
 
 /* PAGE 10 */
 #define StMPLAN		_MB(2,10,0,0,0)
--- a/Discovery/Inc/text_multilanguage.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Inc/text_multilanguage.h	Sun Jan 19 12:02:59 2025 +0100
@@ -387,12 +387,15 @@
 
         TXT2BYTE_Current,
         TXT2BYTE_Log,
+        TXT2BYTE_Reverse,
 
 		TXT2BYTE_DDMMYY,
 		TXT2BYTE_MMDDYY,
 		TXT2BYTE_YYMMDD,
 		TXT2BYTE_TIMEZONE,
 
+		TXT2BYTE_BUZZER,
+
 		TXT2BYTE_END,
 };
 
--- a/Discovery/Src/check_warning.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/check_warning.c	Sun Jan 19 12:02:59 2025 +0100
@@ -43,6 +43,7 @@
 
 
 #define DEBOUNCE_FALLBACK_TIME_MS	(5000u)		/* set warning after 5 seconds of pending error condition */
+#define GUI_BUZZER_TIMEOUT_MS		(200u)      /* the buzzer should be active while Warning string is shown, but diver may be in a menu... */
 
 #define SETPOINT_DECO_START_RANGE_M 3.0
 #define SWITCH_DEPTH_LOW_MINIMUM_M 1.0
@@ -53,6 +54,7 @@
 static uint8_t betterSetpointId = 1;
 static int8_t fallback = 0;
 static uint16_t debounceFallbackTimeMS = 0;
+static uint8_t buzzerRequestActive = 0;
 
 /* Private function prototypes -----------------------------------------------*/
 static int8_t check_fallback(SDiveState * pDiveState);
@@ -75,9 +77,66 @@
 #ifdef HAVE_DEBUG_WARNINGS
 static int8_t check_debug(SDiveState * pDiveState);
 #endif
+static uint8_t buzzerOn = 0;			/* current state of the buzzer */
 
+static void setBuzzer(int8_t warningActive);
+/* Exported functions --------------------------------------------------------*/
+
+void requestBuzzerActivation(uint8_t active)
+{
+	buzzerRequestActive = active;
+}
+
+uint8_t getBuzzerActivationState()
+{
+	return buzzerOn;
+}
+
+static void setBuzzer(int8_t warningActive)
+{
+	static uint32_t guiTimeoutCnt = 0;		/* max delay till buzzer will be activated independend from gui request */
+	static uint32_t stateTick = 0;			/* activation tick of current state */
+	static uint8_t lastWarningState = 0;	/* the parameter value of the last call*/
+
+	uint32_t tick =  HAL_GetTick();
 
-/* Exported functions --------------------------------------------------------*/
+	if(warningActive)
+	{
+		if(!lastWarningState)				/* init structures */
+		{
+			guiTimeoutCnt = tick;
+			stateTick = tick;
+		}
+		if(buzzerOn)
+		{
+			if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS)	/* buzzer has to be on for a certain time */
+			{
+				if((!buzzerRequestActive) || (time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS))
+				{
+					buzzerOn = 0;
+					stateTick = tick;
+					guiTimeoutCnt = tick;
+				}
+			}
+		}
+		else
+		{
+			if(time_elapsed_ms(stateTick, tick) > EXT_INTERFACE_BUZZER_STABLE_TIME_MS)	/* buzzer has to be off for a certain time */
+			{
+				if((buzzerRequestActive) || (time_elapsed_ms(guiTimeoutCnt, tick) > EXT_INTERFACE_BUZZER_ON_TIME_MS + GUI_BUZZER_TIMEOUT_MS))
+				{
+					buzzerOn = 1;
+					stateTick = tick;
+				}
+			}
+		}
+	}
+	else
+	{
+		buzzerOn = 0;
+	}
+	lastWarningState = warningActive;
+}
 
 void check_warning(void)
 {
@@ -89,22 +148,31 @@
 {
   pDiveState->warnings.numWarnings = 0;
 
-	pDiveState->warnings.numWarnings += check_aGF(pDiveState);
+/* Warnings checked before the SetBuzzer call will activate the buzzer */
 	pDiveState->warnings.numWarnings += check_AscentRate(pDiveState);
-	pDiveState->warnings.numWarnings += check_CNS(pDiveState);
 	pDiveState->warnings.numWarnings += check_Deco(pDiveState);
 	pDiveState->warnings.numWarnings += check_ppO2(pDiveState);
 	pDiveState->warnings.numWarnings += check_O2_sensors(pDiveState);
+	pDiveState->warnings.numWarnings += check_fallback(pDiveState);
+#ifdef ENABLE_CO2_SUPPORT
+	pDiveState->warnings.numWarnings += check_co2(pDiveState);
+#endif
+
+	if(settingsGetPointer()->warningBuzzer)
+	{
+		setBuzzer(pDiveState->warnings.numWarnings);
+	}
+
+/* Warnings checked after this line will not cause activation of the buzzer */
+	pDiveState->warnings.numWarnings += check_aGF(pDiveState);
+	pDiveState->warnings.numWarnings += check_CNS(pDiveState);
 	pDiveState->warnings.numWarnings += check_BetterGas(pDiveState);
 	pDiveState->warnings.numWarnings += check_BetterSetpoint(pDiveState);
 	pDiveState->warnings.numWarnings += check_Battery(pDiveState);
-	pDiveState->warnings.numWarnings += check_fallback(pDiveState);
 #ifdef ENABLE_BOTTLE_SENSOR
 	pDiveState->warnings.numWarnings += check_pressureSensor(pDiveState);
 #endif
-#ifdef ENABLE_CO2_SUPPORT
-	pDiveState->warnings.numWarnings += check_co2(pDiveState);
-#endif
+
 #ifdef HAVE_DEBUG_WARNINGS
 	pDiveState->warnings.numWarnings += check_debug(pDiveState);
 #endif
@@ -164,7 +232,7 @@
 
 static int8_t check_ppO2(SDiveState * pDiveState)
 {
-	if((pDiveState->mode != MODE_DIVE) || (pDiveState->warnings.fallback))
+	if((pDiveState->mode != MODE_DIVE) || ((isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->warnings.fallback))))
 	{
 		pDiveState->warnings.ppO2Low = 0;
 		pDiveState->warnings.ppO2High = 0;
@@ -208,7 +276,7 @@
 	pDiveState->warnings.sensorOutOfBounds[2] = 0;
 
 	if(isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors))
-
+	{
 		if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_OPTIC)
 		{
 			{
@@ -216,7 +284,8 @@
 					pDiveState->warnings.sensorLinkLost = 1;
 			}
 		}
-	test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]);
+		test_O2_sensor_values_outOfBounds(&pDiveState->warnings.sensorOutOfBounds[0], &pDiveState->warnings.sensorOutOfBounds[1], &pDiveState->warnings.sensorOutOfBounds[2]);
+	}
 	return 		pDiveState->warnings.sensorLinkLost
 					+ pDiveState->warnings.sensorOutOfBounds[0]
 					+ pDiveState->warnings.sensorOutOfBounds[1]
--- a/Discovery/Src/data_central.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/data_central.c	Sun Jan 19 12:02:59 2025 +0100
@@ -921,7 +921,7 @@
 
 void setCompassHeading(uint16_t heading)
 {
-    stateUsedWrite->diveSettings.compassHeading =  ((heading - 360) % 360) + 360;
+    stateUsedWrite->diveSettings.compassHeading = ((heading - 360) % 360) + 360;
 
     internalLogCompassHeading(heading, true, false);
 }
--- a/Discovery/Src/data_exchange_main.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/data_exchange_main.c	Sun Jan 19 12:02:59 2025 +0100
@@ -73,6 +73,7 @@
 #include "buehlmann.h"
 #include "externLogbookFlash.h"
 #include "vpm.h"
+#include "check_warning.h"
 
 /* #define TESTBENCH */
 
@@ -441,6 +442,13 @@
 	}
 #endif
 
+#ifdef ENABLE_GPIO_V2
+	if(getBuzzerActivationState())
+	{
+		externalInterface_Cmd |= EXT_INTERFACE_BUZZER_ON;
+	}
+#endif
+
 	dataOut.data.externalInterface_Cmd = externalInterface_Cmd;
 	externalInterface_Cmd = 0;
 
@@ -474,7 +482,7 @@
 		
 		settingsHelperButtonSens_keepPercentageValues(settingsGetPointerStandard()->ButtonResponsiveness[3], settings->ButtonResponsiveness);
 		setButtonResponsiveness(settings->ButtonResponsiveness);
-		DataEX_setExtInterface_Cmd(EXT_INTERFACE_COPY_SENSORMAP);
+		DataEX_setExtInterface_Cmd(EXT_INTERFACE_COPY_SENSORMAP, 0);
 	}
 }
 
@@ -583,13 +591,16 @@
 	RTC_DateTypeDef sdatestructure;
 	RTC_TimeTypeDef stimestructure;
 
+	const SFirmwareData *pFirmwareInfo;
+    pFirmwareInfo = firmwareDataGetPointer();
+
 	stimestructure.Hours = UNKNOWN_TIME_HOURS;
 	stimestructure.Minutes = UNKNOWN_TIME_MINUTES;
 	stimestructure.Seconds = UNKNOWN_TIME_SECOND;
 
 	sdatestructure.Date = UNKNOWN_DATE_DAY;
 	sdatestructure.Month = UNKNOWN_DATE_MONTH;
-	sdatestructure.Year = UNKNOWN_DATE_YEAR;
+	sdatestructure.Year =  pFirmwareInfo->release_year;
 	setWeekday(&sdatestructure);
 
 	DataEX_helper_SetTime(stimestructure, &lineWrite->time_rtc_tr);
@@ -1352,9 +1363,14 @@
 	return retval;
 }
 
-void DataEX_setExtInterface_Cmd(uint16_t Cmd)
+void DataEX_setExtInterface_Cmd(uint16_t Cmd, uint8_t sensorId)
 {
-	externalInterface_Cmd = Cmd;
+	if(sensorId < EXT_INTERFACE_SENSOR_CNT - 1)
+	{
+		externalInterface_Cmd |= Cmd;
+		externalInterface_Cmd |= sensorId << 8;
+	}
+
 	return;
 }
 
--- a/Discovery/Src/gfx_colors.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/gfx_colors.c	Sun Jan 19 12:02:59 2025 +0100
@@ -14,7 +14,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
+  * COPYRIGHT(c) 2014 heinrichs weikamp
   *
   ******************************************************************************
   */
@@ -25,35 +25,35 @@
 /* Exported variables --------------------------------------------------------*/
 
 /*
-	0x0000FF00,   gr�n
-	0x00FF0000,    rot
-	0x000000FF,   blau
-	0x00FFFF00,   gelb
+	0x0000FF00,   green
+	0x00FF0000,    red
+	0x000000FF,   blue
+	0x00FFFF00,   yellow
 	0x0000FFFF,   cyan
 	0x00000000,  black
-	0x000092D0,  hw hellblau f�r Beschriftun
+	0x000092D0,  hw light blue
 */
 
 
 uint32_t ColorLUT[] =
 {
 	// ARGB
-	0x00FFFFFF, // \020 wei�
+	0x00FFFFFF, // \020 white
 	0x00333333, // \021 dark grey
 	0x0050FF50, // \022 units
-	0x003060FF, // \023 blau
+	0x003060FF, // \023 blue
 	0x00FFFF00, // \024 + CLUT_WarningYellow
 	0x00FF0000, // \025 + CLUT_WarningRed
 	0x0000FF00, // \026 + CLUT_NiceGreen
 	0x00FFFFFF, // \027 DIVE_MainColorIfNotWhite\020
 	0x00FFFFFF, // \030 DIVE_PluginBoxMainColor
-	0x00777777, // \031 DIVE_PluginBoxGrey also used to display deactivation
+	0x00AAAAAA, // \031 DIVE_PluginBoxGrey also used to display deactivation
 	0x0050FF50, // \032 DIVE_LabelColor
 	0x00FFFFFF, // CLUT_DIVE_FieldSeperatorLines
 	0x0050FF50, // CLUT_DIVE_pluginbox // old pink 0x00FF20FF
 	0x00FF00FF, // CLUT_NiceBlue descent graph (apnoe)
 	0x00FFFFFF, // CLUT_DIVE_SPARE22 - UNUSED
-	0x0000FF00, // CLUT_DiveMainLabel - fast nur Debugmode
+	0x0000FF00, // CLUT_DiveMainLabel - mainly Debug mode
 	0x00555555, // CLUT_pluginboxSurface
 	0x00101010, // CLUT_MenuLineUnselected
 	0x00000000, // CLUT_MenuLineUnselectedSeperator
@@ -142,7 +142,7 @@
 	0x00FF8000, // CLUT_BatteryProblem
 	0x00FFFFFF, // \027 CLUT_MainColor ---------- colorscheme 0
 	0x00FFFFFF, // \030 DIVE_PluginBoxMainColor	 	colorscheme 0
-	0x00777777, // \031 DIVE_PluginBoxGrey				colorscheme 0
+	0x00AAAAAA, // \031 DIVE_PluginBoxGrey				colorscheme 0
 	0x0050FF50, // \032 DIVE_LabelColor 					colorscheme 0
 	0x00FFFFFF, // CLUT_DIVE_FieldSeperatorLines	colorscheme 0
 	0x0050FF50, // CLUT_DIVE_pluginbox						colorscheme 0
@@ -166,7 +166,7 @@
 	0x00FFFFFF, // CLUT_DIVE_SPARE22							colorscheme 2
 	0x0033A1D6, // CLUT_MainColor --------------- colorscheme 3
 	0x00FFFFFF, // \030 DIVE_PluginBoxMainColor	 	colorscheme 3
-	0x00777777, // \031 DIVE_PluginBoxGrey				colorscheme 3
+	0x00AAAAAA, // \031 DIVE_PluginBoxGrey				colorscheme 3
 	0x000000FF, // \032 DIVE_LabelColor 					colorscheme 3
 	0x0033A1D6, // CLUT_DIVE_FieldSeperatorLines	colorscheme 3
 	0x000000FF, // CLUT_DIVE_pluginbox						colorscheme 3
--- a/Discovery/Src/logbook.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/logbook.c	Sun Jan 19 12:02:59 2025 +0100
@@ -1363,8 +1363,12 @@
 
 #if defined ENABLE_GNSS_SUPPORT || defined ENABLE_GPIO_V2
 			pStateReal->events.gnssPositionUpdate = 1;
-			pStateReal->events.info_gnssPosition = pStateReal->lifeData.gnssData.coord;
-			if((pStateReal->events.info_gnssPosition.fLat == 0.0) && (pStateReal->events.info_gnssPosition.fLon == 0.0)) /* no pos => define dummy */
+
+			if(pStateReal->lifeData.gnssData.alive & GNSS_ALIVE_BACKUP_POS)
+			{
+				pStateReal->events.info_gnssPosition = pStateReal->lifeData.gnssData.coord;
+			}
+			else /* no pos => define dummy */
 			{
 				pStateReal->events.info_gnssPosition.fLon = 47.77;
 				pStateReal->events.info_gnssPosition.fLat = 8.99;
--- a/Discovery/Src/settings.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/settings.c	Sun Jan 19 12:02:59 2025 +0100
@@ -342,7 +342,8 @@
 	.cvAutofocus = 0,
 	.slowExitTime = 0,
 	.timeZone.hours = 0,
-	.timeZone.minutes = 0
+	.timeZone.minutes = 0,
+	.warningBuzzer = 0
 };
 
 /* Private function prototypes -----------------------------------------------*/
@@ -608,6 +609,7 @@
     case 0xFFFF002B:
     	Settings.timeZone.hours = 0;
     	Settings.timeZone.minutes = 0;
+    	Settings.warningBuzzer = 0;
     	// no break;
     default:
         pSettings->header = pStandard->header;
@@ -1317,6 +1319,16 @@
         setFirstCorrection(parameterId);
     }
     parameterId++;
+
+    if(Settings.warningBuzzer > 1)
+    {
+    	Settings.warningBuzzer = 0;
+        corrections++;
+        setFirstCorrection(parameterId);
+    }
+    parameterId++;
+
+
 /*	uint8_t serialHigh;
  */
 
--- a/Discovery/Src/simulation.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/simulation.c	Sun Jan 19 12:02:59 2025 +0100
@@ -231,7 +231,7 @@
 
     pDiveState->lifeData.dive_time_seconds += 1;
     pDiveState->lifeData.pressure_ambient_bar = sim_get_ambient_pressure(pDiveState);
-    if(pDiveState->lifeData.pressure_ambient_bar < 1.5)
+    if(pDiveState->lifeData.depth_meter < 1.5)
     {
     	lastPressure_bar = 0;
     	pDiveState->lifeData.ascent_rate_meter_per_min = 0;
--- a/Discovery/Src/t3.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/t3.c	Sun Jan 19 12:02:59 2025 +0100
@@ -535,11 +535,12 @@
     }
     else
     {
+    	color = 0xff;
     	if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter))
     	{
     		color = t3_drawSlowExitGraph(tXscreen, tXl1, tXr1);
     	}
-    	else
+    	if(color == 0xff)	/* no slow exit => continue with common ascent graph */
     	{
 			if(stateUsed->lifeData.ascent_rate_meter_per_min > 0) /* ascentrate graph -standard mode */
 			{
@@ -762,10 +763,14 @@
         customview_warnings = t3_test_customview_warnings();
 
     if(customview_warnings && warning_count_high_time)
+    {
         t3_basics_show_customview_warnings(&t3c1);
+    }
     else
+    {
         t3_refresh_customview(depth_meter);
-
+        requestBuzzerActivation(0);
+    }
     if(stateUsed->warnings.lowBattery)
         t3_basics_battery_low_customview_extra(&t3r1); //t3c1);
 }
@@ -1534,7 +1539,9 @@
 {
     char text[256], textMain[256];
     uint8_t textpointer, textpointerMain, lineFree, more;
+#ifdef HAVE_DEBUG_WARNINGS
     uint8_t index = 0;
+#endif
 
     snprintf(text,TEXTSIZE,"\025\f%c",TXT_Warning);
     GFX_write_string(&FontT42,&t3c1,text,0);
@@ -1680,6 +1687,7 @@
     {
         GFX_write_string(&FontT48,&t3c2,text,0);
     }
+    requestBuzzerActivation(1);
 }
 
 uint8_t t3_customview_disabled(uint8_t view)
@@ -2227,5 +2235,9 @@
 		stop.y = start.y;
 		GFX_draw_thick_line(10,tXscreen, start, stop, 9);
 	}
+	else
+	{
+		color = 0xff;
+	}
 	return color;
 }
--- a/Discovery/Src/t7.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/t7.c	Sun Jan 19 12:02:59 2025 +0100
@@ -1502,7 +1502,9 @@
 {
     char text[256];
     uint8_t textpointer, lineFree;
+#ifdef HAVE_DEBUG_WARNINGS
     uint8_t index = 0;
+#endif
 
     text[0] = '\025';
     text[1] = '\f';
@@ -1614,6 +1616,7 @@
     }
 */
     GFX_write_string(&FontT48,&t7cW,text,1);
+    requestBuzzerActivation(1);
 }
 
 
@@ -2806,18 +2809,21 @@
     GFX_write_string(&FontT105,&t7l2,TextL2,1);
 
 /* ascent rate graph */
-
+    color = 0xff;
     if((pSettings->slowExitTime != 0) && (nextstopDepthMeter == 0) && (stateUsed->lifeData.depth_meter < pSettings->last_stop_depth_meter))
     {
     	color = t7_drawSlowExitGraph();
     }
-    else if(stateUsed->lifeData.ascent_rate_meter_per_min > 1)	/* a value < 1 would cause a bar in negative direction brush rectangle of 12 and step width of 6 */
+    if(color == 0xff)
     {
-        color = drawingColor_from_ascentspeed(stateUsed->lifeData.ascent_rate_meter_per_min);
-    	t7_drawAcentGraph(color);
+    	color = drawingColor_from_ascentspeed(stateUsed->lifeData.ascent_rate_meter_per_min);
+    	if(stateUsed->lifeData.ascent_rate_meter_per_min > 1)	/* a value < 1 would cause a bar in negative direction brush rectangle of 12 and step width of 6 */
+    	{
+
+    	    	t7_drawAcentGraph(color);
+    	}
     }
 
-
     /* depth */
     float depth = unit_depth_float(stateUsed->lifeData.depth_meter);
 
@@ -3217,7 +3223,10 @@
     if(customview_warnings && warning_count_high_time)
         t7_show_customview_warnings();
     else
+    {
         t7_refresh_customview();
+        requestBuzzerActivation(0);
+    }
 
     /* the frame */
     draw_frame(1,1, CLUT_DIVE_pluginbox, CLUT_DIVE_FieldSeperatorLines);
@@ -4032,15 +4041,26 @@
     point_t start, stop;
     uint8_t index = 0;
     uint8_t color = 0;
+    SSettings* pSettings = settingsGetPointer();
 
     t7cY0free.WindowLineSpacing = 28 + 48 + 14;
     t7cY0free.WindowY0 = t7cH.WindowY0 - 5 - 2 * t7cY0free.WindowLineSpacing;
     t7cY0free.WindowNumberOfTextLines = 3;
     t7cY0free.WindowY0 -= 20;
+
+    t7cY0free.WindowX0 = CUSTOMBOX_LINE_LEFT + CUSTOMBOX_INSIDE_OFFSET;
+    t7cY0free.WindowX1 = CUSTOMBOX_LINE_RIGHT - CUSTOMBOX_INSIDE_OFFSET;
+
+    if(pSettings->FlipDisplay)
+    {
+       	t7cY0free.WindowY0 = t7cH.WindowY0 + 15;
+        t7cY0free.WindowY1 = t7cY0free.WindowY0 + 250;
+    }
+
     if(stateUsed->lifeData.gnssData.fixType < 2)
     {
     	textpointer += snprintf(&text[textpointer],50,"\001Satellites\n\r");
-    	if(stateUsed->lifeData.gnssData.alive & GNSS_ALIVE_STATE_TIME)
+    	if(stateUsed->lifeData.gnssData.alive & GNSS_ALIVE_STATE_ALIVE)
     	{
     		textpointer += snprintf(&text[textpointer],50,"\001\020Status\n\r");
     	}
@@ -4056,7 +4076,15 @@
     }
     GFX_write_string(&FontT24, &t7cY0free, text, 1);
 
-    t7cY0free.WindowY0 -= 52;
+    if(!pSettings->FlipDisplay)
+    {
+    	t7cY0free.WindowY0 -= 52;
+    }
+    else
+    {
+        t7cY0free.WindowY1 = 370;
+    }
+
     if(stateUsed->lifeData.gnssData.fixType < 2)
     {
 		snprintf(text,60,"\001%d\n\r",stateUsed->lifeData.gnssData.numSat);
@@ -4072,10 +4100,21 @@
 
     if(stateUsed->lifeData.gnssData.fixType < 2)	/* draw status bars */
     {
-    	start.x = t7cY0free.WindowX0 + 85;
-    	stop.x = start.x;
-    	start.y = t7cY0free.WindowY0 + 75;
-    	stop.y = start.y + 20;
+    	 if(!pSettings->FlipDisplay)
+    	 {
+    	    	start.x = t7cY0free.WindowX0 + 85;
+    	    	stop.x = start.x;
+    	    	start.y = t7cY0free.WindowY0 + 75;
+    	    	stop.y = start.y + 20;
+    	 }
+    	 else
+    	 {
+			start.x = t7cY0free.WindowX0 - 50;
+			stop.x = start.x;
+			start.y = t7cY0free.WindowY0 - 75;
+			stop.y = start.y - 20;
+    	 }
+
     	while((index < stateUsed->lifeData.gnssData.numSat) && (index < 4))
     	{
     		if(stateUsed->lifeData.gnssData.signalQual[index] > 4) color = CLUT_NiceGreen;
@@ -4087,6 +4126,11 @@
 
     		index++;
     	}
+    	if(stateUsed->lifeData.gnssData.alive & GNSS_ALIVE_BACKUP_POS)
+    	{
+    		snprintf(text,50,"\001%2.2f %2.2f", stateUsed->lifeData.gnssData.coord.fLat,stateUsed->lifeData.gnssData.coord.fLon);
+    		GFX_write_string(&FontT24, &t7cY0free, text, 3);
+    	}
     }
 
 
@@ -4698,7 +4742,7 @@
     }
     else
     {
-        	t7cY0free.WindowY1 += 52;
+        t7cY0free.WindowY1 += 52;
     }
 
     if((stateUsed->lifeData.battery_charge > 0) && (stateUsed->chargeStatus != CHARGER_off))
@@ -4871,6 +4915,10 @@
 		stop.y = start.y;
 		GFX_draw_thick_line(10,&t7screen, start, stop, 9);
 	}
+	else
+	{
+		color = 0xff;
+	}
 	return color;
 }
 void t7_tick(void)
--- a/Discovery/Src/tComm.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tComm.c	Sun Jan 19 12:02:59 2025 +0100
@@ -388,10 +388,15 @@
 
 //	char aTxFactoryDefaults[50] = "AT&F1\r";
 
-    char aTxBufferEscapeSequence[50] = "+++";
+    char aTxBufferEscapeSequence[50] = "+++";	/* factory default */
     // limit is 19 chars, with 7 chars shown in BLE advertising mode
     //________________________123456789012345678901
+
+#ifndef BOOTLOADER_STANDALONE
     char aTxBufferName[50] = "AT+BNAME=OSTC4-12345\r";
+#else
+    char aTxBufferName[50] = "AT+UBTLN=OSTC4-12345\r";
+#endif
     char answerOkay[6] = "\r\nOK\r\n";
 
     gfx_number_to_string(5,1,&aTxBufferName[15],serial);
@@ -2187,17 +2192,36 @@
 	{
 		case BM_CONFIG_ECHO: 			sprintf(TxBuffer,"ATE0\r");
 			break;
-		case BM_CONFIG_SILENCE:			sprintf(TxBuffer,"ATS30=0\r");
+		case BM_CONFIG_SILENCE:
+#ifndef BOOTLOADER_STANDALONE
+										sprintf(TxBuffer,"ATS30=0\r");
+#else
+										BmTmpConfig++;
+#endif
 			break;
-		case BM_CONFIG_ESCAPE_DELAY:	sprintf(TxBuffer,"ATS12=10\r");
+		case BM_CONFIG_ESCAPE_DELAY:
+#ifndef BOOTLOADER_STANDALONE
+			sprintf(TxBuffer,"ATS12=10\r");
+#else
+										BmTmpConfig++;
+#endif
 			break;
-		case BM_CONFIG_SIGNAL_POLL:		sprintf(TxBuffer,"AT+BSTPOLL=100\r");
+		case BM_CONFIG_SIGNAL_POLL:
+#ifndef BOOTLOADER_STANDALONE
+										sprintf(TxBuffer,"AT+BSTPOLL=100\r");
+#else
+										BmTmpConfig++;
+#endif
 			break;
 		case BM_CONFIG_BAUD:
 #ifdef ENABLE_FAST_COMM
+ 	#ifndef BOOTLOADER_STANDALONE
 										sprintf(TxBuffer,"AT%%B22\r");
+	#else
+										sprintf(TxBuffer,"AT+UMRS=460800,1,8,1,1,1\r");
+	#endif
 #else
-										BmTmpConfig++;
+										BmTmpConfig = BM_CONFIG_DONE;
 #endif
 			break;
 		case BM_CONFIG_RETRY:			ConfigRetryCnt--;
@@ -2267,7 +2291,11 @@
 			}
 			else if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate == 460800)) /* This shut not happen because default speed is 115200 => update module configuration */
 			{
+#ifndef BOOTLOADER_STANDALONE
 				sprintf(TxBuffer,"AT%%B8\r");	/* set default baudrate */
+#else
+				sprintf(TxBuffer,"AT+UMRS=115200,1,8,1,1,1\r");
+#endif
 				CmdSize = strlen(TxBuffer);
 				HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000);
 				HAL_UART_DeInit(&UartHandle);
@@ -2281,6 +2309,10 @@
 			if(result == HAL_OK)
 			{
 				BmTmpConfig++;
+				if(BmTmpConfig == BM_CONFIG_RETRY)
+				{
+					BmTmpConfig = BM_CONFIG_DONE;
+				}
 			}
 			if(BmTmpConfig == BM_CONFIG_ECHO)
 			{
--- a/Discovery/Src/tInfoSensor.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tInfoSensor.c	Sun Jan 19 12:02:59 2025 +0100
@@ -61,12 +61,12 @@
     	case 0: setBackMenu((uint32_t)openEdit_O2Sensors,0,1);
     	    		break;
     }
-
     sensorActive = 1;
     if(pSettings->ppo2sensors_deactivated & (1 << (activeSensorId)))
     {
     	sensorActive = 0;
     }
+    DataEX_setExtInterface_Cmd(EXT_INTERFACE_O2_INDICATE, activeSensorId);
 }
 
 
@@ -260,7 +260,7 @@
     		break;
 		case ACTION_BUTTON_NEXT:		if(stateRealGetPointer()->lifeData.extIf_sensor_map[activeSensorId] == SENSOR_CO2M)
 										{
-											DataEX_setExtInterface_Cmd(EXT_INTERFACE_CO2_CALIB);
+											DataEX_setExtInterface_Cmd(EXT_INTERFACE_CO2_CALIB, activeSensorId);
 										}
 			break;
 		case ACTION_TIMEOUT:
--- a/Discovery/Src/tMenu.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenu.c	Sun Jan 19 12:02:59 2025 +0100
@@ -864,6 +864,8 @@
     if((page == 0) || (line == 0))
         return;
 
+    requestBuzzerActivation(0);
+
     menu.pageMemoryForNavigation = page;
     /* new test for 3button design */
     if(freshWithFlipPages)
--- a/Discovery/Src/tMenuCustom.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuCustom.c	Sun Jan 19 12:02:59 2025 +0100
@@ -118,6 +118,26 @@
 	strcpy(&text[textPointer],"\n\r");
 	textPointer += 2;
 #endif
+
+#ifdef ENABLE_GPIO_V2
+    if((line == 0) || (line == 5))
+    {
+    /* MotionCtrl */
+		text[textPointer++] = TXT_2BYTE;
+		text[textPointer++] = TXT2BYTE_BUZZER;
+		text[textPointer++] = ' ';
+		text[textPointer++] = TXT_Warning;
+		text[textPointer++] = '\t';
+	    if(settingsGetPointer()->warningBuzzer)
+	            text[textPointer++] = '\005';
+	        else
+	            text[textPointer++] = '\006';
+    }
+
+	strcpy(&text[textPointer],"\n\r");
+	textPointer += 2;
+#endif
+
     return StMCustom;
 }
 
--- a/Discovery/Src/tMenuEdit.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuEdit.c	Sun Jan 19 12:02:59 2025 +0100
@@ -256,10 +256,12 @@
 	 	 case StMCustom3_CViewSelection5:
 	 	 case StMCustom3_CViewSelection6: refreshFct = CustomviewDivemode_refresh;
 	 	 	 break;
+#ifdef ENABLE_MOTION_CONTROL
 	 	 case (StMCustom5_CViewPortCalib & MaskFieldDigit):
 	 	 case StMCustom5_CViewPortLayout:
 	 	 case StMCustom5_CViewPortAmbient: refreshFct = refresh_ViewPort;
 	 		 break;
+#endif
 	 	 default:	 /* no menu has been updated */
 	 		 break;
 	 }
--- a/Discovery/Src/tMenuEditCustom.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuEditCustom.c	Sun Jan 19 12:02:59 2025 +0100
@@ -56,6 +56,7 @@
 void openEdit_BigScreen(void);
 void openEdit_MotionCtrl(void);
 void openEdit_ViewPort(void);
+void openEdit_WarningBuz(void);
 void refresh_Customviews(void);
 void setMenuContentStructure();
 char customview_TXT2BYTE_helper(uint8_t customViewId);
@@ -126,7 +127,6 @@
 
     tMenuEdit_refresh_field(StMCustom1_CViewAutoFocusBF);
 
-
     // field corner  return
     textpointer = 0;
     text[textpointer++] = TXT_2BYTE;
@@ -375,8 +375,14 @@
     		break;
     	case 4:		openEdit_CustomviewDivemode(cv_changelist_BS);
     		break;
+#ifdef ENABLE_MOTION_CONTROL
     	case 5:		openEdit_ViewPort();
     		break;
+#endif
+#ifdef ENABLE_GPIO_V2
+    	case 5:		openEdit_WarningBuz();
+    	    	break;
+#endif
     }
 }
 
@@ -450,6 +456,7 @@
 
 void openEdit_ViewPort(void)
 {
+#ifdef ENABLE_MOTION_CONTROL
 	resetMenuEdit(CLUT_MenuPageCustomView);
     refresh_ViewPort();
 
@@ -464,8 +471,22 @@
     setEvent(StMCustom5_CViewPortLayout,	(uint32_t)OnAction_CViewPortLayout);
     setEvent(StMCustom5_CViewPortAmbient,	(uint32_t)OnAction_CViewPortAmbient);
     setEvent(StMCustom5_CViewPortControl,	(uint32_t)OnAction_CViewPortControl);
+#endif
 }
+void openEdit_WarningBuz(void)
+{
+    SSettings *pSettings = settingsGetPointer();
 
+    if(pSettings->warningBuzzer == 0)
+    {
+        pSettings->warningBuzzer = 1;
+    }
+    else
+    {
+        pSettings->warningBuzzer = 0;
+    }
+    exitMenuEdit_to_Menu_with_Menu_Update_do_not_write_settings_for_this_only();
+}
 
 char customview_TXT2BYTE_helper(uint8_t customViewId)
 {
--- a/Discovery/Src/tMenuEditHardware.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuEditHardware.c	Sun Jan 19 12:02:59 2025 +0100
@@ -843,7 +843,7 @@
 
 uint8_t OnAction_Sensor_Detect(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
-	DataEX_setExtInterface_Cmd(EXT_INTERFACE_AUTODETECT);
+	DataEX_setExtInterface_Cmd(EXT_INTERFACE_AUTODETECT, 0);
 	return UNSPECIFIC_RETURN;
 }
 
--- a/Discovery/Src/tMenuEditSystem.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuEditSystem.c	Sun Jan 19 12:02:59 2025 +0100
@@ -41,6 +41,7 @@
 #include "tMenuEditCustom.h"
 #include "motion.h"
 #include "t7.h"
+#include "math.h"
 
 
 /*#define HAVE_DEBUG_VIEW */
@@ -1687,28 +1688,39 @@
     const SDiveState* pDiveState = stateRealGetPointer();
     SSettings* pSettings = settingsGetPointer();
     uint8_t index = 0;
-    int8_t newOffset = 0;
+    float orgpressure_surface_mbar;
+    float DiveO2_mbar;
+    int8_t newOffset_mbar = 0;
+
 
     char text[32];
 
-    float orgpressure_surface;
+
 
     for (index = 0; index < 3; index++)
     {
     	if(settingsGetPointer()->ext_sensor_map[index] == SENSOR_DIGO2M)
     	{
     		pDiveO2Data = (SSensorDataDiveO2*)stateRealGetPointer()->lifeData.extIf_sensor_data[index];
-    		orgpressure_surface = pDiveState->lifeData.pressure_surface_bar - (settingsGetPointer()->offsetPressure_mbar / 1000.0);
-    		newOffset = ((pDiveO2Data->pressure/1000) - (orgpressure_surface * 1000));
+    		DiveO2_mbar = (pDiveO2Data->pressure/1000.0);
+
+    		orgpressure_surface_mbar = (pDiveState->lifeData.pressure_surface_bar * 1000) - (settingsGetPointer()->offsetPressure_mbar);
+    		newOffset_mbar = DiveO2_mbar - orgpressure_surface_mbar;
 
-    		if((pDiveState->lifeData.pressure_surface_bar * 1000 + newOffset) != (pDiveO2Data->pressure/1000)) /* there might be a rounding difference => compensate */
+    		if(fabs(orgpressure_surface_mbar + ((float)newOffset_mbar) - DiveO2_mbar) > 0.5) /* there might be a rounding difference => compensate */
 			{
-    			newOffset += (pDiveO2Data->pressure/1000) - (pDiveState->lifeData.pressure_surface_bar * 1000 + newOffset);
+    			if((orgpressure_surface_mbar + ((float)newOffset_mbar)) - (pDiveO2Data->pressure/1000.0) > 0.0)
+				{
+    				newOffset_mbar -=1;
+				}
+				else
+				{
+					newOffset_mbar +=1;
+				}
 			}
 
-    		pSettings->offsetPressure_mbar = newOffset;
-    		snprintf(text,32,"%c%c (%1.3lf => %1.3f)\016\016Bar",TXT_2BYTE,TXT2BYTE_AdjustAmbPressure,(float)(pDiveO2Data->pressure/1000000.0),
-    		        													pDiveState->lifeData.pressure_surface_bar + pSettings->offsetPressure_mbar / 1000.0);
+    		pSettings->offsetPressure_mbar = newOffset_mbar;
+    		snprintf(text,32,"%c%c (%1.3lf => %1.3f)\016\016Bar",TXT_2BYTE,TXT2BYTE_AdjustAmbPressure,(float)(pDiveO2Data->pressure/1000000.0),	(orgpressure_surface_mbar + pSettings->offsetPressure_mbar) / 1000.0);
     		tMenuEdit_newButtonText(StMSYS5_AdjustSurfPres,text);
     		break;
     	}
--- a/Discovery/Src/tMenuEditXtra.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/tMenuEditXtra.c	Sun Jan 19 12:02:59 2025 +0100
@@ -314,6 +314,16 @@
 
 
 
+static uint8_t OnAction_CompassHeadingReverse(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+    setCompassHeading((stateUsed->diveSettings.compassHeading + 180) % 360);
+
+    exitMenuEdit_to_Home_with_Menu_Update();
+
+    return EXIT_TO_HOME;
+}
+
+
 static uint8_t OnAction_CompassHeadingClear(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
     clearCompassHeading();
@@ -352,6 +362,13 @@
     snprintf(text, 32, "\001%c%c", TXT_2BYTE, TXT2BYTE_CompassHeading);
     write_topline(text);
 
+    if (!isRefresh) {
+        snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_Set);
+        write_field_button(StMXTRA_CompassHeading, 20, 800, ME_Y_LINE1, &FontT48, text);
+    } else {
+        tMenuEdit_refresh_field(StMXTRA_CompassHeading);
+    }
+
     uint16_t heading;
     if (settings->compassInertia) {
         heading = (uint16_t)compass_getCompensated();
@@ -361,14 +378,18 @@
     snprintf(text,32,"\001%03i`",heading);
     write_label_var(0, 800, ME_Y_LINE1, &FontT54, text);
 
-    if (!isRefresh) {
-        snprintf(text, 32, "%c%c", TXT_2BYTE, TXT2BYTE_Set);
-        write_field_button(StMXTRA_CompassHeading, 20, 800, ME_Y_LINE2, &FontT48, text);
+    bool headingIsSet = stateUsed->diveSettings.compassHeading;
+    snprintf(text, 32, "%s%c%c", makeGrey(!headingIsSet), TXT_2BYTE, TXT2BYTE_Reverse);
+    if (headingIsSet) {
+        if (!isRefresh) {
+            write_field_button(StMXTRA_CompassHeadingReverse, 20, 800, ME_Y_LINE2, &FontT48, text);
+        } else {
+            tMenuEdit_refresh_field(StMXTRA_CompassHeadingReverse);
+        }
     } else {
-        tMenuEdit_refresh_field(StMXTRA_CompassHeading);
+        write_label_var(20, 800, ME_Y_LINE2, &FontT48, text);
     }
 
-    bool headingIsSet = stateUsed->diveSettings.compassHeading;
     snprintf(text, 32, "%s%c%c", makeGrey(!headingIsSet), TXT_2BYTE, TXT2BYTE_Clear);
     if (headingIsSet) {
         if (!isRefresh) {
@@ -407,6 +428,7 @@
 
     if (!isRefresh) {
         setEvent(StMXTRA_CompassHeading, (uint32_t)OnAction_CompassHeading);
+        setEvent(StMXTRA_CompassHeadingReverse, (uint32_t)OnAction_CompassHeadingReverse);
         setEvent(StMXTRA_CompassHeadingClear, (uint32_t)OnAction_CompassHeadingClear);
         setEvent(StMXTRA_CompassHeadingReset, (uint32_t)OnAction_CompassHeadingReset);
         setEvent(StMXTRA_CompassHeadingLog, (uint32_t)OnAction_CompassHeadingLog);
--- a/Discovery/Src/text_multilanguage.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Discovery/Src/text_multilanguage.c	Sun Jan 19 12:02:59 2025 +0100
@@ -1993,6 +1993,18 @@
 static uint8_t text_IT_TIMEZONE[] = "";
 static uint8_t text_ES_TIMEZONE[] = "";
 
+static uint8_t text_EN_BUZZER[] = "Buzzer";
+static uint8_t text_DE_BUZZER[] = "Vibration";
+static uint8_t text_FR_BUZZER[] = "";
+static uint8_t text_IT_BUZZER[] = "";
+static uint8_t text_ES_BUZZER[] = "";
+
+static uint8_t text_EN_Reverse[] = "Reverse";
+static uint8_t text_DE_Reverse[] = "Umkehren";
+static uint8_t text_FR_Reverse[] = "Inverser";
+static uint8_t text_IT_Reverse[] = "Invertire";
+static uint8_t text_ES_Reverse[] = "Invertir";
+
 /* Lookup Table -------------------------------------------------------------*/
 
 const tText text_array[] =
@@ -2301,6 +2313,12 @@
 	{(uint8_t)TXT2BYTE_YYMMDD, 			{text_EN_YYMMDD, text_DE_YYMMDD, text_FR_YYMMDD, text_IT_YYMMDD, text_ES_YYMMDD}},
 	{(uint8_t)TXT2BYTE_TIMEZONE, 		{text_EN_TIMEZONE, text_DE_TIMEZONE, text_FR_TIMEZONE, text_IT_TIMEZONE, text_ES_TIMEZONE}},
 
+	{(uint8_t)TXT2BYTE_BUZZER, 			{text_EN_BUZZER, text_DE_BUZZER, text_FR_BUZZER, text_IT_BUZZER, text_ES_BUZZER}},
+
+	{(uint8_t)TXT2BYTE_Current, 		{text_EN_Current, text_DE_Current, text_FR_Current, text_IT_Current, text_ES_Current}},
+ 	{(uint8_t)TXT2BYTE_Log, 			{text_EN_Log, text_DE_Log, text_FR_Log, text_IT_Log, text_ES_Log}},
+	{(uint8_t)TXT2BYTE_Reverse, 		{text_EN_Reverse, text_DE_Reverse, text_FR_Reverse, text_IT_Reverse, text_ES_Reverse}},
+
 
 
 };
--- a/Small_CPU/Inc/GNSS.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Inc/GNSS.h	Sun Jan 19 12:02:59 2025 +0100
@@ -93,6 +93,10 @@
 
 	uint8_t alive;
 
+	float last_fLon;	/* last known position storage and time stamp */
+	float last_fLat;
+	float last_hour;
+
 }GNSS_StateHandle;
 
 GNSS_StateHandle GNSS_Handle;
--- a/Small_CPU/Inc/gpio.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Inc/gpio.h	Sun Jan 19 12:02:59 2025 +0100
@@ -49,6 +49,8 @@
 void GPIO_GPS_ON(void);
 void GPIO_GPS_BCKP_OFF(void);
 void GPIO_GPS_BCKP_ON(void);
+
+void GPIO_HandleBuzzer();
 #endif
 #ifdef __cplusplus
 }
--- a/Small_CPU/Inc/rtc.h	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Inc/rtc.h	Sun Jan 19 12:02:59 2025 +0100
@@ -40,6 +40,8 @@
 void RTC_SetTime(RTC_TimeTypeDef stimestructure);
 void RTC_SetDate(RTC_DateTypeDef sdatestructure);
 
+void RTC_GetTime(RTC_TimeTypeDef* pstimestructure);
+
 #ifdef __cplusplus
 }
 #endif
--- a/Small_CPU/Src/GNSS.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/GNSS.c	Sun Jan 19 12:02:59 2025 +0100
@@ -29,6 +29,7 @@
 #include <string.h>
 #include "GNSS.h"
 #include "data_exchange.h"
+#include "rtc.h"
 
 union u_Short uShort;
 union i_Short iShort;
@@ -57,7 +58,6 @@
 	GNSS->vAcc = 0;
 	GNSS->gSpeed = 0;
 	GNSS->headMot = 0;
-	GNSS->alive = 0;
 }
 
 /*!
@@ -66,7 +66,7 @@
  * @param GNSS Pointer to main GNSS structure.
  */
 void GNSS_ParseUniqID(GNSS_StateHandle *GNSS) {
-	for (int var = 0; var < 5; var++) {
+	for (int var = 0; var < 4; var++) {
 		GNSS->uniqueID[var] = GNSS_Handle.uartWorkingBuffer[10 + var];
 	}
 }
@@ -80,6 +80,8 @@
 
 	static float searchCnt = 1.0;
 
+	RTC_TimeTypeDef sTimeNow;
+
 	uShort.bytes[0] = GNSS_Handle.uartWorkingBuffer[10];
 	GNSS->yearBytes[0]=GNSS_Handle.uartWorkingBuffer[10];
 	uShort.bytes[1] = GNSS_Handle.uartWorkingBuffer[11];
@@ -143,7 +145,7 @@
 
 	if(GNSS->alive & GNSS_ALIVE_STATE_ALIVE)							/* alive */
 	{
-		GNSS->alive &= !GNSS_ALIVE_STATE_ALIVE;
+		GNSS->alive &= ~GNSS_ALIVE_STATE_ALIVE;
 	}
 	else
 	{
@@ -155,7 +157,16 @@
 	}
 	else
 	{
-		GNSS->alive &= !GNSS_ALIVE_STATE_TIME;
+		GNSS->alive &= ~GNSS_ALIVE_STATE_TIME;
+	}
+
+	if(GNSS->fixType >= 2)
+	{
+		RTC_GetTime(&sTimeNow);
+		GNSS->alive |= GNSS_ALIVE_BACKUP_POS;
+		GNSS->last_fLat = GNSS->fLat;
+		GNSS->last_fLon = GNSS->fLon;
+		GNSS->last_hour = sTimeNow.Hours;
 	}
 }
 
--- a/Small_CPU/Src/baseCPU2.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/baseCPU2.c	Sun Jan 19 12:02:59 2025 +0100
@@ -383,6 +383,12 @@
 	GPIO_Power_MainCPU_Init();
 	global.mode = MODE_TEST;
 #endif
+
+	GNSS_Handle.alive = 0;			/* only init at startup (outside init function) */
+	GNSS_Handle.last_fLat = 0.0;
+	GNSS_Handle.last_fLon = 0.0;
+	GNSS_Handle.last_hour = 0;
+
 	while (1) {
 /*		printf("Global mode = %d\n", global.mode); */
 
--- a/Small_CPU/Src/externalInterface.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/externalInterface.c	Sun Jan 19 12:02:59 2025 +0100
@@ -1018,15 +1018,6 @@
 											SensorMap[index] = SENSOR_SEARCH;
 										}
 			break;
-		case EXT_INTERFACE_CO2_CALIB:	for(index = 0; index < EXT_INTERFACE_SENSOR_CNT; index++)
-										{
-											if(SensorMap[index] == SENSOR_CO2)
-											{
-												externalInterface_SensorState[index] = UART_CO2_CALIBRATE;
-												break;
-											}
-										}
-			break;
 		case EXT_INTERFACE_COPY_SENSORMAP:	if(externalAutoDetect == DETECTION_OFF)
 											{
 												memcpy(SensorMap, MasterSensorMap, sizeof(MasterSensorMap));
@@ -1049,6 +1040,27 @@
 												}
 											}
 			break;
+		case EXT_INTERFACE_CO2_CALIB:	index = (Cmd >> 8) & 0x000F;
+										if(SensorMap[index] == SENSOR_CO2M)
+										{
+											index = Mux2ADCMap[index];
+										}
+										if(SensorMap[index] == SENSOR_CO2)
+										{
+											externalInterface_SensorState[index] = UART_CO2_CALIBRATE;
+										}
+			break;
+		case EXT_INTERFACE_O2_INDICATE:	index = (Cmd >> 8) & 0x000F;
+										if(SensorMap[index] == SENSOR_DIGO2M)
+										{
+											index = Mux2ADCMap[index];
+										}
+										if(SensorMap[index] == SENSOR_DIGO2)
+										{
+											externalInterface_SensorState[index] = UART_O2_CHECK;
+										}
+			break;
+
 		default:
 			break;
 	}
@@ -1192,6 +1204,12 @@
 						break;
 				}
 			}
+			if((externalInterface_SensorState[activeSensorId] == UART_CO2_SETUP)	/* timeout while setting up sensors */
+					|| (externalInterface_SensorState[activeSensorId] == UART_O2_CHECK))
+			{
+				forceMuxChannel = 1;
+			}
+
 
 			if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX) /* select next sensor if mux is connected */
 			{
@@ -1203,14 +1221,17 @@
 						forceMuxChannel = 0;
 						timeToTrigger = 100;
 						activeUartChannel = index;
-						if((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
-								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2)
-								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_GNSS))
+						switch(pmap[index + EXT_INTERFACE_MUX_OFFSET])
 						{
-							uartO2_SetChannel(activeUartChannel);
-							externalInterface_CheckBaudrate(SENSOR_MUX);
-							UART_MUX_SelectAddress(activeUartChannel);
-							externalInterface_CheckBaudrate(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET]);
+							case SENSOR_DIGO2: uartO2_SetChannel(activeUartChannel);
+							/* no break */
+							case SENSOR_CO2:
+							case SENSOR_GNSS: 	externalInterface_CheckBaudrate(SENSOR_MUX);
+												UART_MUX_SelectAddress(activeUartChannel);
+												externalInterface_CheckBaudrate(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET]);
+								break;
+							default:
+								break;
 						}
 					}
 				}
--- a/Small_CPU/Src/gpio.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/gpio.c	Sun Jan 19 12:02:59 2025 +0100
@@ -23,6 +23,8 @@
 
 #include "stm32f4xx_hal.h"
 #include "gpio.h"
+#include "data_exchange.h"
+#include "scheduler.h"
 
 /* Exported variables --------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
@@ -89,6 +91,40 @@
 	HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET);
 }
 
+#ifdef ENABLE_GPIO_V2
+void GPIO_HandleBuzzer()
+{
+	static uint32_t buzzerOnTick = 0;
+	static uint8_t buzzerWasOn = 0;
+
+	if(((global.dataSendToSlave.data.externalInterface_Cmd & EXT_INTERFACE_BUZZER_ON) != 0))
+	{
+		if(!buzzerWasOn)
+		{
+			buzzerOnTick = HAL_GetTick();
+			GPIO_VIBRATION_ON();
+			/* GPIO_LED_RED_ON(); */
+
+			if(time_elapsed_ms(buzzerOnTick,HAL_GetTick()) > EXT_INTERFACE_BUZZER_ON_TIME_MS)
+			{
+				GPIO_VIBRATION_OFF();
+			/*	GPIO_LED_RED_OFF(); */
+			}
+		}
+		buzzerWasOn = 1;
+	}
+	else
+	{
+		if(buzzerWasOn)
+		{
+			buzzerOnTick = 0;
+			GPIO_VIBRATION_OFF();
+			/* GPIO_LED_RED_OFF(); */
+		}
+		buzzerWasOn = 0;
+	}
+}
+#endif
 void GPIO_Power_MainCPU_ON(void) {
 	HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET);
 }
--- a/Small_CPU/Src/rtc.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/rtc.c	Sun Jan 19 12:02:59 2025 +0100
@@ -29,6 +29,12 @@
 static void RTC_Error_Handler(void);
 
 
+
+void RTC_GetTime(RTC_TimeTypeDef* pstimestructure)
+{
+	HAL_RTC_GetTime(&RTCHandle, pstimestructure, RTC_FORMAT_BIN);
+}
+
 void RTC_SetTime(RTC_TimeTypeDef stimestructure)
 {
 
--- a/Small_CPU/Src/scheduler.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/scheduler.c	Sun Jan 19 12:02:59 2025 +0100
@@ -342,6 +342,9 @@
 	{
 		externalInterface_ExecuteCmd(global.dataSendToSlave.data.externalInterface_Cmd);
 	}
+#ifdef ENABLE_GPIO_V2
+	GPIO_HandleBuzzer();
+#endif
 
 
 #if 0
@@ -1791,6 +1794,8 @@
 
 void copyGNSSdata(void)
 {
+	RTC_TimeTypeDef sTimeNow;
+
 	global.dataSendToMaster.data[0].gnssInfo.coord.fLat = GNSS_Handle.fLat;
 	global.dataSendToMaster.data[0].gnssInfo.coord.fLon = GNSS_Handle.fLon;
 	global.dataSendToMaster.data[0].gnssInfo.fixType = GNSS_Handle.fixType;
@@ -1804,6 +1809,23 @@
 
 	global.dataSendToMaster.data[0].gnssInfo.alive = GNSS_Handle.alive;
 
+	if(( GNSS_Handle.fixType < 2) && (GNSS_Handle.alive & GNSS_ALIVE_BACKUP_POS))		/* fallback to last known position ? */
+	{
+		RTC_GetTime(&sTimeNow);
+		if(GNSS_Handle.last_hour > sTimeNow.Hours)
+		{
+			sTimeNow.Hours += 24;	/* compensate date change */
+		}
+		if(sTimeNow.Hours - GNSS_Handle.last_hour > 2)
+		{
+			GNSS_Handle.alive &= ~GNSS_ALIVE_BACKUP_POS;		/* position outdated */
+		}
+		else
+		{
+			global.dataSendToMaster.data[0].gnssInfo.coord.fLat = GNSS_Handle.last_fLat;
+			global.dataSendToMaster.data[0].gnssInfo.coord.fLon = GNSS_Handle.last_fLon;
+		}
+	}
 	memcpy(&global.dataSendToMaster.data[0].gnssInfo.signalQual,&GNSS_Handle.statSat, sizeof(GNSS_Handle.statSat));
 }
 
--- a/Small_CPU/Src/uartProtocol_GNSS.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/uartProtocol_GNSS.c	Sun Jan 19 12:02:59 2025 +0100
@@ -289,7 +289,9 @@
 													break;
 												case UART_GNSS_LOADCONF_2:	gnssState = UART_GNSS_SETMODE_MOBILE;
 													break;
-												case UART_GNSS_SETMODE_MOBILE: gnssState = UART_GNSS_PWRUP;
+												case UART_GNSS_SETMODE_MOBILE:	rxState = GNSSRX_DETECT_ACK_0;
+																				UART_Gnss_SendCmd(GNSSCMD_MODE_NORMAL);
+																				gnssState = UART_GNSS_PWRUP;
 													break;
 												default:
 													break;
--- a/Small_CPU/Src/uartProtocol_O2.c	Sun Jan 19 12:00:50 2025 +0100
+++ b/Small_CPU/Src/uartProtocol_O2.c	Sun Jan 19 12:02:59 2025 +0100
@@ -134,6 +134,10 @@
 		rxState = O2RX_CONFIRM;
 		uartO2_SetupCmd(localComState,cmdString,&cmdLength);
 		UART_SendCmdString(cmdString);
+		if(localComState == UART_O2_CHECK)
+		{
+			localComState = UART_O2_IDLE;	/* confirmation seems to be send after blinking => the response could be longer as the channel switch time => ignore */
+		}
 	}
 	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
 }