changeset 662:1b995079c045 Betatest

PSCR Mode
author heinrichs weikamp
date Tue, 14 Dec 2021 15:36:10 +0100
parents 87bee7cc77b3
children 16833cd3a2f5
files Common/Inc/data_central.h Common/Inc/data_exchange.h Common/Inc/decom.h Common/Inc/settings.h Common/Src/decom.c Discovery/Inc/configuration.h Discovery/Inc/data_exchange_main.h Discovery/Inc/t7.h Discovery/Inc/tMenuEditXtra.h Discovery/Inc/tStructure.h Discovery/Inc/text_multilanguage.h Discovery/Src/base.c Discovery/Src/check_warning.c Discovery/Src/data_central.c Discovery/Src/data_exchange_main.c Discovery/Src/logbook.c Discovery/Src/settings.c Discovery/Src/show_logbook.c Discovery/Src/t3.c Discovery/Src/t7.c Discovery/Src/tCCR.c Discovery/Src/tMenu.c Discovery/Src/tMenuDeco.c Discovery/Src/tMenuEdit.c Discovery/Src/tMenuEditCustom.c Discovery/Src/tMenuEditDeco.c Discovery/Src/tMenuEditGasOC.c Discovery/Src/tMenuEditPlanner.c Discovery/Src/tMenuEditSetpoint.c Discovery/Src/tMenuEditSystem.c Discovery/Src/tMenuEditXtra.c Discovery/Src/tMenuGas.c Discovery/Src/tMenuSetpoint.c Discovery/Src/tMenuXtra.c Discovery/Src/text_multilanguage.c Small_CPU/Inc/batteryCharger.h Small_CPU/Inc/batteryGasGauge.h Small_CPU/Inc/externalInterface.h Small_CPU/Inc/uart.h Small_CPU/Src/baseCPU2.c Small_CPU/Src/batteryCharger.c Small_CPU/Src/batteryGasGauge.c Small_CPU/Src/dma.c Small_CPU/Src/externalInterface.c Small_CPU/Src/scheduler.c Small_CPU/Src/spi.c Small_CPU/Src/stm32f4xx_hal_msp_v3.c Small_CPU/Src/stm32f4xx_it_v3.c Small_CPU/Src/uart.c
diffstat 49 files changed, 1942 insertions(+), 624 deletions(-) [+]
line wrap: on
line diff
--- a/Common/Inc/data_central.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Common/Inc/data_central.h	Tue Dec 14 15:36:10 2021 +0100
@@ -50,7 +50,8 @@
 	uint8_t setPoint_cbar;
 	uint8_t change_during_ascent_depth_meter_otherwise_zero;
 	uint8_t GasIdInSettings;
-	uint8_t temp1_for16bitalign;
+	uint8_t AppliedDiveMode;
+	float pscr_factor;
 } 	SGas;
 
 typedef struct
@@ -75,6 +76,13 @@
 		uint8_t data[12];
 } 	SDataWireless;
 
+
+typedef struct
+{
+		uint16_t CO2_ppm;
+		uint16_t signalStrength;
+} 	SCO2Sensor;
+
 /* Main structs -------------------------------------------------------------*/
 
 
@@ -187,6 +195,8 @@
 	uint16_t ambient_light_level;
 	SDataWireless wireless_data[4];
 	uint8_t buttonPICdata[4];
+	SCO2Sensor CO2_data;
+
 
 	/* by create DiveSettings() and by setActualGas()
 	 * is send to Small CPU2 for nitrogen calculation
@@ -221,6 +231,9 @@
 	 float ppO2Sensor_bar[3];
 	 float sensorVoltage_mV[3];
 	 float HUD_battery_voltage_V;
+
+/* for PSCR Mode */
+	 float ppo2Simulated_bar;
 } 	SLifeData;
 
 
@@ -323,6 +336,9 @@
 	 */
 	float internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero;
 	uint16_t compassHeading;
+
+	uint8_t pscr_o2_drop;
+	uint8_t pscr_lung_ratio;
  }  SDiveSettings;
 
 enum CHARGE_STATUS{
@@ -454,4 +470,6 @@
 
 _Bool is_ambient_pressure_close_to_surface(SLifeData *lifeData);
 
+uint8_t isLoopMode(uint8_t Mode);
+
 #endif // DATA_CENTRAL_H
--- a/Common/Inc/data_exchange.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Common/Inc/data_exchange.h	Tue Dec 14 15:36:10 2021 +0100
@@ -31,6 +31,10 @@
 #include "settings.h"
 #include "stm32f4xx_hal.h"
 
+/* Command definitions for contral of external interface */
+#define EXT_INTERFACE_33V_ON	(0x8000u)	/* Bit set to enable 3.3V power interface */
+#define EXT_INTERFACE_CO2_CALIB (0x0001u)	/* Request calibration of CO2Sensor */
+
 enum MODE
 {
 	MODE_SURFACE	= 0,
@@ -80,9 +84,11 @@
 #define CRBUTTON 			(0x01)
 #define CRDATE 				(0x02)
 #define CRTIME 				(0x04)
-#define CRCLEARDECO		(0x08)
-#define CRCOMPASS 		(0x10)
-#define CRDEVICEDATA 	(0x20)
+#define CRCLEARDECO			(0x08)
+#define CRCOMPASS 			(0x10)
+#define CRDEVICEDATA 		(0x20)
+#define CRBATTERY			(0x40)
+#define CRACCIDENT			(0x80)
 
 typedef union{
 confirmbit8_t ub;
@@ -148,7 +154,10 @@
 		uint16_t ambient_light_level;
 		uint16_t SPARE_ALIGN32;
 		float	extADC_voltage[3];
-		uint8_t SPARE_OldWireless[50]; /* 64 - 12 for extADC */
+		uint16_t CO2_ppm;
+		uint16_t CO2_signalStrength;
+		uint16_t externalInterface_CmdAnswer;
+		uint8_t SPARE_OldWireless[44]; /* 64 - 12 for extADC - 6 for CO2 */
 		// PIC data
 		uint8_t button_setting[4]; /* see dependency to SLiveData->buttonPICdata */
 		uint8_t SPARE1;
@@ -166,8 +175,7 @@
 		int8_t offsetPressureSensor_mbar;
 		int8_t offsetTemperatureSensor_centiDegree;
 
-		uint8_t SPARE1;
-		uint8_t SPARE2;
+		uint16_t externalInterface_Cmd;
 
 		float UNUSED1[16-1];//VPM_adjusted_critical_radius_he[16];
 		float UNUSED2[16];//VPM_adjusted_critical_radius_n2[16];
--- a/Common/Inc/decom.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Common/Inc/decom.h	Tue Dec 14 15:36:10 2021 +0100
@@ -46,6 +46,8 @@
 void test_decom_CreateGasChangeList(void);
 
 float decom_calc_ppO2(const float ambiant_pressure_bar, const SGas* pGas);
+float decom_calc_SimppO2(float ambiant_pressure_bar, const SGas* pGas);
+float decom_calc_SimppO2_O2based(float ambiant_pressure_bar, uint8_t O2PerCent, float factor);
 void decom_oxygen_calculate_otu(float* oxygen_otu, float pressure_oxygen_real);
 void decom_oxygen_calculate_otu_degrade(float* oxygen_otu, long seconds_since_last_dive);
 void decom_oxygen_calculate_cns_degrade(float* oxygen_cns, long seconds_since_last_dive);
--- a/Common/Inc/settings.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Common/Inc/settings.h	Tue Dec 14 15:36:10 2021 +0100
@@ -47,11 +47,13 @@
 
 #define CCRMODE_FixedSetpoint 0
 #define CCRMODE_Sensors 1
+#define CCRMODE_Simulation 2
 
 #define DIVEMODE_OC 0
 #define DIVEMODE_CCR 1
 #define DIVEMODE_Gauge 2
 #define DIVEMODE_Apnea 3
+#define DIVEMODE_PSCR 4
 
 #define GF_MODE 1
 #define VPM_MODE 2
@@ -74,6 +76,12 @@
 #define MAX_SCRUBBER_TIME 		(500u)
 #define MIN_PPO2_SP_CBAR		(40u)
 
+#define PSCR_MAX_O2_DROP		(15u)
+#define PSCR_MIN_LUNG_RATIO		(5u)
+#define PSCR_MAX_LUNG_RATIO		(20u)
+
+#define FUTURE_SPARE_SIZE		(29u)		/* Applied for reuse of old, not used, scooter block (was 32 bytes)*/
+
 typedef enum
 {
 	O2_SENSOR_SOURCE_OPTIC = 0,
@@ -202,13 +210,10 @@
 	uint8_t bluetoothActive; /* will be set to zero on each startup at the moment */
 	uint8_t safetystopDepth;
 	uint32_t updateSettingsAllowedFromHeader;
-	uint8_t scooterControl;
-	uint8_t scooterDrag;
-	uint8_t scooterLoad;
-	uint8_t scooterNumberOfBatteries;
-	uint16_t scooterBattSize;
-	uint8_t scooterSPARE1[7];
-	uint8_t scooterSPARE2[19];
+	uint8_t pscr_lung_ratio;									/* redefined in 0xFFFF0020 */
+	uint8_t pscr_o2_drop;										/* redefined in 0xFFFF0020 */
+	uint8_t co2_sensor_active;									/* redefined in 0xFFFF0021 */
+	uint8_t Future_SPARE[FUTURE_SPARE_SIZE];					/* redefined in 0xFFFF0020 (old scooter Block was 32 byte)*/
 	// new in 0xFFFF0006
 	uint8_t ppo2sensors_deactivated;
 	uint8_t tX_colorscheme;
@@ -340,4 +345,7 @@
 uint8_t settingsHelperButtonSens_translate_percentage_to_hwOS_values(uint8_t inputValuePercentage);
 uint8_t settingsHelperButtonSens_translate_hwOS_values_to_percentage(uint8_t inputValuePIC);
 
+void reset_SettingWarning();
+uint8_t isSettingsWarning();
+
 #endif // SETTINGS_H
--- a/Common/Src/decom.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Common/Src/decom.c	Tue Dec 14 15:36:10 2021 +0100
@@ -217,24 +217,34 @@
 	float ppo2_fraction_setpoint;
 	float diluent_divisor;
 
-
 	*fraction_nitrogen = ((float)pGas->nitrogen_percentage) / 100.0f;
 	*fraction_helium = ((float)pGas->helium_percentage) / 100.0f;
 
-	if(!pGas->setPoint_cbar)
-		return;
+	if(pGas->AppliedDiveMode == DIVEMODE_CCR)
+	{
+		// continue with CCR
+		fraction_all_inertgases = *fraction_nitrogen + *fraction_helium;
 
-	// continue with CCR
-	fraction_all_inertgases = *fraction_nitrogen + *fraction_helium;
+		ppo2_fraction_setpoint = (float)pGas->setPoint_cbar/ (100 * ambient_pressure_bar);
+
+		diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases;
+		if(diluent_divisor < 0)
+			diluent_divisor = 0;
 
-	ppo2_fraction_setpoint = (float)pGas->setPoint_cbar/ (100 * ambient_pressure_bar);
+		*fraction_nitrogen *= diluent_divisor;
+		*fraction_helium   *= diluent_divisor;
+	}
+	if(pGas->AppliedDiveMode == DIVEMODE_PSCR)
+	{
+		fraction_all_inertgases = *fraction_nitrogen + *fraction_helium;
+		ppo2_fraction_setpoint =  decom_calc_SimppO2(ambient_pressure_bar, pGas) / ambient_pressure_bar;
+		diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases;
+		if(diluent_divisor < 0)
+			diluent_divisor = 0;
 
-	diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases;
-	if(diluent_divisor < 0)
-		diluent_divisor = 0;
-
-	*fraction_nitrogen *= diluent_divisor;
-	*fraction_helium   *= diluent_divisor;
+		*fraction_nitrogen *= diluent_divisor;
+		*fraction_helium   *= diluent_divisor;
+	}
 }
 
 
@@ -618,13 +628,13 @@
 								pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage;
 								pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage;
 								pInput->decogaslist[count].GasIdInSettings = i;
-
+								pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_OC;
 						}
 				}
 		}
 		else
 		{
-			//divmode CCR
+			//divmode CCR or PSCR
 				for(i=6; i <= 10; i++)
 				{
 						if(pInput->gas[i].note.ub.active && pInput->gas[i].depth_meter
@@ -642,55 +652,69 @@
 								}
 								pInput->decogaslist[count].change_during_ascent_depth_meter_otherwise_zero = pInput->gas[i].depth_meter;
 								pInput->decogaslist[count].nitrogen_percentage = 100;
-								pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage;
+								if(pInput->diveMode == DIVEMODE_PSCR)
+								{
+									pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_PSCR;
+									pInput->decogaslist[count].setPoint_cbar = decom_calc_SimppO2_O2based((float)(pInput->gas[i].depth_meter / 10.0 + 1.0), pInput->gas[i].oxygen_percentage, pInput->decogaslist[count].pscr_factor ) * 100;
+									pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage;
+								}
+								else
+								{
+									pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage;
+								}
 								pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage;
 								pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage;
 								pInput->decogaslist[count].GasIdInSettings = i;
 
 						}
 				}
-				/* Include Setpoint Changes */
-				for(j=0; j <= count; j++)
+				if(pInput->diveMode == DIVEMODE_CCR)
 				{
-					uint8_t depth = 0;
-					uint8_t changedepth = 0;
-					char newSetpoint;
-					if(j == 0)
-					{
-						depth = pLifeData->depth_meter;
-					}
-					else
-					{
-						//no setpointchange ?
-						pInput->decogaslist[j].setPoint_cbar =  pInput->decogaslist[j - 1].setPoint_cbar;
-						depth = pInput->decogaslist[j].change_during_ascent_depth_meter_otherwise_zero + 0.1f;
-					}
-					/* Setpoint change at the same depth as gas changes */
-					if(nextSetpointChange(pInput,depth + 1, &changedepth,&newSetpoint) && changedepth == depth)
+					/* Include Setpoint Changes */
+					for(j=0; j <= count; j++)
 					{
-						 pInput->decogaslist[j].setPoint_cbar = newSetpoint;
-					}
-					/* Setpoint changes inbetween gas changes */
-					while(nextSetpointChange(pInput, depth, &changedepth,&newSetpoint)
-							&& (
-										( (j < count) && (changedepth > pInput->decogaslist[j + 1].change_during_ascent_depth_meter_otherwise_zero))
-										|| ((j == count) && (changedepth > 0))
-								 ))
-					{
-						//Include new entry with setpoint change in decogaslist
-						for(int k = count; k > j; k--)
+						uint8_t depth = 0;
+						uint8_t changedepth = 0;
+						char newSetpoint;
+
+						pInput->decogaslist[j].AppliedDiveMode = DIVEMODE_CCR;
+						if(j == 0)
+						{
+							depth = pLifeData->depth_meter;
+						}
+						else
+						{
+							//no setpointchange ?
+							pInput->decogaslist[j].setPoint_cbar =  pInput->decogaslist[j - 1].setPoint_cbar;
+							depth = pInput->decogaslist[j].change_during_ascent_depth_meter_otherwise_zero + 0.1f;
+						}
+						/* Setpoint change at the same depth as gas changes */
+						if(nextSetpointChange(pInput,depth + 1, &changedepth,&newSetpoint) && changedepth == depth)
 						{
-								 pInput->decogaslist[k+1] = pInput->decogaslist[k];
+							 pInput->decogaslist[j].setPoint_cbar = newSetpoint;
 						}
-						pInput->decogaslist[j + 1] =  pInput->decogaslist[j];
-						pInput->decogaslist[j + 1].setPoint_cbar = newSetpoint;
-						j++;
-						count++;
-						depth = changedepth;
+						/* Setpoint changes inbetween gas changes */
+						while(nextSetpointChange(pInput, depth, &changedepth,&newSetpoint)
+								&& (
+											( (j < count) && (changedepth > pInput->decogaslist[j + 1].change_during_ascent_depth_meter_otherwise_zero))
+											|| ((j == count) && (changedepth > 0))
+									 ))
+						{
+							//Include new entry with setpoint change in decogaslist
+							for(int k = count; k > j; k--)
+							{
+									 pInput->decogaslist[k+1] = pInput->decogaslist[k];
+							}
+							pInput->decogaslist[j + 1] =  pInput->decogaslist[j];
+							pInput->decogaslist[j + 1].setPoint_cbar = newSetpoint;
+							j++;
+							count++;
+							depth = changedepth;
+						}
+
 					}
 
 				}
-
 		}
 }
 void test_decom_CreateGasChangeList(void)
@@ -1022,16 +1046,51 @@
 
 float decom_calc_ppO2(const float ambiant_pressure_bar, const SGas* pGas)
 {
-		float percent_N2 = 0;
+	float percent_N2 = 0;
 	float percent_He = 0;
 	float percent_O2 = 0;
-		decom_get_inert_gases(ambiant_pressure_bar, pGas, &percent_N2, &percent_He);
-		percent_O2 = 1 - percent_N2 - percent_He;
 
-		return  (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2;
+	decom_get_inert_gases(ambiant_pressure_bar, pGas, &percent_N2, &percent_He);
+	percent_O2 = 1 - percent_N2 - percent_He;
+
+	return  (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2;
 }
 
 
+float decom_calc_SimppO2(float ambiant_pressure_bar, const SGas* pGas)
+{
+	float o2Ratio = 0.0;
+	float inertGasRatio = 0.0;
+	float simulatedPSCRppo2 = 0.0;
+
+	o2Ratio = (100.0 - pGas->nitrogen_percentage - pGas->helium_percentage) / 100.0;
+	inertGasRatio = 1.0 - o2Ratio;
+	simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio;
+	simulatedPSCRppo2 -= (inertGasRatio * pGas->pscr_factor);
+	if(simulatedPSCRppo2 < 0.0)
+	{
+		simulatedPSCRppo2 = 0.0;
+	}
+	return simulatedPSCRppo2;
+}
+
+float decom_calc_SimppO2_O2based(float ambiant_pressure_bar, uint8_t O2PerCent, float factor)
+{
+	float o2Ratio = 0.0;
+	float inertGasRatio = 0.0;
+	float simulatedPSCRppo2 = 0.0;
+
+	o2Ratio = O2PerCent / 100.0;
+	inertGasRatio = 1.0 - o2Ratio;
+	simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio;
+	simulatedPSCRppo2 -= (inertGasRatio * factor);
+	if(simulatedPSCRppo2 < 0.0)
+	{
+		simulatedPSCRppo2 = 0.0;
+	}
+	return simulatedPSCRppo2;
+}
+
 uint8_t decom_get_actual_deco_stop(SDiveState* pDiveState)
 {
 		SDecoinfo* pDecoinfo;
--- a/Discovery/Inc/configuration.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/configuration.h	Tue Dec 14 15:36:10 2021 +0100
@@ -61,4 +61,13 @@
 /* Enable to have PPO2 adjustments in T3 sensor view during dive simulation */
 /* #define ENABLE_T3_PPO_SIM */
 
+/* Enable to have PSCR functionality available */
+/* #define ENABLE_PSCR_MODE */
+
+/* Enable to have CO2 sensor functionality available */
+/* #define ENABLE_CO2_SUPPORT */
+
+/* Enable if you are using sensors with a voltage range 8..16 mV at surface / air level */
+/* #define ENABLE_ALTERNATIVE_SENSORTYP */
+
 #endif
--- a/Discovery/Inc/data_exchange_main.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/data_exchange_main.h	Tue Dec 14 15:36:10 2021 +0100
@@ -45,7 +45,7 @@
 void DataEX_copy_to_LifeData(_Bool *modeChangeFlag);
 void DataEX_copy_to_deco(void);
 void DateEx_copy_to_dataOut(void);
-void DataEX_merge_deviceData(void);
+void DataEX_merge_devicedata(void);
 uint32_t DataEX_lost_connection_count(void);
 void DataEX_control_connection_while_asking_for_sleep(void);
 uint8_t DataEX_check_RTE_version__needs_update(void);
@@ -56,4 +56,6 @@
 
 uint16_t DataEX_debug_data(uint16_t *dataOut20x5);
 
+void DataEX_setExtInterface_Cmd(uint16_t Cmd);
+
 #endif /* DATA_EXCHANGE_MAIN_H */
--- a/Discovery/Inc/t7.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/t7.h	Tue Dec 14 15:36:10 2021 +0100
@@ -49,6 +49,9 @@
 #ifdef ENABLE_BOTTLE_SENSOR
 		LCC_BottleBar,
 #endif
+#ifdef ENABLE_PSCR_MODE
+		LCC_SimPpo2,
+#endif
 		LLC_END
 
 } customview_llc_t;
--- a/Discovery/Inc/tMenuEditXtra.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/tMenuEditXtra.h	Tue Dec 14 15:36:10 2021 +0100
@@ -33,5 +33,6 @@
 
 void openEdit_Xtra(uint8_t line);
 void refresh_CompassHeading(void);
+void refresh_CO2Data(void);
 
 #endif /* TMENU_EDIT_XTRA_H */
--- a/Discovery/Inc/tStructure.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/tStructure.h	Tue Dec 14 15:36:10 2021 +0100
@@ -195,10 +195,13 @@
 #define StMXTRA_CompassHeading	_MB(2,4,2,1,0)
 
  /* SURFACE MODE */
- #define StMXTRA_ScrubTimer_Max_Minutes	_MB(2,4,1,1,0)
- #define StMXTRA_ScrubTimer_Reset		_MB(2,4,2,1,0)
- #define StMXTRA_ScrubTimer_OP_Mode		_MB(2,4,3,1,0)
-
+#define StMXTRA_ScrubTimer_Max_Minutes	_MB(2,4,1,1,0)
+#define StMXTRA_ScrubTimer_Reset		_MB(2,4,2,1,0)
+#define StMXTRA_ScrubTimer_OP_Mode		_MB(2,4,3,1,0)
+#define StMXTRA_PSCR_O2_Drop			_MB(2,4,4,1,0)
+#define StMXTRA_PSCR_LUNG_RATIO			_MB(2,4,5,1,0)
+#define StMXTRA_CO2_Sensor				_MB(2,4,6,1,0)
+#define StMXTRA_CO2_Sensor_Calib		_MB(2,4,6,2,0)
 
 /* PAGE 5 */
 #define StMDECO		_MB(2,5,0,0,0)
@@ -216,12 +219,13 @@
 /* PAGE 5 EDIT FIELD CONTENT */
 #define StMDECO1_OC						_MB(2,5,1,1,0)
 #define StMDECO1_CC						_MB(2,5,1,2,0)
-#define StMDECO1_Apnea				_MB(2,5,1,3,0)
-#define StMDECO1_Gauge				_MB(2,5,1,4,0)
+#define StMDECO1_Apnea					_MB(2,5,1,3,0)
+#define StMDECO1_Gauge					_MB(2,5,1,4,0)
+#define StMDECO1_PSCR					_MB(2,5,1,5,0)
 
 #define StMDECO2_CCRmode			_MB(2,5,2,1,0)
 #define StMDECO3_PPO2Max			_MB(2,5,3,1,0)
-#define StMDECO4_SafetyStop		_MB(2,5,4,1,0)
+#define StMDECO4_SafetyStop			_MB(2,5,4,1,0)
 #define StMDECO5_FUTURE				_MB(2,5,5,1,0)
 #define StMDECO6_SALINITY			_MB(2,5,6,1,0)
 
@@ -310,7 +314,8 @@
 #define StMSYS5_RebootMainCPU	_MB(2,8,5,9,0)
 #define StMSYS5_ScreenTest		_MB(2,8,5,10,0)
 #define StMSYS5_SetFactoryBC	_MB(2,8,5,11,0)
-#define StMSYS5_SetSampleIndx   _MB(2,8,5,12,0)
+#define StMSYS5_ResetBluetooth	_MB(2,8,5,12,0)
+#define StMSYS5_SetSampleIndx   _MB(2,8,5,13,0)
 
  /* PAGE 9 */
 
--- a/Discovery/Inc/text_multilanguage.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Inc/text_multilanguage.h	Tue Dec 14 15:36:10 2021 +0100
@@ -119,6 +119,7 @@
 		TXT_ClosedCircuit,
 		TXT_Apnoe,
 		TXT_Gauge,
+		TXT_PSClosedCircuit,
 		TXT_Sensor,
 		TXT_FixedSP,
 		TXT_Decoparameters,
@@ -141,6 +142,10 @@
 		TXT_ScrubTimeReset,
 		TXT_ScrubTimeMode,
 		TXT_Percent,
+		TXT_PSCRO2Drop,
+		TXT_PSCRLungRatio,
+		TXT_SimPpo2,
+		TXT_CO2Sensor,
 		/* */
 		TXT_END,
 
@@ -308,6 +313,7 @@
 		TXT2BYTE_Maintenance,
 		TXT2BYTE_SetBatteryCharge,
 		TXT2BYTE_SetFactoryDefaults,
+		TXT2BYTE_ResetBluetooth,
 		TXT2BYTE_SetSampleIndex,
 		TXT2BYTE_Reboot,
 		TXT2BYTE_ButtonLeft,
@@ -335,6 +341,8 @@
 		TXT2BYTE_Normal,
 		TXT2BYTE_Maximum,
 
+		TXT2BYTE_CheckSettings,
+
 		TXT2BYTE_END
 };
 
--- a/Discovery/Src/base.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/base.c	Tue Dec 14 15:36:10 2021 +0100
@@ -507,6 +507,7 @@
         {
 	        DoDisplayRefresh = 0;
 
+	        updateSetpointStateUsed();
             if(stateUsed == stateSimGetPointer())
             {
                 simulation_UpdateLifeData(1);
@@ -588,8 +589,6 @@
     case BaseHome:
     case BaseMenu:
     case BaseInfo:
-        updateSetpointStateUsed();
-
         DateEx_copy_to_dataOut();
         DataEX_copy_to_LifeData(&modeChange);
 //foto session :-)  stateRealGetPointerWrite()->lifeData.battery_charge = 99;
@@ -769,17 +768,20 @@
 					}
 				} else if ((status.page == PageDive) && (status.line != 0))
 				{
-					if (pSettings->extraDisplay == EXTRADISPLAY_BIGFONT)
+					if(get_globalState() == StDMENU)
 					{
-						pSettings->design = 3;
-						if(pSettings->MotionDetection == MOTION_DETECT_SECTOR)
+						if (pSettings->extraDisplay == EXTRADISPLAY_BIGFONT)
 						{
-							DefineSectorCount(CUSTOMER_DEFINED_VIEWS);
-							MapCVToSector();
+							pSettings->design = 3;
+							if(pSettings->MotionDetection == MOTION_DETECT_SECTOR)
+							{
+								DefineSectorCount(CUSTOMER_DEFINED_VIEWS);
+								MapCVToSector();
+							}
 						}
+						else if (pSettings->extraDisplay	== EXTRADISPLAY_DECOGAME)
+							pSettings->design = 4;
 					}
-					else if (pSettings->extraDisplay	== EXTRADISPLAY_DECOGAME)
-						pSettings->design = 4;
 					set_globalState(StD);
 				}
 				else
@@ -1733,7 +1735,7 @@
 					}
 				}
 				// stuff before and new @161121 CCR-sensor limit 10 minutes
-				if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors))
+				if(isLoopMode(settingsGetPointer()->dive_mode) && (settingsGetPointer()->CCR_Mode == CCRMODE_Sensors))
 				{
 					timeout_limit_Surface_in_seconds = settingsGetPointer()->timeoutSurfacemodeWithSensors;
 				}
--- a/Discovery/Src/check_warning.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/check_warning.c	Tue Dec 14 15:36:10 2021 +0100
@@ -128,7 +128,7 @@
 /* Private functions ---------------------------------------------------------*/
 static int8_t check_fallback(SDiveState * pDiveState)
 {
-	if(fallback && ((pDiveState->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR)))
+	if(fallback && ((pDiveState->mode != MODE_DIVE) || (!isLoopMode(pDiveState->diveSettings.diveMode))))
 		fallback = 0;
 	
 	pDiveState->warnings.fallback = fallback;
@@ -181,7 +181,7 @@
 	pDiveState->warnings.sensorOutOfBounds[1] = 0;
 	pDiveState->warnings.sensorOutOfBounds[2] = 0;
 
-	if((pDiveState->diveSettings.diveMode == DIVEMODE_CCR) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors))
+	if(isLoopMode(pDiveState->diveSettings.diveMode) && (pDiveState->diveSettings.CCR_Mode == CCRMODE_Sensors))
 
 		if(settingsGetPointer()->ppo2sensors_source == O2_SENSOR_SOURCE_OPTIC)
 		{
@@ -218,7 +218,7 @@
 	betterGasIdLocal = pLifeData->actualGas.GasIdInSettings;
 	bestGasDepth = 255;
 
-	if(pDiveSettings->diveMode == DIVEMODE_CCR)
+	if(isLoopMode(pDiveSettings->diveMode))
 		gasIdOffset = NUM_OFFSET_DILUENT;
 	else
 		gasIdOffset = 0;
@@ -285,33 +285,31 @@
 {
 	pDiveState->warnings.betterSetpoint = 0;
 	betterSetpointId = 0;
-
-	if((stateUsed->mode != MODE_DIVE) || (pDiveState->diveSettings.diveMode != DIVEMODE_CCR) || (pDiveState->diveSettings.CCR_Mode != CCRMODE_FixedSetpoint))
-	{
-		return 0;
-	}
-	
 	uint8_t bestSetpointDepth = 0; // travel the deeper, the better
 	uint8_t betterSetpointIdLocal = 0; // nothing better
 
-	if(!actualLeftMaxDepth(pDiveState)) /* travel gases */
+
+	if((stateUsed->mode == MODE_DIVE) && (pDiveState->diveSettings.diveMode == DIVEMODE_CCR))
 	{
-		for(int i=1; i<=NUM_GASES; i++)
+		if(!actualLeftMaxDepth(pDiveState)) /* travel gases */
 		{
-			if(	 (pDiveState->diveSettings.setpoint[i].note.ub.active)
-				&& (pDiveState->diveSettings.setpoint[i].depth_meter)
-				&& (pDiveState->diveSettings.setpoint[i].depth_meter <= ( pDiveState->lifeData.depth_meter + 0.01f ))
-				&& (pDiveState->diveSettings.setpoint[i].depth_meter >= bestSetpointDepth)
-			)
-				{
-					betterSetpointIdLocal = i;
-					bestSetpointDepth = pDiveState->diveSettings.setpoint[i].depth_meter;
-				}
-		}
-		if((betterSetpointIdLocal) && (pDiveState->diveSettings.setpoint[betterSetpointIdLocal].setpoint_cbar  != pDiveState->lifeData.actualGas.setPoint_cbar))
-		{
-			betterSetpointId = betterSetpointIdLocal;
-			pDiveState->warnings.betterSetpoint = 1;
+			for(int i=1; i<=NUM_GASES; i++)
+			{
+				if(	 (pDiveState->diveSettings.setpoint[i].note.ub.active)
+					&& (pDiveState->diveSettings.setpoint[i].depth_meter)
+					&& (pDiveState->diveSettings.setpoint[i].depth_meter <= ( pDiveState->lifeData.depth_meter + 0.01f ))
+					&& (pDiveState->diveSettings.setpoint[i].depth_meter >= bestSetpointDepth)
+				)
+					{
+						betterSetpointIdLocal = i;
+						bestSetpointDepth = pDiveState->diveSettings.setpoint[i].depth_meter;
+					}
+			}
+			if((betterSetpointIdLocal) && (pDiveState->diveSettings.setpoint[betterSetpointIdLocal].setpoint_cbar  != pDiveState->lifeData.actualGas.setPoint_cbar))
+			{
+				betterSetpointId = betterSetpointIdLocal;
+				pDiveState->warnings.betterSetpoint = 1;
+			}
 		}
 	}
 	return pDiveState->warnings.betterSetpoint;
--- a/Discovery/Src/data_central.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/data_central.c	Tue Dec 14 15:36:10 2021 +0100
@@ -71,6 +71,7 @@
 #include "ostc.h" // for button adjust on hw testboard 1
 #include "tCCR.h"
 #include "crcmodel.h"
+#include "configuration.h"
 
 static SDiveState stateReal = { 0 };
 SDiveState stateSim = { 0 };
@@ -316,6 +317,7 @@
 
 void createDiveSettings(void)
 {
+	int i;
 	SSettings* pSettings = settingsGetPointer();
 
 	setActualGasFirst(&stateReal.lifeData);
@@ -325,7 +327,13 @@
 
 	stateReal.diveSettings.diveMode = pSettings->dive_mode;
 	stateReal.diveSettings.CCR_Mode = pSettings->CCR_Mode;
-	if(stateReal.diveSettings.diveMode == DIVEMODE_CCR)
+	if((stateReal.diveSettings.diveMode == DIVEMODE_PSCR) && (stateReal.diveSettings.CCR_Mode == CCRMODE_FixedSetpoint))
+	{
+		/* TODO: update selection of sensor used on/off (currently sensor/fixpoint). As PSCR has no fixed setpoint change to simulated ppo2 if sensors are not active */
+		stateReal.diveSettings.CCR_Mode = CCRMODE_Simulation;
+	}
+
+	if(isLoopMode(stateReal.diveSettings.diveMode))
 		stateReal.diveSettings.ccrOption = 1;
 	else
 		stateReal.diveSettings.ccrOption = 0;
@@ -341,13 +349,24 @@
 	stateReal.diveSettings.ppo2sensors_deactivated = pSettings->ppo2sensors_deactivated;
 	stateReal.diveSettings.future_TTS_minutes = pSettings->future_TTS;
 	
+	stateReal.diveSettings.pscr_lung_ratio = pSettings->pscr_lung_ratio;
+	stateReal.diveSettings.pscr_o2_drop = pSettings->pscr_o2_drop;
+
+	if(stateReal.diveSettings.diveMode == DIVEMODE_PSCR)
+	{
+		for(i=0; i<5; i++)
+		{
+			stateReal.diveSettings.decogaslist[i].pscr_factor = 1.0 / stateReal.diveSettings.pscr_lung_ratio * stateReal.diveSettings.pscr_o2_drop;
+		}
+	}
+
 	decom_CreateGasChangeList(&stateReal.diveSettings, &stateReal.lifeData); // decogaslist
 	stateReal.diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = 0;
 
 	/* for safety */
 	stateReal.diveSettings.input_second_to_last_stop_depth_bar = stateReal.diveSettings.last_stop_depth_bar + stateReal.diveSettings.input_next_stop_increment_depth_bar;
 	/* and the proper calc */
-	for(int i = 1; i <10; i++)
+	for(i = 1; i <10; i++)
 	{
 		if(stateReal.diveSettings.input_next_stop_increment_depth_bar * i > stateReal.diveSettings.last_stop_depth_bar)
 		{
@@ -389,9 +408,11 @@
 }
 
 
+
+
 void updateSetpointStateUsed(void)
 {
-	if(stateUsed->diveSettings.diveMode != DIVEMODE_CCR)
+	if(!isLoopMode(stateReal.diveSettings.diveMode))
 	{
 		stateUsedWrite->lifeData.actualGas.setPoint_cbar = 0;
 		stateUsedWrite->lifeData.ppO2 = decom_calc_ppO2(stateUsed->lifeData.pressure_ambient_bar, &stateUsed->lifeData.actualGas);
@@ -402,7 +423,17 @@
 		{
 			stateUsedWrite->lifeData.actualGas.setPoint_cbar = get_ppO2SensorWeightedResult_cbar();
 		}
-
+#ifdef ENABLE_PSCR_MODE
+		if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR)	/* calculate a ppO2 value based on assumptions ( transfered approach from hwos code) */
+		{
+			stateUsedWrite->lifeData.ppo2Simulated_bar = decom_calc_SimppO2_O2based(stateUsed->lifeData.pressure_ambient_bar, stateReal.diveSettings.gas[stateUsed->lifeData.actualGas.GasIdInSettings].oxygen_percentage, stateUsed->lifeData.actualGas.pscr_factor);
+			if(stateUsed->diveSettings.CCR_Mode == CCRMODE_Simulation)
+			{
+				stateUsedWrite->lifeData.actualGas.setPoint_cbar = stateUsedWrite->lifeData.ppo2Simulated_bar * 100;
+			}
+		}
+#endif
+	/* limit calculated value to the physically possible if needed */
 		if((stateUsed->lifeData.pressure_ambient_bar * 100) < stateUsed->lifeData.actualGas.setPoint_cbar)
 			stateUsedWrite->lifeData.ppO2 = stateUsed->lifeData.pressure_ambient_bar;
 		else
@@ -417,7 +448,7 @@
 	uint8_t gasId = 0;
 	uint8_t setpoint_cbar = 0;
 
-	if(pSettings->dive_mode == DIVEMODE_CCR)
+	if(isLoopMode(pSettings->dive_mode))
 	{
 		setpoint_cbar = pSettings->setpoint[1].setpoint_cbar;
 		start = NUM_OFFSET_DILUENT+1;
@@ -449,6 +480,7 @@
 	lifeData->actualGas.helium_percentage =0;
 	lifeData->actualGas.setPoint_cbar = 0;
 	lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
+	lifeData->actualGas.AppliedDiveMode = stateUsed->diveSettings.diveMode;
 }
 
 
@@ -466,8 +498,9 @@
 	lifeData->actualGas.helium_percentage = pSettings->gas[gasId].helium_percentage;
 	lifeData->actualGas.setPoint_cbar = setpoint_cbar;
 	lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
-	
-	if((pSettings->dive_mode == DIVEMODE_CCR) && (gasId > NUM_OFFSET_DILUENT))
+	lifeData->actualGas.AppliedDiveMode = pSettings->dive_mode;
+	lifeData->actualGas.pscr_factor = 1.0 / pSettings->pscr_lung_ratio * pSettings->pscr_o2_drop;
+	if(isLoopMode(pSettings->dive_mode) && (gasId > NUM_OFFSET_DILUENT))
 		lifeData->lastDiluent_GasIdInSettings = gasId;
 }
 
@@ -525,7 +558,7 @@
   lifeData->actualGas.helium_percentage = helium;
   lifeData->actualGas.setPoint_cbar = setpoint_cbar;
   lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
-
+  lifeData->actualGas.AppliedDiveMode = stateUsed->diveSettings.diveMode;
 }
 
 void setButtonResponsiveness(uint8_t *ButtonSensitivyList)
@@ -814,3 +847,12 @@
 	return compass_compensated;
 }
 
+uint8_t isLoopMode(uint8_t Mode)
+{
+	uint8_t retVal = 0;
+	if((Mode == DIVEMODE_CCR) || (Mode == DIVEMODE_PSCR))
+	{
+		retVal = 1;
+	}
+	return retVal;
+}
--- a/Discovery/Src/data_exchange_main.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/data_exchange_main.c	Tue Dec 14 15:36:10 2021 +0100
@@ -72,7 +72,7 @@
 #include "buehlmann.h"
 #include "externLogbookFlash.h"
 
-//#define TESTBENCH
+/* #define TESTBENCH */
 
 /* Exported variables --------------------------------------------------------*/
 static uint8_t	wasPowerOn = 0;
@@ -94,6 +94,8 @@
 
 static uint8_t DeviceDataUpdated = 0;
 
+static uint16_t externalInterface_Cmd = 0;
+
 /* Private types -------------------------------------------------------------*/
 #define UNKNOWN_TIME_HOURS		1
 #define UNKNOWN_TIME_MINUTES	0
@@ -181,12 +183,12 @@
 	if(getDeviceDataWasSend)
 	{
 		dataOut.getDeviceDataNow = 0;
-		requestNecessary.ub.devicedata = 1;
 	}
 	getDeviceDataWasSend = 0;
 	if(dataOut.getDeviceDataNow)
 	{
 		getDeviceDataWasSend = 1;
+		requestNecessary.ub.devicedata = 1;
 	}
 	
 	if(setEndDiveWasSend)
@@ -203,40 +205,39 @@
 	if(setAccidentFlagWasSend)
 	{
 		dataOut.setAccidentFlag = 0;
-		requestNecessary.ub.accident = 1;
 	}
 	setAccidentFlagWasSend = 0;
 	if(dataOut.setAccidentFlag)
 	{
 		setAccidentFlagWasSend = 1;
+		requestNecessary.ub.accident = 1;
 	}
 
 	if(setDateWasSend)
 	{
 		dataOut.setDateNow = 0;
-		requestNecessary.ub.date = 1;
 	}
 	setDateWasSend = 0;
 	if(dataOut.setDateNow)
 	{
 		setDateWasSend = 1;
+		requestNecessary.ub.date = 1;
 	}
 
 	if(setTimeWasSend)
 	{
 		dataOut.setTimeNow = 0;
-		requestNecessary.ub.time = 1;
 	}
 	setTimeWasSend = 0;
 	if(dataOut.setTimeNow)
 	{
 		setTimeWasSend = 1;
+		requestNecessary.ub.time = 1;
 	}
 
 	if(calibrateCompassWasSend)
 	{
 		dataOut.calibrateCompassNow = 0;
-		requestNecessary.ub.compass = 1;
 	}
 	calibrateCompassWasSend = 0;
 	if(dataOut.calibrateCompassNow)
@@ -247,22 +248,23 @@
 	if(clearDecoWasSend)
 	{
 		dataOut.clearDecoNow = 0;
-		requestNecessary.ub.clearDeco = 1;
+		requestNecessary.ub.compass = 1;
 	}
 	if(dataOut.clearDecoNow)
 	{
 		clearDecoWasSend = 1;
+		requestNecessary.ub.clearDeco = 1;
 	}
 	
 	if(setButtonSensitivityWasSend)
 	{
 		dataOut.setButtonSensitivityNow = 0;
-		requestNecessary.ub.button = 1;
 	}
 	setButtonSensitivityWasSend = 0;
 	if(dataOut.setButtonSensitivityNow)
 	{
 		setButtonSensitivityWasSend = 1;
+		requestNecessary.ub.button = 1;
 	}
 }
 
@@ -389,6 +391,13 @@
 	dataOut.data.offsetPressureSensor_mbar = settings->offsetPressure_mbar;
 	dataOut.data.offsetTemperatureSensor_centiDegree = settings->offsetTemperature_centigrad;
 
+	if(settings->co2_sensor_active)
+	{
+		externalInterface_Cmd |= EXT_INTERFACE_33V_ON;
+	}
+	dataOut.data.externalInterface_Cmd = externalInterface_Cmd;
+	externalInterface_Cmd = 0;
+
 	if((hardwareDataGetPointer()->primarySerial <= 32) || (((hardwareDataGetPointer()->primarySerial == 72) && (hardwareDataGetPointer()->secondarySerial == 15))))
 	{
 		dataOut.revisionHardware = 0x00;
@@ -773,9 +782,14 @@
 
 void DataEX_copy_to_LifeData(_Bool *modeChangeFlag)
 {
+	static uint16_t getDeviceDataAfterStartOfMainCPU = 20;
+
 	SDiveState *pStateReal = stateRealGetPointerWrite();
-	static uint16_t getDeviceDataAfterStartOfMainCPU = 20;
 	uint8_t idx;
+	float meter = 0;
+	SSettings *pSettings;
+
+
 	
 	// wireless - �ltere daten aufr�umen
 #if 0
@@ -836,23 +850,46 @@
 		}
 	}
 
-	/* new 151207 hw */
-	if(requestNecessary.uw != 0)
+	if((requestNecessary.uw != 0) && (dataIn.confirmRequest.uw != 0))
 	{
 		if(((dataIn.confirmRequest.uw) & CRBUTTON) != 0)
 		{
 			requestNecessary.ub.button = 0;
 		}
+		if(((dataIn.confirmRequest.uw) & CRCLEARDECO) != 0)
+		{
+			requestNecessary.ub.clearDeco = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRDATE) != 0)
+		{
+			requestNecessary.ub.date = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRTIME) != 0)
+		{
+			requestNecessary.ub.time = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRCOMPASS) != 0)
+		{
+			requestNecessary.ub.compass = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRDEVICEDATA) != 0)
+		{
+			requestNecessary.ub.devicedata = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRBATTERY) != 0)
+		{
+			requestNecessary.ub.batterygauge = 0;
+		}
+		if(((dataIn.confirmRequest.uw) & CRACCIDENT) != 0)
+		{
+			requestNecessary.ub.accident = 0;
+		}
 
-		if(requestNecessary.ub.button == 1)
+		if(requestNecessary.ub.button == 1)	/* send button values to RTE */
 		{
 			setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness);
 		}
 	}
-	requestNecessary.uw = 0; // clear all 
-	
-	float meter = 0;
-	SSettings *pSettings;
 
 	/*	uint8_t IAmStolenPleaseKillMe;
 	 */
@@ -909,7 +946,6 @@
 		pStateReal->lifeData.dateBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_dr;
 		pStateReal->lifeData.timeBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_tr;
 	}
-	dataOut.setAccidentFlag = 0;
 
 	if(pStateReal->data_old__lost_connection_to_slave == 0)
 	{
@@ -971,11 +1007,25 @@
 			  pStateReal->lifeData.max_depth_meter = meter;
 		}
 
-		if(dataIn.accidentFlags & ACCIDENT_DECOSTOP)
-			pStateReal->decoMissed_at_the_end_of_dive = 1;
-		if(dataIn.accidentFlags & ACCIDENT_CNS)
-			pStateReal->cnsHigh_at_the_end_of_dive = 1;
-
+		if(requestNecessary.ub.clearDeco == 0)		/* No "reset deco" is send to RTE ? */
+		{
+			if(dataIn.accidentFlags & ACCIDENT_DECOSTOP)
+			{
+				pStateReal->decoMissed_at_the_end_of_dive = 1;
+			}
+			else
+			{
+				pStateReal->decoMissed_at_the_end_of_dive = 0;
+			}
+			if(dataIn.accidentFlags & ACCIDENT_CNS)
+			{
+				pStateReal->cnsHigh_at_the_end_of_dive = 1;
+			}
+			else
+			{
+				pStateReal->cnsHigh_at_the_end_of_dive = 0;
+			}
+		}
 		pStateReal->lifeData.dive_time_seconds = (int32_t)dataIn.data[dataIn.boolTimeData].divetime_seconds;
 		pStateReal->lifeData.dive_time_seconds_without_surface_time = (int32_t)dataIn.data[dataIn.boolTimeData].dive_time_seconds_without_surface_time;
 		pStateReal->lifeData.counterSecondsShallowDepth = dataIn.data[dataIn.boolTimeData].counterSecondsShallowDepth;
@@ -1030,6 +1080,10 @@
 		/* sensorErrors
 		 */
 		pStateReal->sensorErrorsRTE = dataIn.sensorErrors;
+
+		/* data from CO2 sensor */
+		pStateReal->lifeData.CO2_data.CO2_ppm = dataIn.data[0].CO2_ppm;
+		pStateReal->lifeData.CO2_data.signalStrength = dataIn.data[0].CO2_signalStrength;
 	}
 
 	/* apnea specials
@@ -1205,3 +1259,10 @@
 
 	return retval;
 }
+
+void DataEX_setExtInterface_Cmd(uint16_t Cmd)
+{
+	externalInterface_Cmd = Cmd;
+	return;
+}
+
--- a/Discovery/Src/logbook.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/logbook.c	Tue Dec 14 15:36:10 2021 +0100
@@ -1002,7 +1002,7 @@
             break;
     }
     firstgasid = i + 1;
-    if(header.diveMode == DIVEMODE_CCR)
+    if(isLoopMode(header.diveMode))
       setPointLast = header.setpoint[0].setpoint_cbar;
     else
       setPointLast = 0;
@@ -1166,6 +1166,10 @@
 						gas.setPoint_cbar = setPointVal;
 						if(gasidVal > 0)
 						{
+							if((gasidVal >= NUM_GASES) && (header.diveMode == DIVEMODE_PSCR))		/* in case gas switches the absolute gas ID is used => map to the 0..NUM_GASES index used in header */
+							{
+								gasidVal -= NUM_GASES;
+							}
 							gas.helium_percentage = header.gasordil[gasidVal - 1].helium_percentage;
 							gas.nitrogen_percentage = 100 -  gas.helium_percentage - header.gasordil[gasidVal - 1].oxygen_percentage;
 						}
@@ -1175,7 +1179,15 @@
 							gas.nitrogen_percentage = 100 -  gas.helium_percentage - manualGasVal.percentageO2;
 						}
 						ambiant_pressure_bar =((float)(depthVal + header.surfacePressure_mbar))/1000;
-						ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas );
+
+						if(header.diveMode == DIVEMODE_PSCR)
+						{
+							ppO2 = decom_calc_SimppO2(ambiant_pressure_bar, &gas);
+						}
+						else	/* open circuit calculation */
+						{
+							ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas);
+						}
 						ppo2[iNum] = (uint16_t) ( ppO2 * 100);
 					}
 
--- a/Discovery/Src/settings.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/settings.c	Tue Dec 14 15:36:10 2021 +0100
@@ -36,6 +36,8 @@
 #include "t7.h"
 #include "data_central.h"
 
+static uint8_t settingsWarning = 0;		/* Active if setting values have been corrected */
+
 SSettings Settings;
 
 const uint8_t RTErequiredHigh = 2;
@@ -85,10 +87,10 @@
  * There might even be entries with fixed values that have no range
  */
 const SSettings SettingsStandard = {
-    .header = 0xFFFF001F,
+    .header = 0xFFFF0021,
     .warning_blink_dsec = 8 * 2,
     .lastDiveLogId = 0,
-    .logFlashNextSampleStartAddress = 0,
+    .logFlashNextSampleStartAddress = SAMPLESTART,
 
     .gas[0].oxygen_percentage = 21,
     .gas[1].oxygen_percentage = 21,
@@ -219,7 +221,7 @@
     .ppO2_min = 15,
     .CNS_max = 90,
     .ascent_MeterPerMinute_max = 30,
-    .ascent_MeterPerMinute_showGraph = 7,
+    .ascent_MeterPerMinute_showGraph = 30,
     .future_TTS = 5,
     .GF_high = 85,
     .GF_low = 30,
@@ -268,13 +270,9 @@
     .bluetoothActive = 0,
     .safetystopDepth = 5,
     .updateSettingsAllowedFromHeader = 0xFFFF0002,
-    .scooterControl = 0,
-    .scooterDrag = 2,
-    .scooterLoad = 2,
-    .scooterNumberOfBatteries = 1,
-    .scooterBattSize = 760,
-    .scooterSPARE1[0] = 0,
-    .scooterSPARE2[0] = 0,
+	.pscr_lung_ratio = 10,
+	.pscr_o2_drop = 4,
+	.co2_sensor_active = 0,
     .ppo2sensors_deactivated = 0,
     .tX_colorscheme  = 0,
     .tX_userselectedLeftLowerCornerPrimary = LLC_Temperature,
@@ -371,8 +369,6 @@
     SSettings* pSettings = settingsGetPointer();
     const SSettings* pStandard = settingsGetPointerStandard();
 
-    pSettings->scooterControl = 0;
-
     /* Pointing to the old header data => set new data depending on what had been added since last version */
     switch(pSettings->header)
     {
@@ -433,15 +429,7 @@
     case 0xFFFF000F:
         pSettings->compassBearing                   = 0;
         // no break
-    case 0xFFFF0010:
-        pSettings->scooterDrag                      = 2;
-        pSettings->scooterLoad                      = 2;
-        pSettings->scooterSPARE1[0]                 = 0;
-        pSettings->scooterSPARE2[0]                 = 0;
-        // no break
     case 0xFFFF0011:
-        pSettings->scooterNumberOfBatteries         = 1;
-        pSettings->scooterBattSize                  = 760;
         pSettings->lastKnownBatteryPercentage       = 0;
         // no break
     case 0xFFFF0012:
@@ -496,7 +484,21 @@
     	pSettings->ppo2sensors_calibCoeff[0] = 0.0;
     	pSettings->ppo2sensors_calibCoeff[1] = 0.0;
     	pSettings->ppo2sensors_calibCoeff[2] = 0.0;
+    	pSettings->amPMTime = 0;
     	// no break
+    case 0xFFFF001E:
+    	pSettings->autoSetpoint = 0;
+    	pSettings->scrubTimerMax = 0;
+    	pSettings->scrubTimerCur = 0;
+    	pSettings->scrubTimerMode = SCRUB_TIMER_OFF;
+    	// no break
+    case 0xFFFF001F:
+    	pSettings->pscr_lung_ratio = 10;
+    	pSettings->pscr_o2_drop = 4;
+    	// no break
+    case 0xFFFF0020:
+    	pSettings->co2_sensor_active = 0;
+    	// no break;
     default:
         pSettings->header = pStandard->header;
         break; // no break before!!
@@ -536,6 +538,9 @@
     uint8_t firstGasFoundOC = 0;
     uint8_t firstGasFoundCCR = 0;
 
+
+    settingsWarning = 0; /* reset warning indicator */
+
 /*	uint32_t header;
  */
 
@@ -564,7 +569,8 @@
     if(	(Settings.dive_mode != DIVEMODE_OC) 		&&
             (Settings.dive_mode != DIVEMODE_CCR)  	&&
             (Settings.dive_mode != DIVEMODE_Gauge)	&&
-            (Settings.dive_mode != DIVEMODE_Apnea)		)
+            (Settings.dive_mode != DIVEMODE_Apnea)	&&
+			(Settings.dive_mode != DIVEMODE_PSCR))
     {
         Settings.dive_mode = DIVEMODE_OC;
         corrections++;
@@ -618,9 +624,9 @@
         }
         if(Settings.gas[i].note.ub.first)
         {
-            if(Settings.setpoint[i].note.ub.active != 1)
+            if(Settings.gas[i].note.ub.active != 1)
             {
-                Settings.setpoint[i].note.ub.active = 1;
+                Settings.gas[i].note.ub.active = 1;
                 corrections++;
             }
             if(Settings.gas[i].note.ub.travel == 1)
@@ -671,6 +677,7 @@
         Settings.gas[1].note.ub.first = 1;
         Settings.gas[1].note.ub.travel = 0;
         Settings.gas[1].note.ub.deco = 0;
+        corrections++;
     }
     if(!firstGasFoundCCR)
     {
@@ -678,6 +685,7 @@
         Settings.gas[1 + NUM_GASES].note.ub.first = 1;
         Settings.gas[1 + NUM_GASES].note.ub.travel = 0;
         Settings.gas[1 + NUM_GASES].note.ub.deco = 0;
+        corrections++;
     }
 /*	SSetpointLine setpoint[1 + NUM_GASES];
  */
@@ -747,6 +755,7 @@
 /*	uint8_t CCR_Mode;
  */
     if(	(Settings.CCR_Mode != CCRMODE_Sensors) &&
+    		(Settings.CCR_Mode != CCRMODE_Simulation) &&
             (Settings.CCR_Mode != CCRMODE_FixedSetpoint))
     {
         Settings.CCR_Mode = CCRMODE_FixedSetpoint;
@@ -1461,10 +1470,36 @@
     	Settings.scrubTimerMode = SCRUB_TIMER_OFF;
     	corrections++;
     }
+
+    if((Settings.pscr_lung_ratio > PSCR_MAX_LUNG_RATIO) || (Settings.pscr_lung_ratio < PSCR_MIN_LUNG_RATIO))
+    {
+    	Settings.pscr_lung_ratio = 10;
+    	corrections++;
+    }
+    if(Settings.pscr_o2_drop > PSCR_MAX_O2_DROP)
+    {
+    	Settings.pscr_o2_drop = 4;
+    	corrections++;
+    }
+
+    if(Settings.co2_sensor_active > 1)
+    {
+    	Settings.co2_sensor_active = 0;
+    	corrections++;
+    }
+
+    if(corrections)
+    {
+    	settingsWarning = 1;
+    }
+    else
+
     if(corrections > 255)
-        return 255;
-    else
-        return (uint8_t)corrections;
+    {
+    	corrections = 255;
+    }
+
+    return (uint8_t)corrections;
 }
 
 
@@ -2921,3 +2956,13 @@
         }
     }
 }
+
+void reset_SettingWarning()
+{
+	settingsWarning = 0;
+}
+inline uint8_t isSettingsWarning()
+{
+	return settingsWarning;
+}
+
--- a/Discovery/Src/show_logbook.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/show_logbook.c	Tue Dec 14 15:36:10 2021 +0100
@@ -35,6 +35,7 @@
 #include "unit.h"
 #include "configuration.h"
 #include "logbook_miniLive.h"
+#include "text_multilanguage.h"
 
 #include <stdint.h>
 #include <stdio.h>
@@ -515,16 +516,19 @@
     switch(logbookHeader.diveMode)
     {
     case DIVEMODE_OC:
-            snprintf(text,20,"open circuit");
+            snprintf(text,20,"%c",TXT_OpenCircuit);
             break;
     case DIVEMODE_CCR:
-            snprintf(text,20,"closed circuit");
+            snprintf(text,20,"%c",TXT_ClosedCircuit);
             break;
     case DIVEMODE_Gauge:
-            snprintf(text,20,"Gauge");
+            snprintf(text,20,"%c",TXT_Gauge);
             break;
     case DIVEMODE_Apnea:
-            snprintf(text,20,"Apnea");
+            snprintf(text,20,"%c",TXT_Apnoe);
+            break;
+    case DIVEMODE_PSCR:
+            snprintf(text,20,"%c",TXT_PSClosedCircuit);
             break;
     }
     Gfx_write_label_var(hgfx, 30, 250,60, &FontT42,CLUT_GasSensor4,text);
@@ -886,6 +890,10 @@
 {
     SWindowGimpStyle wintemp;
     SWindowGimpStyle winsmal;
+    uint8_t gasWasUsed[NUM_GASES * 2];
+    int16_t index = 0;
+    uint8_t loopMode = 0;
+
     wintemp.left = 50;
     wintemp.right = 799 - wintemp.left;
     wintemp.top = 50;
@@ -899,6 +907,40 @@
     uint8_t  gasdata[1000];
     dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
 
+    char msg[15];
+    char gas_name[15];
+    int j = 0;
+
+    loopMode = isLoopMode(logbookHeader.diveMode);
+
+    /* check if gas was used, independent from its active state */
+    for(index = 0; index < NUM_GASES * 2; index++)
+    {
+    	gasWasUsed[index] = 0;
+    }
+    for(index = 0; index < dataLength; index++)
+    {
+    	if(loopMode)
+    	{
+    		if(gasdata[index] < NUM_GASES)	/* the log entry starts with a ID in range 1..4 independend if diluent is used at start */
+			{
+				gasdata[index] += NUM_GASES;
+			}
+    		else
+    		{
+    			loopMode = 0;				/* after the first gas change, no matter if diluent or bailout, the correct ID will be stored */
+    		}
+    	}
+    	if(gasdata[index] > 0)
+    	{
+    		gasWasUsed[gasdata[index]-1] = 1;		/* The ID stored in the samples is starting with 1 (array[0] = gasID1) */
+    	}
+    	else
+    	{
+    		gasWasUsed[0] = 1;
+    	}
+    }
+
     //--- print coordinate system & depth graph with gaschanges ---
     show_logbook_draw_depth_graph(hgfx, StepBackwards, &wintemp, 1, dataLength, depthdata, gasdata, NULL);
 
@@ -906,21 +948,38 @@
     winsmal.left = wintemp.right - 190;
     winsmal.right =  winsmal.left + 150;
 
-    char msg[15];
-    char gas_name[15];
-    int j = 0;
-    for(int i = 4;i >= 0;i--)
+    loopMode = isLoopMode(logbookHeader.diveMode);
+    for(index = (2 * NUM_GASES) -1; index >= 0; index--)
     {
-        if(logbookHeader.gasordil[i].note.ub.active > 0)
+    	if(gasWasUsed[index])
         {
             j++;
+            if(j > 5)	/* limit number of gases displayed to 5 */
+            {
+            	break;
+            }
             winsmal.top	= wintemp.bottom - 5 - j * 26 ;
             winsmal.bottom = winsmal.top + 21  ;
-            uint8_t color = get_colour(i);
+            uint8_t color = get_colour(index);
 
-            print_gas_name(gas_name,15,logbookHeader.gasordil[i].oxygen_percentage,logbookHeader.gasordil[i].helium_percentage);
-            snprintf(msg,15,"G%i: %s",i + 1, gas_name);
-            //msg[10] = 0;
+            if(loopMode)
+            {
+            	if(index < NUM_GASES)		/* Switch to Bailout is not covered by log gas list */
+            	{
+            		snprintf(gas_name,15,"Bailout");
+            		snprintf(msg,15,"G%d: %s",index +1, gas_name);
+            	}
+            	else
+            	{
+            		print_gas_name(gas_name,15,logbookHeader.gasordil[index-NUM_GASES].oxygen_percentage,logbookHeader.gasordil[index-NUM_GASES].helium_percentage);
+            		snprintf(msg,15,"D%d: %s",index +1 - NUM_GASES, gas_name);
+            	}
+            }
+            else
+            {
+            	print_gas_name(gas_name,15,logbookHeader.gasordil[index].oxygen_percentage,logbookHeader.gasordil[index].helium_percentage);
+            	snprintf(msg,15,"G%d: %s",index +1, gas_name);
+            }
             Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,msg);
         }
     }
@@ -933,6 +992,26 @@
         */
 }
 
+static uint8_t check_data_array_empty(uint16_t* pdata)
+{
+	uint8_t ret = 0;
+	uint8_t index = 0;
+	uint8_t emptyCnt = 0;
+
+	for (index=0; index < 10; index++)	/* read the first 10 data points. If all are 0 then the array is rated as empty */
+	{
+		if(*(pdata+index) == 0)
+		{
+			emptyCnt++;
+		}
+	}
+	if(emptyCnt == 10)
+	{
+		ret = 1;
+	}
+	return ret;
+}
+
 static void show_logbook_logbook_show_log_page4(GFX_DrawCfgScreen *hgfx, uint8_t StepBackwards)
 { SWindowGimpStyle wintemp;
     SWindowGimpStyle winsmal;
@@ -950,18 +1029,55 @@
     uint16_t ppO2data[1000];
     uint16_t sensor2[1000];
     uint16_t sensor3[1000];
-        uint16_t *setpoint = ppO2data;
-        uint16_t *sensor1 = ppO2data;
+    uint16_t *setpoint = ppO2data;
+    uint16_t *sensor1 = ppO2data;
+    uint8_t  sensorDataAvailable[] = {0,0,0};
 
 
-        if(logbookHeader.diveMode != DIVEMODE_CCR)
+        if(!isLoopMode(logbookHeader.diveMode))
             dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
         else
         {
-            if(logbookHeader.CCRmode == CCRMODE_FixedSetpoint)
-                dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, setpoint, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-            else
-                dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL);
+        	switch(logbookHeader.CCRmode)
+        	{
+        		case CCRMODE_FixedSetpoint:
+        		default:				dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, setpoint, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        				break;
+        		case CCRMODE_Sensors:	dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata, gasdata, NULL, NULL, NULL, sensor1, sensor2, sensor3, NULL, NULL, NULL, NULL, NULL);
+        								if(!check_data_array_empty(sensor1))
+        								{
+        									sensorDataAvailable[0] = 1;
+        								}
+        								if(!check_data_array_empty(sensor2))
+        								{
+        								    sensorDataAvailable[1] = 1;
+        								}
+        								if(!check_data_array_empty(sensor3))
+        								{
+        								    sensorDataAvailable[2] = 1;
+        								}
+        								if((logbookHeader.diveMode == DIVEMODE_PSCR) && (sensorDataAvailable[0] + sensorDataAvailable[1] + sensorDataAvailable[2] != 3)) /*insert sim data if not all three sensors are in use*/
+        								{
+        									if(sensorDataAvailable[0] == 0)
+        									{
+        										logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        										sensorDataAvailable[0] = 1;
+        									}
+        									else if(sensorDataAvailable[1] == 0)
+        									{
+        										logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        										sensorDataAvailable[1] = 1;
+        									}
+        									else if(sensorDataAvailable[2] == 0)
+        									{
+        										logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, sensor3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        										sensorDataAvailable[2] = 1;
+        									}
+        								}
+        		    	break;
+        		case CCRMODE_Simulation: dataLength = logbook_readSampleData(StepBackwards, 1000, depthdata,gasdata, NULL, ppO2data, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+        				break;
+        	}
         }
 
 
@@ -999,14 +1115,25 @@
     winsmal.left = 799 - 67;//wintemp.right -67;
     winsmal.right = winsmal.left;// + 45;
 
-    color = CLUT_LogbookTemperature;//LOGBOOK_GRAPH_DEPTH;
-    if(logbookHeader.diveMode != DIVEMODE_CCR)
+    color = CLUT_LogbookTemperature;
+
+    if(!isLoopMode(logbookHeader.diveMode))
+    {
     	Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002PP O2");
+    }
     else
-    if(logbookHeader.CCRmode != CCRMODE_Sensors)
-    	Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SETPOINT");
-    else
-    	Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SENSORS");
+    {
+    	switch(logbookHeader.CCRmode)
+    	{
+    		case CCRMODE_FixedSetpoint:
+    		default:				Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SETPOINT");
+    				break;
+    		case CCRMODE_Sensors:	Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SENSORS");
+    		    	break;
+    		case CCRMODE_Simulation: Gfx_write_label_var(hgfx, winsmal.left, winsmal.right,winsmal.top, &FontT24,color,"\002SIM PPO2");
+    				break;
+    	}
+    }
 
     //*** PP O2 ****************************************************
     //calc lines and labels
@@ -1019,7 +1146,7 @@
         if(ppO2data[i]<datamin)
             datamin = ppO2data[i];
     }
-    if((logbookHeader.diveMode == DIVEMODE_CCR) && (logbookHeader.CCRmode == CCRMODE_Sensors))
+    if(isLoopMode(logbookHeader.diveMode) && (logbookHeader.CCRmode == CCRMODE_Sensors))
     {
         for(int i=1;i<dataLength;i++)
         {
@@ -1077,11 +1204,20 @@
     wintemp.top = MaxU32LOG(wintemp.top ,0);
     if(wintemp.top < wintemp.bottom)
     {
-        if((logbookHeader.diveMode == DIVEMODE_CCR) && (logbookHeader.CCRmode == CCRMODE_Sensors))
+    	if(isLoopMode(logbookHeader.diveMode) && (logbookHeader.CCRmode == CCRMODE_Sensors))
         {
-            GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, ppO2data,dataLength,CLUT_LogbookTemperature, NULL);
-            GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor2,dataLength,CLUT_LogbookTemperature, NULL);
-            GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor3,dataLength,CLUT_LogbookTemperature, NULL);
+            if(sensorDataAvailable[0])
+            {
+            	GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, ppO2data,dataLength,CLUT_GasSensor2, NULL);
+            }
+            if(sensorDataAvailable[1])
+            {
+            	GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor2,dataLength,CLUT_GasSensor3, NULL);
+            }
+            if(sensorDataAvailable[2])
+            {
+            	GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, sensor3,dataLength,CLUT_GasSensor4, NULL);
+            }
         }
         else
             GFX_graph_print(hgfx,&wintemp,0,1,datamax,datamin, ppO2data,dataLength,CLUT_LogbookTemperature, NULL);
--- a/Discovery/Src/t3.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/t3.c	Tue Dec 14 15:36:10 2021 +0100
@@ -947,6 +947,9 @@
     SDivetime Stopwatch = {0,0,0,0};
     float fAverageDepth, fAverageDepthAbsolute;
 
+#ifdef ENABLE_PSCR_MODE
+    uint8_t showSimPPO2 = 1;
+#endif
     uint16_t tempWinX0;
     uint16_t tempWinX1;
     uint16_t tempWinY0;
@@ -1264,11 +1267,22 @@
 
             if((stateUsed->diveSettings.ppo2sensors_deactivated & (1<<i)) || (stateUsed->lifeData.ppO2Sensor_bar[i] == 0.0))
             {
-                text[textpointer++] = '\031';
-                text[textpointer++] = ' ';
-                text[textpointer++] = '-';
-                text[textpointer++] = ' ';
-                text[textpointer++] = 0;
+#ifdef ENABLE_PSCR_MODE
+            	if((stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) && (showSimPPO2) && (stateUsed->mode == MODE_DIVE))	/* display ppo2 sim in blue letters in case a slot is not used in the ppo2 custom view */
+            	{
+            		text[textpointer++] = '\023';
+            		textpointer += snprintf(&text[textpointer],TEXTSIZE,"%.2f",stateUsed->lifeData.ppo2Simulated_bar);
+            		showSimPPO2 = 0;
+            	}
+            	else
+#endif
+            	{
+					text[textpointer++] = '\031';
+					text[textpointer++] = ' ';
+					text[textpointer++] = '-';
+					text[textpointer++] = ' ';
+					text[textpointer++] = 0;
+            	}
             }
             else
             {
@@ -1279,7 +1293,7 @@
             GFX_write_string(&FontT105,tXc1,text,0);
 
 
-            if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR))
+            if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && isLoopMode(pSettings->dive_mode))
             {
                  snprintf(text,TEXTSIZE,"\032\002\f%c",TXT_ScrubTime);
                  GFX_write_string(&FontT42,tXc1,text,0);
--- a/Discovery/Src/t7.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/t7.c	Tue Dec 14 15:36:10 2021 +0100
@@ -35,6 +35,7 @@
 #include "gfx_fonts.h"
 #include "logbook_miniLive.h"
 #include "math.h"
+#include "tComm.h"
 #include "tHome.h"
 #include "simulation.h"
 #include "timer.h"
@@ -743,8 +744,11 @@
     }
     else
 */
-    if(DataEX_was_power_on())
+    if(DataEX_was_power_on()) {
         GFX_write_string_color(&FontT42,&t7surfaceR,"cold start",4,CLUT_WarningRed);
+	// Reset the bluetooth interface after a cold start
+	tComm_Set_Bluetooth_Name(1);
+    }
 
     /* time and date */
     translateDate(stateUsed->lifeData.dateBinaryFormat, &Sdate);
@@ -1015,7 +1019,7 @@
     else
     {
     	textIdx = 0;
-        if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR)
+        if(isLoopMode(stateUsed->diveSettings.diveMode))
             gasOffset = NUM_OFFSET_DILUENT;
         else
             gasOffset = 0;
@@ -1090,6 +1094,9 @@
 	case DIVEMODE_CCR:
 		GFX_write_string(&FontT24, &t7c1, "\f\002" "CCR", 0);
 		break;
+	case DIVEMODE_PSCR:
+		GFX_write_string(&FontT24, &t7c1, "\f\002" "PSCR", 0);
+		break;
 	case DIVEMODE_OC:
 		GFX_write_string(&FontT24, &t7c1, "\f\002" "OC", 0);
 		break;
@@ -1610,7 +1617,8 @@
 uint8_t t7_change_customview(uint8_t action)
 {
     uint8_t *pViews;
-    uint8_t *pStartView,*pCurView, *pLastView;
+    uint8_t *pStartView,*pLastView;
+    uint8_t *pCurView = NULL;
     _Bool cv_disabled = 0;
 
     if(stateUsed->mode == MODE_DIVE)
@@ -1694,6 +1702,9 @@
     char text[256];
 	char timeSuffix;
 	uint8_t hoursToDisplay;
+#ifdef ENABLE_PSCR_MODE
+	uint8_t showSimPPO2 = 1;
+#endif
     uint16_t textpointer = 0;
     uint16_t heading = 0;
     int16_t start;
@@ -1790,6 +1801,24 @@
             }
             t7cC.WindowNumberOfTextLines = 3;
         }
+        else if(isSettingsWarning())
+		{
+            if(warning_count_high_time)
+            {
+                shiftWindowY0 += 20;
+                t7cC.WindowY0 -= shiftWindowY0;
+                textpointer = 0;
+                text[textpointer++] = '\001';
+                text[textpointer++] = TXT_2BYTE;
+                text[textpointer++] = TXT2BYTE_CheckSettings;
+                text[textpointer++] = '\n';
+                text[textpointer++] = '\r';
+                text[textpointer++] = 0;
+                GFX_write_string_color(&FontT42,&t7cC,text,1, CLUT_WarningRed);
+                t7cC.WindowY0 += shiftWindowY0;
+            }
+            t7cC.WindowNumberOfTextLines = 1;
+		}
         else // customtext
         {
             lineCountCustomtext = t7_customtextPrepare(text);
@@ -1993,13 +2022,24 @@
         {
             if((stateUsed->diveSettings.ppo2sensors_deactivated & (1<<i)) || (stateUsed->lifeData.ppO2Sensor_bar[i] == 0.0))
             {
-                text[textpointer++] = '\031'; // labelcolor
-                text[textpointer++] = '\001';
-                text[textpointer++] = '-';
-                text[textpointer++] = '\n';
-                text[textpointer++] = '\r';
-                text[textpointer++] = '\030'; // main color
-                text[textpointer] = 0;
+#ifdef ENABLE_PSCR_MODE
+            	if((stateUsed->diveSettings.diveMode == DIVEMODE_PSCR) && (showSimPPO2) && (stateUsed->mode == MODE_DIVE))	/* display ppo2 sim in blue letters in case a slot is not used in the ppo2 custom view */
+            	{
+            		text[textpointer++] = '\023';
+            		textpointer += snprintf(&text[textpointer],100,"\001%01.2f\n\r\030",stateUsed->lifeData.ppo2Simulated_bar);
+            		showSimPPO2 = 0;
+            	}
+            	else
+#endif
+            	{
+					text[textpointer++] = '\031'; // labelcolor
+					text[textpointer++] = '\001';
+					text[textpointer++] = '-';
+					text[textpointer++] = '\n';
+					text[textpointer++] = '\r';
+					text[textpointer++] = '\030'; // main color
+					text[textpointer] = 0;
+            	}
             }
             else
             {
@@ -2515,9 +2555,10 @@
 
         if(stateUsed->diveSettings.ccrOption)
         {
-            if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR)
+        	if(isLoopMode(stateUsed->diveSettings.diveMode))
             {
                 snprintf(TextC2,TEXTSIZE,"\020%01.2f",stateUsed->lifeData.ppO2);
+
                 if(stateUsed->warnings.betterSetpoint && warning_count_high_time && (stateUsed->diveSettings.diveMode == DIVEMODE_CCR))
                 {
                     TextC2[0] = '\a'; // inverse instead of color \020
@@ -2547,7 +2588,7 @@
         TextC2[1] = TXT_2BYTE;
         TextC2[2] = TXT2BYTE_WarnCnsHigh;
         TextC2[3] = 0;
-        GFX_write_string_color(&FontT48,&t7c1,TextC2,0,CLUT_WarningRed);
+        GFX_write_string_color(&FontT42,&t7c1,TextC2,0,CLUT_WarningRed);
     }
     else
     {
@@ -2568,6 +2609,9 @@
             GFX_write_string(&FontT24,&t7c1,"\027\f\002" "CCR",0);
         //  GFX_write_string(&FontT24,&t7c1,"\f\177\177\x80" "CCR",0);
         else
+        if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR)
+                GFX_write_string(&FontT24,&t7c1,"\027\f\002" "PSCR",0);
+        else
         if(stateUsed->diveSettings.ccrOption)
             GFX_write_string(&FontT24,&t7c1,"\f\002\024" "Bailout",0);
         //  GFX_write_string(&FontT24,&t7c1,"\f\177\177\x80\024" "Bailout",0);
@@ -2661,11 +2705,16 @@
     {
     	selection_custom_field++;
     }
-    if((selection_custom_field == LLC_ScrubberTime) && ((settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_OFF) || (settingsGetPointer()->dive_mode != DIVEMODE_CCR)))
+    if((selection_custom_field == LLC_ScrubberTime) && ((settingsGetPointer()->scrubTimerMode == SCRUB_TIMER_OFF) || (!isLoopMode(settingsGetPointer()->dive_mode))))
     {
     	selection_custom_field++;
     }
-
+#ifdef ENABLE_PSCR_MODE
+    if((selection_custom_field == LCC_SimPpo2) && (settingsGetPointer()->dive_mode != DIVEMODE_PSCR))
+    {
+    	selection_custom_field++;
+    }
+#endif
     if(selection_custom_field >= LLC_END)
     {
         selection_custom_field = LLC_Empty;
@@ -2803,6 +2852,12 @@
         	snprintf(text,TEXTSIZE,"\020%u\016\016%%\017", (settingsGetPointer()->scrubTimerCur * 100 / settingsGetPointer()->scrubTimerMax));
         }
 		break;
+#ifdef ENABLE_PSCR_MODE
+    case LCC_SimPpo2:
+        headerText[2] = TXT_SimPpo2;
+        snprintf(text,TEXTSIZE,"\020%.2f\016\016Bar\017",stateUsed->lifeData.ppo2Simulated_bar);
+        break;
+#endif
 
 #ifdef ENABLE_BOTTLE_SENSOR
     case LCC_BottleBar:
@@ -3380,7 +3435,7 @@
     text[textpointer++] = TXT_FutureTTS;
     text[textpointer++] = '\n';
     text[textpointer++] = '\r';
-    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR))
+    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)))
     {
 		text[textpointer++] = TXT_ScrubTime;
 
@@ -3429,7 +3484,7 @@
     else
     	textpointer += snprintf(&text[textpointer],10,"\020%ih", (pDecoinfoFuture->output_time_to_surface_seconds + 59) / 3600);
 
-    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR))
+    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)))
     {
         text[textpointer++] = '\n';
         text[textpointer++] = '\r';
--- a/Discovery/Src/tCCR.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tCCR.c	Tue Dec 14 15:36:10 2021 +0100
@@ -65,6 +65,13 @@
 #define BOTTLE_SENSOR_TIMEOUT		(6000u)     /* signal pressure budget as not received after 10 minutes (6000 * 100ms) */
 
 #define MAX_SENSOR_COMPARE_DEVIATION (0.15f)	/* max deviation between two sensors allowed before their results are rated as suspect */
+#define MAX_SENSOR_VOLTAGE_MV		(250u)		/* max allowed voltage value for a sensor measurement */
+
+#ifdef ENABLE_ALTERNATIVE_SENSORTYP
+#define MIN_SENSOR_VOLTAGE_MV		(3u)		/* min allowed voltage value for a sensor measurement (Inspiration, Submatix, Sentinel Typ) */
+#else
+#define MIN_SENSOR_VOLTAGE_MV		(8u)		/* min allowed voltage value for a sensor measurement (legacy OSTC TYP)  */
+#endif
 
 /* Private variables ---------------------------------------------------------*/
 static SIrLink receiveHUD[2];
@@ -173,8 +180,8 @@
 
         if(sensorActive[i])
         {
-            if(	(stateUsed->lifeData.sensorVoltage_mV[i] < 8) ||
-                    (stateUsed->lifeData.sensorVoltage_mV[i] > 250))
+            if(	(stateUsed->lifeData.sensorVoltage_mV[i] < MIN_SENSOR_VOLTAGE_MV) ||
+                    (stateUsed->lifeData.sensorVoltage_mV[i] > MAX_SENSOR_VOLTAGE_MV))
             {
                 sensorActive[i] = 0;
                 switch(i)
@@ -330,7 +337,7 @@
 	}
 
 	/* decrease scrubber timer only in real dive mode */
-    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (pSettings->dive_mode == DIVEMODE_CCR) && (stateUsed->mode == MODE_DIVE) && (stateUsed == stateRealGetPointer()))
+    if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (stateUsed->mode == MODE_DIVE) && (stateUsed == stateRealGetPointer()))
     {
     	ScrubberTimeoutCount++;
     	if(ScrubberTimeoutCount >= 600)		/* resolution is minutes */
@@ -444,18 +451,25 @@
 static uint8_t tCCR_fallbackToFixedSetpoint(void)
 {
 	uint8_t retVal = 0;
-    if((stateUsed->mode == MODE_DIVE) && (stateUsed->diveSettings.diveMode == DIVEMODE_CCR) && (stateUsed->diveSettings.CCR_Mode == CCRMODE_Sensors) && (stateUsed->diveSettings.fallbackOption))
-    {
-        uint8_t setpointCbar, actualGasID;
+	uint8_t setpointCbar, actualGasID;
 
-        setpointCbar = stateUsed->diveSettings.setpoint[1].setpoint_cbar;
-        stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint;
+    if((stateUsed->mode == MODE_DIVE) && (stateUsed->diveSettings.CCR_Mode == CCRMODE_Sensors) && (stateUsed->diveSettings.fallbackOption))
+    {
+    	if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR)
+    	{
+			setpointCbar = stateUsed->diveSettings.setpoint[1].setpoint_cbar;
+			stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint;
+    	}
+    	else
+    	{
+    		setpointCbar = stateUsed->lifeData.ppo2Simulated_bar * 100;
+    		stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation;
+    	}
+    	actualGasID = stateUsed->lifeData.actualGas.GasIdInSettings;
+    	setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar);
 
-        actualGasID = stateUsed->lifeData.actualGas.GasIdInSettings;
-        setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar);
-
-        set_warning_fallback();
-        retVal = stateUsed->diveSettings.setpoint[1].setpoint_cbar;
+    	set_warning_fallback();
+    	retVal = setpointCbar;
     }
     return retVal;
 }
--- a/Discovery/Src/tMenu.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenu.c	Tue Dec 14 15:36:10 2021 +0100
@@ -58,6 +58,8 @@
 #define MENU_WDW_HIGH	390
 #define KEY_LABEL_HIGH	25	/* Height of the label used for the the user keys */
 
+#define SLOW_UPDATE_CNT	10	/* Some content shall not be update in short intervals => add prescalar */
+
 typedef struct
 {
     uint32_t	StartAddressForPage[MAXPAGES+1];
@@ -530,7 +532,7 @@
         tM_add(StMDECOP);
 //	}
 
-    if((pSettings->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1))
+    if((isLoopMode(pSettings->dive_mode)) || (stateUsed->diveSettings.ccrOption == 1))
     {
         tM_add(StMCG);
         tM_add(StMSP);
@@ -586,23 +588,45 @@
 
 void tM_refresh_live_content(void)
 {
+	static uint8_t slowUpdate = SLOW_UPDATE_CNT;
     uint8_t page = 0;
     char text[MAX_PAGE_TEXTSIZE];
     char subtext[MAX_PAGE_TEXTSIZE];
     uint16_t tabPosition;
 
-    if((get_globalState() == StMSYS) && (actual_menu_content == MENU_SURFACE))
+    uint32_t globalState = get_globalState();
+
+    slowUpdate--;
+    page = menu.pageMemoryForNavigation;
+    switch(globalState)
     {
-        page = menu.pageMemoryForNavigation;
-        tMSystem_refresh(0, text, &tabPosition, subtext);
-        update_content_with_new_frame(page, text, tabPosition, subtext);
+    	case StMSYS: 	if(actual_menu_content == MENU_SURFACE)
+    					{
+    						tMSystem_refresh(0, text, &tabPosition, subtext);
+    						update_content_with_new_frame(page, text, tabPosition, subtext);
+    					}
+    		break;
+    	case StMHARD:	tMHardware_refresh(0, text, &tabPosition, subtext);
+        				update_content_with_new_frame(page, text, tabPosition, subtext);
+        	break;
+    	case StMOG:		if((actual_menu_content != MENU_SURFACE) && (slowUpdate == 0))
+    					{
+    						tMOG_refresh(0, text, &tabPosition, subtext);
+    						update_content_with_new_frame(page, text, tabPosition, subtext);
+    					}
+    		break;
+        case StMCG:		if((actual_menu_content != MENU_SURFACE) && (slowUpdate == 0))
+        				{
+        					tMCG_refresh(0, text, &tabPosition, subtext);
+        					update_content_with_new_frame(page, text, tabPosition, subtext);
+        				}
+    		break;
+    	default:
+    		break;
     }
-    else
-    if(get_globalState() == StMHARD)
+    if(slowUpdate == 0)
     {
-        page = menu.pageMemoryForNavigation;
-        tMHardware_refresh(0, text, &tabPosition, subtext);
-        update_content_with_new_frame(page, text, tabPosition, subtext);
+    	slowUpdate = SLOW_UPDATE_CNT;
     }
 
     tMscreen.FBStartAdress = menu.StartAddressForPage[page];
--- a/Discovery/Src/tMenuDeco.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuDeco.c	Tue Dec 14 15:36:10 2021 +0100
@@ -67,6 +67,9 @@
         case DIVEMODE_Apnea:
             divemode = TXT_Apnoe;
             break;
+        case DIVEMODE_PSCR:
+            divemode = TXT_PSClosedCircuit;
+        break;
         default :
         	divemode = TXT_OpenCircuit;
         	break;
@@ -81,14 +84,22 @@
     strcpy(&text[textPointer],"\n\r");
     textPointer += 2;
 
-    if(data->dive_mode == DIVEMODE_CCR)
+    if(isLoopMode(data->dive_mode))
     {
         if((line == 0) || (line == 2))
         {
-            if(data->CCR_Mode == CCRMODE_Sensors)
-                CcrModusTxtId = TXT_Sensor;
-            else
-                CcrModusTxtId = TXT_FixedSP;
+        	switch(data->CCR_Mode)
+        	{
+        		case CCRMODE_Sensors: CcrModusTxtId = TXT_Sensor;
+        			break;
+        		case CCRMODE_FixedSetpoint: CcrModusTxtId = TXT_FixedSP;
+        			break;
+        		case CCRMODE_Simulation: CcrModusTxtId = TXT_SimPpo2;
+        			break;
+        		default:	CcrModusTxtId = 'X';
+        			break;
+        	}
+
 
             textPointer += snprintf(&text[textPointer], 60,\
                 "%c"
--- a/Discovery/Src/tMenuEdit.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEdit.c	Tue Dec 14 15:36:10 2021 +0100
@@ -213,6 +213,13 @@
 	 	 	 break;
 	 	 case (StMXTRA_CompassHeading & MaskFieldDigit):  refreshFct = refresh_CompassHeading;
 	 	 	 break;
+	 	 case (StMXTRA_PSCR_O2_Drop & MaskFieldDigit): if(settingsGetPointer()->dive_mode != DIVEMODE_PSCR)	/* workaround because PSCR mode is set dynamic */
+	 	 	 	 	 	 	 	 	 	 	 	 	 	 {
+	 		 	 	 	 	 	 	 	 	 	 	 	 	 refreshFct = refresh_CO2Data;
+	 	 	 	 	 	 	 	 	 	 	 	 	 	 }
+	 	 	 break;
+	 	 case (StMXTRA_CO2_Sensor & MaskFieldDigit):  refreshFct = refresh_CO2Data;
+	 	 	 break;
 	 	 case (StMSYS4_Info & MaskFieldDigit): refreshFct = &refresh_InformationPage;
 	 	 	 break;
 	 	 case (StMPLAN5_ExitResult & MaskFieldDigit): refreshFct = refresh_PlanResult;
@@ -256,6 +263,7 @@
 {
     if(WriteSettings)
     {
+    	reset_SettingWarning();
         GFX_logoAutoOff();
         ext_flash_write_settings(0);
         WriteSettings = 0;
--- a/Discovery/Src/tMenuEditCustom.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditCustom.c	Tue Dec 14 15:36:10 2021 +0100
@@ -169,6 +169,12 @@
     	text[4] = TXT_AtemGasVorrat;
     	    	break;
 #endif
+
+#ifdef ENABLE_PSCR_MODE
+    case LCC_SimPpo2:
+    	text[4] = TXT_SimPpo2;
+    	    	break;
+#endif
     /* none */
     case LLC_Empty:
         text[4] = '-';
@@ -713,7 +719,7 @@
 uint8_t OnAction_CViewPortLayout(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
 	SSettings* pSettings = settingsGetPointer();
-	if((pSettings->viewPortMode >> 4) & 0x10 != 0)
+	if(((pSettings->viewPortMode >> 4) & 0x10) != 0)
 	{
 		pSettings->viewPortMode &= 0xEF;	/* 1110 1111 */
 	}
--- a/Discovery/Src/tMenuEditDeco.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditDeco.c	Tue Dec 14 15:36:10 2021 +0100
@@ -32,6 +32,7 @@
 #include "gfx_fonts.h"
 #include "tMenuEdit.h"
 #include "unit.h"
+#include "configuration.h"
 
 /* Private variables ---------------------------------------------------------*/
 static uint8_t lineSelected = 0;
@@ -46,11 +47,7 @@
 static void openEdit_Salinity(void);
 
 /* Announced function prototypes -----------------------------------------------*/
-
-static uint8_t OnAction_OC			(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
-static uint8_t OnAction_CC			(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
-static uint8_t OnAction_Apnea		(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
-static uint8_t OnAction_Gauge		(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+static uint8_t OnAction_setMode (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 static uint8_t OnAction_FutureTTS	(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 static uint8_t OnAction_ppO2Max	(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 static uint8_t OnAction_SafetyStop (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
@@ -66,7 +63,7 @@
 
     lineSelected = line;
 
-    if((data->dive_mode != DIVEMODE_CCR )&&  (line > 1))
+    if((!isLoopMode(data->dive_mode)) &&  (line > 1))
         line += 1;
 
     switch(line)
@@ -101,6 +98,7 @@
 #define APNEAANDGAUGE
 
     char text[32];
+    uint8_t lineOffset = 0;
     uint8_t actualDiveMode, active;
     SSettings *pSettings = settingsGetPointer();
     actualDiveMode = pSettings->dive_mode;
@@ -113,6 +111,10 @@
     text[1] = 0;
 
 
+#ifdef ENABLE_PSCR_MODE
+    lineOffset = ME_Y_LINE_STEP;
+#endif
+
     text[0] = TXT_OpenCircuit;
     if(actualDiveMode == DIVEMODE_OC)
         active = 1;
@@ -127,89 +129,81 @@
         active = 0;
     write_field_on_off(StMDECO1_CC,			 30, 500, ME_Y_LINE2,  &FontT48, text, active);
 
-    #ifdef APNEAANDGAUGE
+#ifdef ENABLE_PSCR_MODE
+    text[0] = TXT_PSClosedCircuit;
+    if(actualDiveMode == DIVEMODE_PSCR)
+        active = 1;
+    else
+        active = 0;
+    write_field_on_off(StMDECO1_PSCR,		 30, 500, ME_Y_LINE3,  &FontT48, text, active);
+#endif
+#ifdef APNEAANDGAUGE
     text[0] = TXT_Apnoe;
     if(actualDiveMode == DIVEMODE_Apnea)
         active = 1;
     else
         active = 0;
-    write_field_on_off(StMDECO1_Apnea,	 30, 500, ME_Y_LINE3,  &FontT48, text, active);
+    write_field_on_off(StMDECO1_Apnea,	 30, 500, ME_Y_LINE3 + lineOffset,  &FontT48, text, active);
 
     text[0] = TXT_Gauge;
     if(actualDiveMode == DIVEMODE_Gauge)
         active = 1;
     else
         active = 0;
-    write_field_on_off(StMDECO1_Gauge,	 30, 500, ME_Y_LINE4,  &FontT48, text, active);
-    #endif
+    write_field_on_off(StMDECO1_Gauge,	 30, 500, ME_Y_LINE4 + lineOffset,  &FontT48, text, active);
+#endif
 
-    setEvent(StMDECO1_OC, 			(uint32_t)OnAction_OC);
-    setEvent(StMDECO1_CC, 			(uint32_t)OnAction_CC);
-    #ifdef APNEAANDGAUGE
-    setEvent(StMDECO1_Apnea, 		(uint32_t)OnAction_Apnea);
-    setEvent(StMDECO1_Gauge, 		(uint32_t)OnAction_Gauge);
-    #endif
+    setEvent(StMDECO1_OC, 			(uint32_t)OnAction_setMode);
+    setEvent(StMDECO1_CC, 			(uint32_t)OnAction_setMode);
+#ifdef ENABLE_PSCR_MODE
+    setEvent(StMDECO1_PSCR,			(uint32_t)OnAction_setMode);
+#endif
+
+#ifdef APNEAANDGAUGE
+    setEvent(StMDECO1_Apnea, 		(uint32_t)OnAction_setMode);
+    setEvent(StMDECO1_Gauge, 		(uint32_t)OnAction_setMode);
+#endif
 
     write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext);
 }
 
-static uint8_t OnAction_OC						(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+
+static uint8_t OnAction_setMode (uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action) //(uint32_t newMode)
 {
-    SSettings *pSettings = settingsGetPointer();
-    if(pSettings->dive_mode == DIVEMODE_OC)
-        return EXIT_TO_MENU;
-    pSettings->dive_mode = DIVEMODE_OC;
-    setActualGasFirst(&stateRealGetPointerWrite()->lifeData);
-    tMenuEdit_set_on_off(editId, 1);
-    tMenuEdit_set_on_off(StMDECO1_CC, 0);
-    tMenuEdit_set_on_off(StMDECO1_Apnea, 0);
-    tMenuEdit_set_on_off(StMDECO1_Gauge, 0);
-    return UPDATE_DIVESETTINGS;
-}
+	uint32_t modeArray[] = {StMDECO1_OC, StMDECO1_CC, StMDECO1_Gauge, StMDECO1_Apnea  /* definition needs to follow order of DIVEMODE (settings.h) */
+#ifdef ENABLE_PSCR_MODE
+			, StMDECO1_PSCR
+#endif
+	};
+
+	uint8_t index = 0;
+	SSettings *pSettings = settingsGetPointer();
+	uint8_t retVal = EXIT_TO_MENU;
+	uint8_t lastMode = pSettings->dive_mode;
 
 
-static uint8_t OnAction_CC						(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
-{
-    SSettings *pSettings = settingsGetPointer();
-    if(pSettings->dive_mode == DIVEMODE_CCR)
-        return EXIT_TO_MENU;
-    pSettings->dive_mode = DIVEMODE_CCR;
-    setActualGasFirst(&stateRealGetPointerWrite()->lifeData);
-    tMenuEdit_set_on_off(editId, 1);
-    tMenuEdit_set_on_off(StMDECO1_OC, 0);
-    tMenuEdit_set_on_off(StMDECO1_Apnea, 0);
-    tMenuEdit_set_on_off(StMDECO1_Gauge, 0);
-    return UPDATE_DIVESETTINGS;
-}
-
-
-static uint8_t OnAction_Apnea				(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
-{
-    SSettings *pSettings = settingsGetPointer();
-    if(pSettings->dive_mode == DIVEMODE_Apnea)
-        return EXIT_TO_MENU;
-    pSettings->dive_mode = DIVEMODE_Apnea;
-    setActualGasFirst(&stateRealGetPointerWrite()->lifeData);
-    tMenuEdit_set_on_off(editId, 1);
-    tMenuEdit_set_on_off(StMDECO1_CC, 0);
-    tMenuEdit_set_on_off(StMDECO1_OC, 0);
-    tMenuEdit_set_on_off(StMDECO1_Gauge, 0);
-    return UPDATE_DIVESETTINGS;
-}
-
-
-static uint8_t OnAction_Gauge				(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
-{
-    SSettings *pSettings = settingsGetPointer();
-    if(pSettings->dive_mode == DIVEMODE_Gauge)
-        return EXIT_TO_MENU;
-    pSettings->dive_mode = DIVEMODE_Gauge;
-    setActualGasFirst(&stateRealGetPointerWrite()->lifeData);
-    tMenuEdit_set_on_off(editId, 1);
-    tMenuEdit_set_on_off(StMDECO1_CC, 0);
-    tMenuEdit_set_on_off(StMDECO1_Apnea, 0);
-    tMenuEdit_set_on_off(StMDECO1_OC, 0);
-    return UPDATE_DIVESETTINGS;
+	setActualGasFirst(&stateRealGetPointerWrite()->lifeData);
+	while(index < sizeof(modeArray) / 4)	/* calculate number of items out of array size (bytes) */
+	{
+		if(editId == modeArray[index])
+		{
+			if(pSettings->dive_mode != index)
+			{
+				tMenuEdit_set_on_off(modeArray[index], 1);
+				pSettings->dive_mode = index;
+				retVal = UPDATE_DIVESETTINGS;
+			}
+		}
+		else
+		{
+			if(lastMode == index)		/* reset state of previous mode selection */
+			{
+				tMenuEdit_set_on_off(modeArray[index], 0);
+			}
+		}
+		index++;
+	}
+	return retVal;
 }
 
 
--- a/Discovery/Src/tMenuEditGasOC.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditGasOC.c	Tue Dec 14 15:36:10 2021 +0100
@@ -92,7 +92,7 @@
     {
 		if(line == 6)
 		{
-			if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1))
+			if(isLoopMode(settingsGetPointer()->dive_mode) || (stateUsed->diveSettings.ccrOption == 1))
 			{
 				selectPage(StMOG);
 			}
@@ -122,7 +122,7 @@
     {
 		if(line == 6)
 		{
-			if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1))
+			if(isLoopMode(settingsGetPointer()->dive_mode) || (stateUsed->diveSettings.ccrOption == 1))
 			{
 				selectPage(StMCG);
 			}
@@ -367,7 +367,7 @@
 
 void tMEGas_check_switch_to_bailout(void)
 {
-    if(stateUsed->diveSettings.diveMode == DIVEMODE_CCR)
+    if(isLoopMode(stateUsed->diveSettings.diveMode))
     {
     	stateUsedWrite->diveSettings.diveMode = DIVEMODE_OC;
         block_diluent_page();
--- a/Discovery/Src/tMenuEditPlanner.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditPlanner.c	Tue Dec 14 15:36:10 2021 +0100
@@ -689,7 +689,7 @@
                     textpointer += snprintf(&text[textpointer],20,"GF %u/%u", stateUsed->diveSettings.gf_low, stateUsed->diveSettings.gf_high);
                 break;
             case 1:
-                if(settingsGetPointer()->dive_mode == DIVEMODE_CCR)
+                if(isLoopMode(settingsGetPointer()->dive_mode))
                     text[textpointer++] = 'C';
                 else
                     text[textpointer++] = 'O';
--- a/Discovery/Src/tMenuEditSetpoint.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditSetpoint.c	Tue Dec 14 15:36:10 2021 +0100
@@ -58,6 +58,8 @@
 void openEdit_Setpoint(uint8_t line)
 {
     uint8_t useSensorSubMenu = 0;
+    char text[20];
+    uint8_t sensorActive[3];
 
     /* dive mode */
     if(actual_menu_content != MENU_SURFACE)
@@ -66,7 +68,7 @@
         setpointCbar = 100;
 
         // actualGasID
-        if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_CCR)
+        if(!isLoopMode(stateUsedWrite->diveSettings.diveMode))
         {
             actualGasID = stateUsedWrite->lifeData.lastDiluent_GasIdInSettings;
             if((actualGasID <= NUM_OFFSET_DILUENT) || (actualGasID > NUM_GASES + NUM_OFFSET_DILUENT))
@@ -76,7 +78,7 @@
             actualGasID = stateUsedWrite->lifeData.actualGas.GasIdInSettings;
 
         // setpointCbar, CCR_Mode and sensor menu
-        if(line < 6)
+        if((line < 6) && (stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR))		/* setpoints inactive in PSCR mode */
         {
             setpointCbar = stateUsedWrite->diveSettings.setpoint[line].setpoint_cbar;
             stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_FixedSetpoint;
@@ -96,25 +98,32 @@
                 stateUsedWrite->diveSettings.setpoint[line].note.ub.first = 1;
             }
         }
-        else
+        else	/* menu item not pointing to setpoint selection => use sensor or ppo2 simulation */
         {
-            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;
-            }
+        	if((stateUsedWrite->diveSettings.diveMode == DIVEMODE_PSCR) && (line == 2))
+			{
+        		stateUsedWrite->diveSettings.CCR_Mode = CCRMODE_Simulation;
+			}
+			else	/* => use sensor */
+			{
+				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;
+				}
+			}
         }
 
         setActualGas_DM(&stateUsedWrite->lifeData,actualGasID,setpointCbar);
 
-        if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_CCR)
+        if(!isLoopMode(stateUsedWrite->diveSettings.diveMode))
         {
-        	stateUsedWrite->diveSettings.diveMode = DIVEMODE_CCR;
+        	stateUsedWrite->diveSettings.diveMode = settingsGetPointer()->dive_mode;
             unblock_diluent_page();
         }
 
@@ -129,9 +138,6 @@
             set_globalState_Menu_Line(line);
             resetMenuEdit(CLUT_MenuPageGasSP);
 
-            char text[20];
-            uint8_t sensorActive[3];
-
             text[0] = '\001';
             text[1] = TXT_o2Sensors;
             text[2] = 0;
@@ -145,6 +151,7 @@
             else
             {
             	snprintf (text,20,"Sensor 1    (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[0] );
+            	sensorActive[0] = 1;
             }
             write_label_var(  96, 600, ME_Y_LINE1, &FontT48, text);
             if(stateUsedWrite->diveSettings.ppo2sensors_deactivated & 2)
@@ -155,6 +162,7 @@
             else
             {
                	snprintf (text,20,"Sensor 2    (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[1] );
+               	sensorActive[1] = 1;
             }
             write_label_var(  96, 600, ME_Y_LINE2, &FontT48, text);
             if(stateUsedWrite->diveSettings.ppo2sensors_deactivated & 4)
@@ -165,13 +173,10 @@
             else
             {
               	snprintf (text,20,"Sensor 3    (%01.2f)", stateUsed->lifeData.ppO2Sensor_bar[2] );
+              	sensorActive[2] = 1;
             }
             write_label_var(  96, 600, ME_Y_LINE3, &FontT48, text);
 
-            sensorActive[0] = 1;
-            sensorActive[1] = 1;
-            sensorActive[2] = 1;
-
             write_field_on_off(StMSP_Sensor1,	 30, 95, ME_Y_LINE1,  &FontT48, "", sensorActive[0]);
             write_field_on_off(StMSP_Sensor2,	 30, 95, ME_Y_LINE2,  &FontT48, "", sensorActive[1]);
             write_field_on_off(StMSP_Sensor3,	 30, 95, ME_Y_LINE3,  &FontT48, "", sensorActive[2]);
@@ -329,23 +334,26 @@
     uint8_t spId;
     uint8_t depth;
 
-    spId = actualBetterSetpointId();
-
-    depth = stateUsedWrite->diveSettings.setpoint[spId].depth_meter;
-
-    // BetterSetpoint warning only once -> clear active
-    for(int i=0; i<=NUM_GASES; i++)
+    if(stateUsedWrite->diveSettings.diveMode != DIVEMODE_PSCR)		/* no setpoints in PSCR mode */
     {
-    	stateUsedWrite->diveSettings.setpoint[i].note.ub.first = 0;
-        if(stateUsedWrite->diveSettings.setpoint[i].depth_meter <= depth)
-        	stateUsedWrite->diveSettings.setpoint[i].note.ub.active = 0;
-    }
+		spId = actualBetterSetpointId();
+
+		depth = stateUsedWrite->diveSettings.setpoint[spId].depth_meter;
 
-    // new setpoint
-    stateUsedWrite->diveSettings.setpoint[spId].note.ub.first = 1;
+		// 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;
+		}
 
-    // change in lifeData
-    setActualGas_DM(&stateUsedWrite->lifeData, stateUsedWrite->lifeData.actualGas.GasIdInSettings, stateUsedWrite->diveSettings.setpoint[spId].setpoint_cbar);
+		// new setpoint
+		stateUsedWrite->diveSettings.setpoint[spId].note.ub.first = 1;
+
+		// change in lifeData
+		setActualGas_DM(&stateUsedWrite->lifeData, stateUsedWrite->lifeData.actualGas.GasIdInSettings, stateUsedWrite->diveSettings.setpoint[spId].setpoint_cbar);
+    }
 }
 
 static uint8_t OnAction_SP_DM_Sensor1	(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
--- a/Discovery/Src/tMenuEditSystem.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditSystem.c	Tue Dec 14 15:36:10 2021 +0100
@@ -34,6 +34,7 @@
 #include "gfx_fonts.h"
 #include "ostc.h"
 #include "settings.h" // for getLicence()
+#include "tComm.h"
 #include "tHome.h"  // for enum CUSTOMVIEWS and init_t7_compass()
 #include "tMenu.h"
 #include "tMenuEdit.h"
@@ -86,6 +87,7 @@
 uint8_t OnAction_Nothing			(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_LogbookOffset(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_SetFactoryDefaults(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+uint8_t OnAction_ResetBluetooth(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_SetBatteryCharge(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 #ifdef ENABLE_ANALYSE_SAMPLES
 uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
@@ -1073,11 +1075,16 @@
         text[2] = 0;
         write_field_button(StMSYS5_SetFactoryBC,			30, 800, ME_Y_LINE2,  &FontT48, text);
 
+        text[0] = TXT_2BYTE;
+        text[1] = TXT2BYTE_ResetBluetooth;
+        text[2] = 0;
+        write_field_button(StMSYS5_ResetBluetooth,			30, 800, ME_Y_LINE3,  &FontT48, text);
+
 #ifdef ENABLE_ANALYSE_SAMPLES
         text[0] = TXT_2BYTE;
         text[1] = TXT2BYTE_SetSampleIndex;
         text[2] = 0;
-        write_field_button(StMSYS5_SetSampleIndx,			30, 800, ME_Y_LINE3,  &FontT48, text);
+        write_field_button(StMSYS5_SetSampleIndx,			30, 800, ME_Y_LINE4,  &FontT48, text);
 #endif
 
 
@@ -1095,6 +1102,7 @@
 
             setEvent(StMSYS5_Exit, (uint32_t)OnAction_Exit);
             setEvent(StMSYS5_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults);
+            setEvent(StMSYS5_ResetBluetooth, (uint32_t)OnAction_ResetBluetooth);
 #ifdef ENABLE_ANALYSE_SAMPLES
             setEvent(StMSYS5_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx);
 #endif
@@ -1104,6 +1112,7 @@
         {
             setEvent(StMSYS5_Exit, (uint32_t)OnAction_Exit);
             setEvent(StMSYS5_SetFactoryBC, (uint32_t)OnAction_SetFactoryDefaults);
+            setEvent(StMSYS5_ResetBluetooth, (uint32_t)OnAction_ResetBluetooth);
 #ifdef ENABLE_ANALYSE_SAMPLES
             setEvent(StMSYS5_SetSampleIndx, (uint32_t)OnAction_RecoverSampleIdx);
 #endif
@@ -1224,6 +1233,13 @@
     return EXIT_TO_MENU;
 }
 
+uint8_t OnAction_ResetBluetooth(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+    tComm_Set_Bluetooth_Name(1);
+
+    return EXIT_TO_MENU;
+}
+
 #ifdef ENABLE_ANALYSE_SAMPLES
 uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
--- a/Discovery/Src/tMenuEditXtra.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuEditXtra.c	Tue Dec 14 15:36:10 2021 +0100
@@ -35,6 +35,7 @@
 #include "tMenuEdit.h"
 #include "data_exchange_main.h"
 #include "motion.h"
+#include "configuration.h"
 
 
 /* Private function prototypes -----------------------------------------------*/
@@ -47,10 +48,26 @@
 static void openEdit_ScrubberTimer(uint8_t line);
 static void openEdit_ScrubberReset(void);
 static void openEdit_ScrubberTimerMode(void);
+#ifdef ENABLE_PSCR_MODE
+static void openEdit_PSCRO2Drop(uint8_t line);
+static void openEdit_PSCRLungRatio(uint8_t line);
+#endif
+#ifdef ENABLE_CO2_SUPPORT
+static void openEdit_CO2Sensor(void);
+#endif
 
 /* Announced function prototypes -----------------------------------------------*/
 uint8_t OnAction_CompassHeading	(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 static uint8_t OnAction_ScrubberTimer(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#ifdef ENABLE_PSCR_MODE
+static uint8_t OnAction_PSCRO2Drop(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+static uint8_t OnAction_PSCRLungRation(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#endif
+
+#ifdef ENABLE_CO2_SUPPORT
+static uint8_t OnAction_CO2OnOff(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+static uint8_t OnAction_CO2Calib(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#endif
 
 /* Exported functions --------------------------------------------------------*/
 
@@ -91,6 +108,11 @@
     }
     else /* surface mode */
     {
+    	if((settingsGetPointer()->dive_mode != DIVEMODE_PSCR) && (line > 3))		/* PSCR items are only optional */
+		{
+			line = 6;
+		}
+
 		switch(line)
 		{
 			case 1:	openEdit_ScrubberTimer(line);
@@ -99,6 +121,16 @@
 				break;
 			case 3:	openEdit_ScrubberTimerMode();
 				break;
+#ifdef ENABLE_PSCR_MODE
+			case 4: openEdit_PSCRO2Drop(line);
+				break;
+			case 5: openEdit_PSCRLungRatio(line);
+							break;
+#endif
+#ifdef ENABLE_CO2_SUPPORT
+			case 6: openEdit_CO2Sensor();
+				break;
+#endif
 			default:
 				break;
 		}
@@ -191,6 +223,103 @@
      exitMenuEdit_to_Menu_with_Menu_Update();
 }
 
+#ifdef ENABLE_PSCR_MODE
+static void openEdit_PSCRO2Drop(uint8_t line)
+{
+    uint8_t localO2Drop;
+    uint16_t y_line;
+
+    char text[32];
+    SSettings *pSettings = settingsGetPointer();
+    localO2Drop = pSettings->pscr_o2_drop;
+
+    y_line = ME_Y_LINE_BASE + (line * ME_Y_LINE_STEP);
+
+    text[0] = '\001';
+    text[1] = TXT_PSCRO2Drop;
+    text[2] = 0;
+    write_topline(text);
+
+    text[0] = '\002';
+    text[1] = '\016';
+    text[2] = '\016';
+    text[3] = '%';
+    text[4] = 0;
+    write_label_fix(   20, 800, y_line, &FontT48, TXT_PSCRO2Drop);
+    write_label_var(  435, 780, y_line, &FontT48, text);
+    write_field_udigit(StMXTRA_PSCR_O2_Drop, 710, 779, y_line, &FontT48, "##", (uint32_t)localO2Drop, 0, 0, 0);
+
+    write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus);
+
+    setEvent(StMXTRA_PSCR_O2_Drop,	(uint32_t)OnAction_PSCRO2Drop);
+    startEdit();
+}
+
+static void openEdit_PSCRLungRatio(uint8_t line)
+{
+    uint8_t localLungRatio;
+    uint16_t y_line;
+
+    char text[32];
+    SSettings *pSettings = settingsGetPointer();
+    localLungRatio = pSettings->pscr_lung_ratio;
+
+    y_line = ME_Y_LINE_BASE + (line * ME_Y_LINE_STEP);
+
+    text[0] = '\001';
+    text[1] = TXT_PSCRO2Drop;
+    text[2] = 0;
+    write_topline(text);
+
+    text[0] = '\002';
+    text[1] = '1';
+    text[2] = '/';
+    text[3] = 0;
+
+    write_label_fix(   20, 800, y_line, &FontT48, TXT_PSCRLungRatio);
+    write_label_var(  435, 710, y_line, &FontT48, text);
+    write_field_udigit(StMXTRA_PSCR_LUNG_RATIO, 710, 779, y_line, &FontT48, "##", (uint32_t)localLungRatio, 0, 0, 0);
+
+    write_buttonTextline(TXT2BYTE_ButtonMinus,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonPlus);
+
+    setEvent(StMXTRA_PSCR_LUNG_RATIO,	(uint32_t)OnAction_PSCRLungRation);
+    startEdit();
+}
+#endif
+
+#ifdef ENABLE_CO2_SUPPORT
+static void openEdit_CO2Sensor()
+{
+    char text[32];
+    snprintf(text,32,"\001%c",TXT_CO2Sensor);
+    write_topline(text);
+
+    refresh_CO2Data();
+    if(settingsGetPointer()->co2_sensor_active)
+    {
+    	text[0] = '\005';
+    }
+    else
+    {
+        text[0] = '\006';
+    }
+    text[0] = TXT_CO2Sensor;
+    text[1] = 0;
+
+    write_field_on_off(StMXTRA_CO2_Sensor,	 30, 95, ME_Y_LINE3,  &FontT48, text, settingsGetPointer()->co2_sensor_active);
+
+   	text[0] = TXT_2BYTE;
+    text[1] = TXT2BYTE_O2Calib;
+    text[2] = 0;
+    write_field_button(StMXTRA_CO2_Sensor_Calib,30, 800, ME_Y_LINE4,  &FontT48, text);
+
+    setEvent(StMXTRA_CO2_Sensor,	(uint32_t)OnAction_CO2OnOff);
+    setEvent(StMXTRA_CO2_Sensor_Calib,	(uint32_t)OnAction_CO2Calib);
+
+    write_buttonTextline(TXT2BYTE_ButtonBack,TXT2BYTE_ButtonEnter,TXT2BYTE_ButtonNext);
+}
+#endif
+
 void refresh_CompassHeading(void)
 {
     uint16_t heading;
@@ -209,6 +338,23 @@
     tMenuEdit_refresh_field(StMXTRA_CompassHeading);
 }
 
+void refresh_CO2Data(void)
+{
+    char text[32];
+
+    snprintf(text,32,"\001%c",TXT_CO2Sensor);
+    write_topline(text);
+
+    snprintf(text,32,"CO2: %d ppm",stateUsed->lifeData.CO2_data.CO2_ppm);
+    write_label_var(   30, 800, ME_Y_LINE1, &FontT48, text);
+
+    snprintf(text,32,"Signal: %d",stateUsed->lifeData.CO2_data.signalStrength);
+    write_label_var(   30, 800, ME_Y_LINE2, &FontT48, text);
+
+    tMenuEdit_refresh_field(StMXTRA_CO2_Sensor);
+    tMenuEdit_refresh_field(StMXTRA_CO2_Sensor_Calib);
+}
+
 void openEdit_CompassHeading(void)
 {
 
@@ -267,4 +413,107 @@
     }
     return digitContentNew;
 }
+#ifdef ENABLE_PSCR_MODE
+static uint8_t OnAction_PSCRO2Drop(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+    SSettings *pSettings;
+    uint8_t digitContentNew = EXIT_TO_MENU;
+    uint32_t newO2Drop;
 
+    if(action == ACTION_BUTTON_ENTER)
+    {
+        return digitContent;
+    }
+    if(action == ACTION_BUTTON_ENTER_FINAL)
+    {
+        evaluateNewString(editId, &newO2Drop, 0, 0, 0);
+
+        if(newO2Drop > PSCR_MAX_O2_DROP)
+        	newO2Drop = PSCR_MAX_O2_DROP;
+
+        pSettings = settingsGetPointer();
+        pSettings->pscr_o2_drop = newO2Drop;
+
+        tMenuEdit_newInput(editId, newO2Drop, 0, 0, 0);
+        digitContentNew = UPDATE_AND_EXIT_TO_MENU;
+    }
+    if(action == ACTION_BUTTON_NEXT)
+    {
+        digitContentNew = digitContent + 1;
+        if(digitContentNew > '9')
+            digitContentNew = '0';
+    }
+    if(action == ACTION_BUTTON_BACK)
+    {
+        digitContentNew = digitContent - 1;
+        if(digitContentNew < '0')
+            digitContentNew = '9';
+    }
+    return digitContentNew;
+}
+
+static uint8_t OnAction_PSCRLungRation(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+    SSettings *pSettings;
+    uint8_t digitContentNew = EXIT_TO_MENU;
+    uint32_t newLungRatio;
+
+    if(action == ACTION_BUTTON_ENTER)
+    {
+        return digitContent;
+    }
+    if(action == ACTION_BUTTON_ENTER_FINAL)
+    {
+        evaluateNewString(editId, &newLungRatio, 0, 0, 0);
+
+        if(newLungRatio > PSCR_MAX_LUNG_RATIO)
+        	newLungRatio = PSCR_MAX_LUNG_RATIO;
+
+        if(newLungRatio < PSCR_MIN_LUNG_RATIO)
+        	newLungRatio = PSCR_MIN_LUNG_RATIO;
+
+        pSettings = settingsGetPointer();
+        pSettings->pscr_lung_ratio = newLungRatio;
+
+        tMenuEdit_newInput(editId, newLungRatio, 0, 0, 0);
+        digitContentNew = UPDATE_AND_EXIT_TO_MENU;
+    }
+    if(action == ACTION_BUTTON_NEXT)
+    {
+        digitContentNew = digitContent + 1;
+        if(digitContentNew > '9')
+            digitContentNew = '0';
+    }
+    if(action == ACTION_BUTTON_BACK)
+    {
+        digitContentNew = digitContent - 1;
+        if(digitContentNew < '0')
+            digitContentNew = '9';
+    }
+    return digitContentNew;
+}
+#endif
+
+#ifdef ENABLE_CO2_SUPPORT
+static uint8_t OnAction_CO2OnOff(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+	SSettings *pSettings = settingsGetPointer();
+	if(pSettings->co2_sensor_active)
+	{
+		pSettings->co2_sensor_active = 0;
+		tMenuEdit_set_on_off(StMXTRA_CO2_Sensor,0);
+	}
+	else
+	{
+		pSettings->co2_sensor_active = 1;
+		tMenuEdit_set_on_off(StMXTRA_CO2_Sensor,1);
+	}
+	return UPDATE_DIVESETTINGS;
+}
+
+static uint8_t OnAction_CO2Calib(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
+{
+	DataEX_setExtInterface_Cmd(EXT_INTERFACE_CO2_CALIB);
+	return UPDATE_DIVESETTINGS;
+}
+#endif
--- a/Discovery/Src/tMenuGas.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuGas.c	Tue Dec 14 15:36:10 2021 +0100
@@ -55,7 +55,7 @@
     }
     else
     {
-        if (stateUsed->diveSettings.diveMode == DIVEMODE_CCR)
+        if (isLoopMode(stateUsed->diveSettings.diveMode))
             gas_mode = OCGAS_BAILOUT_INACTIVE;
         else
             gas_mode = OCGAS_BAILOUT_ACTIVE;
@@ -328,7 +328,7 @@
 			text[textPointer++] = 0;
     	}
     	else	/* switch to bailout selection in surface mode */
-    	if((settingsGetPointer()->dive_mode == DIVEMODE_CCR) || (stateUsed->diveSettings.ccrOption == 1))
+    	if((isLoopMode(settingsGetPointer()->dive_mode)) || (stateUsed->diveSettings.ccrOption == 1))
     	{
 			text[textPointer++] = '\024';
 			if(gasMode == CCGAS_STANDARD)
--- a/Discovery/Src/tMenuSetpoint.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuSetpoint.c	Tue Dec 14 15:36:10 2021 +0100
@@ -53,76 +53,79 @@
     *tab = 130;
     *subtext = 0;
 
-    for(int spId=1;spId<=NUM_GASES;spId++)
+    if((actual_menu_content == MENU_SURFACE) || (stateUsed->diveSettings.diveMode != DIVEMODE_PSCR))	/* do not show setpoints in PSCR mode */
     {
-        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;
+		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;
 
-            strcpy(&text[textPointer],"\020"); // if(active) always active
-            textPointer += 1;
+				strcpy(&text[textPointer],"\020"); // if(active) always active
+				textPointer += 1;
 
-            sp_high = setpoint_cbar / 100;
+				sp_high = setpoint_cbar / 100;
 
-            text[textPointer++] = 'S';
-            text[textPointer++] = 'P';
-            text[textPointer++] = '0' + spId;
-            text[textPointer++] = '\t';
+				text[textPointer++] = 'S';
+				text[textPointer++] = 'P';
+				text[textPointer++] = '0' + spId;
+				text[textPointer++] = '\t';
 
-            if((first == 0) || (actual_menu_content != MENU_SURFACE))
-                strcpy(&text[textPointer++],"\177");
+				if((first == 0) || (actual_menu_content != MENU_SURFACE))
+					strcpy(&text[textPointer++],"\177");
 
-            char color = '\031';
-            if(depthUp)
-                color = '\020';
+				char color = '\031';
+				if(depthUp)
+					color = '\020';
 
-            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], 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()
+				);
+			}
+		}
     }
     if((actual_menu_content != MENU_SURFACE) /*&& (line == 0)*/)
     {
@@ -131,6 +134,12 @@
         text[textPointer++] = TXT2BYTE_UseSensor;
         text[textPointer++] = '\n';
         text[textPointer++] = '\r';
+
+
+        if(stateUsed->diveSettings.diveMode == DIVEMODE_PSCR)
+        {
+        	textPointer += snprintf(&text[textPointer], 20,"\020%c", TXT_SimPpo2);
+        }
         text[textPointer++] = 0;
     }
     else
--- a/Discovery/Src/tMenuXtra.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/tMenuXtra.c	Tue Dec 14 15:36:10 2021 +0100
@@ -47,6 +47,8 @@
     *tab = 500;
     *subtext = 0;
 
+    SSettings *pSettings = settingsGetPointer();
+
     /* DIVE MODE */
     if(actual_menu_content != MENU_SURFACE)
     {
@@ -133,7 +135,7 @@
                 "\017"
                 ,TXT_ScrubTime
 				,TXT_Maximum
-                ,settingsGetPointer()->scrubTimerMax
+                ,pSettings->scrubTimerMax
                 ,TXT_Minutes
             );
         }
@@ -144,14 +146,14 @@
             textPointer += snprintf(&text[textPointer], 60,\
                         "%c\002%03u\016\016 %c\017"
                         ,TXT_ScrubTimeReset
-                        ,settingsGetPointer()->scrubTimerCur
+                        ,pSettings->scrubTimerCur
                         ,TXT_Minutes);
         }
         strcpy(&text[textPointer],"\n\r");
         textPointer += 2;
         if((line == 0) || (line == 3))
         {
-        	switch(settingsGetPointer()->scrubTimerMode)
+        	switch(pSettings->scrubTimerMode)
         	{
         		case SCRUB_TIMER_OFF:
         		default: 	textPointer += snprintf(&text[textPointer], 60,"%c\002%c%c",TXT_ScrubTimeMode, TXT_2BYTE, TXT2BYTE_MoCtrlNone );
@@ -165,6 +167,35 @@
         strcpy(&text[textPointer],"\n\r");
         textPointer += 2;
 
+#ifdef ENABLE_PSCR_MODE
+        if(pSettings->dive_mode == DIVEMODE_PSCR)
+        {
+            if((line == 0) || (line == 4))
+             {
+                 textPointer += snprintf(&text[textPointer], 60,\
+                             "%c\002%02u\016\016%%\017"
+                             ,TXT_PSCRO2Drop
+                             ,pSettings->pscr_o2_drop);
+             }
+             strcpy(&text[textPointer],"\n\r");
+             textPointer += 2;
+             if((line == 0) || (line == 5))
+              {
+                  textPointer += snprintf(&text[textPointer], 60,\
+                              "%c\002 1/%02u"
+                              ,TXT_PSCRLungRatio
+                              ,pSettings->pscr_lung_ratio);
+              }
+              strcpy(&text[textPointer],"\n\r");
+              textPointer += 2;
+        }
+#endif
+#ifdef ENABLE_CO2_SUPPORT
+        if((line == 0) || (line == 6))
+         {
+             textPointer += snprintf(&text[textPointer], 60, "%c", TXT_CO2Sensor);
+         }
+#endif
     }
     return StMXTRA;
 }
--- a/Discovery/Src/text_multilanguage.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Discovery/Src/text_multilanguage.c	Tue Dec 14 15:36:10 2021 +0100
@@ -453,6 +453,12 @@
 static uint8_t text_IT_ClosedCircuit[] = "Ciurcuito chiuso";
 static uint8_t text_ES_ClosedCircuit[] = "Circuito cerrado";
 
+static uint8_t text_EN_PSClosedCircuit[] = "PSC circuit";
+static uint8_t text_DE_PSClosedCircuit[] = "PSC Kreislauf";
+static uint8_t text_FR_PSClosedCircuit[] = "PSC circuit";
+static uint8_t text_IT_PSClosedCircuit[] = "PSC circuit";
+static uint8_t text_ES_PSClosedCircuit[] = "PSC circuit";
+
 static uint8_t text_EN_Time[] = "Time";
 static uint8_t text_DE_Time[] = "Uhrzeit";
 static uint8_t text_FR_Time[] = "Heure";
@@ -632,6 +638,13 @@
 static uint8_t text_ES_SetFactoryDefaults[] = "Restablecer ajustes de fábrica";
 
 // Menu SYS2 sub
+static uint8_t text_EN_ResetBluetooth[] = "Reset bluetooth interface";
+static uint8_t text_DE_ResetBluetooth[] = "Bluetooth interface zurüchsetzen";
+static uint8_t text_FR_ResetBluetooth[] = "";
+static uint8_t text_IT_ResetBluetooth[] = "";
+static uint8_t text_ES_ResetBluetooth[] = "";
+
+// Menu SYS2 sub
 static uint8_t text_EN_SetSampleIndex[] = "Analyse log memory";
 static uint8_t text_DE_SetSampleIndex[] = "Prüfe Logbuchspeicher";
 static uint8_t text_FR_SetSampleIndex[] = "Maintain log memory";
@@ -1704,6 +1717,37 @@
 static uint8_t text_IT_Percent[] = "Percent";
 static uint8_t text_ES_Percent[] = "Percent";
 
+static uint8_t text_EN_PSCRO2Drop[] = "PSCR O2 drop";
+static uint8_t text_DE_PSCRO2Drop[] = "PSCR O2 Abfall";
+static uint8_t text_FR_PSCRO2Drop[] = "PSCR O2 drop";
+static uint8_t text_IT_PSCRO2Drop[] = "PSCR O2 drop";
+static uint8_t text_ES_PSCRO2Drop[] = "PSCR O2 drop";
+
+static uint8_t text_EN_LungRatio[] = "PSCR lung ratio";
+static uint8_t text_DE_LungRatio[] = "PSCR Lungen Faktor";
+static uint8_t text_FR_LungRatio[] = "PSCR lung ratio";
+static uint8_t text_IT_LungRatio[] = "PSCR lung ratio";
+static uint8_t text_ES_LungRatio[] = "PSCR lung ratio";
+
+static uint8_t text_EN_CheckSettings[] = "Check settings";
+static uint8_t text_DE_CheckSettings[] = "Prüfe Optionen";
+static uint8_t text_FR_CheckSettings[] = "Check settings";
+static uint8_t text_IT_CheckSettings[] = "Check settings";
+static uint8_t text_ES_CheckSettings[] = "Check settings";
+
+static uint8_t text_EN_SimPpo2[] = "Sim ppO2";
+static uint8_t text_DE_SimPpo2[] = "Sim ppO2";
+static uint8_t text_FR_SimPpo2[] = "Sim ppO2";
+static uint8_t text_IT_SimPpo2[] = "Sim ppO2";
+static uint8_t text_ES_SimPpo2[] = "Sim ppO2";
+
+static uint8_t text_EN_CO2Sensor[] = "CO2 Sensor";
+static uint8_t text_DE_CO2Sensor[] = "CO2 Sensor";
+static uint8_t text_FR_CO2Sensor[] = "CO2 Sensor";
+static uint8_t text_IT_CO2Sensor[] = "CO2 Sensor";
+static uint8_t text_ES_CO2Sensor[] = "CO2 Sensor";
+
+
 /* Lookup Table -------------------------------------------------------------*/
 
 const tText text_array[] =
@@ -1770,7 +1814,8 @@
     {(uint8_t)TXT_ClosedCircuit,	{text_EN_ClosedCircuit, text_DE_ClosedCircuit, text_FR_ClosedCircuit, text_IT_ClosedCircuit, text_ES_ClosedCircuit}},
     {(uint8_t)TXT_Apnoe,	 		{text_EN_Apnoe, text_DE_Apnoe, text_FR_Apnoe, text_IT_Apnoe, text_ES_Apnoe}},
     {(uint8_t)TXT_Gauge,	 		{text_EN_Gauge, text_DE_Gauge, text_FR_Gauge, text_IT_Gauge, text_ES_Gauge}},
-    {(uint8_t)TXT_Sensor,			{text_EN_Sensor, text_DE_Sensor, text_FR_Sensor, text_IT_Sensor, text_ES_Sensor}},
+    {(uint8_t)TXT_PSClosedCircuit,  {text_EN_PSClosedCircuit, text_DE_PSClosedCircuit, text_FR_PSClosedCircuit, text_IT_PSClosedCircuit, text_ES_PSClosedCircuit}},
+	{(uint8_t)TXT_Sensor,			{text_EN_Sensor, text_DE_Sensor, text_FR_Sensor, text_IT_Sensor, text_ES_Sensor}},
     {(uint8_t)TXT_FixedSP,			{text_EN_FixedSP, text_DE_FixedSP, text_FR_FixedSP, text_IT_FixedSP, text_ES_FixedSP}},
     {(uint8_t)TXT_Decoparameters,	{text_EN_Decoparameters, text_DE_Decoparameters, text_FR_Decoparameters, text_IT_Decoparameters, text_ES_Decoparameters}},
     {(uint8_t)TXT_LastDecostop,		{text_EN_LastDecostop, text_DE_LastDecostop, text_FR_LastDecostop, text_IT_LastDecostop, text_ES_LastDecostop}},
@@ -1787,7 +1832,10 @@
 	{(uint8_t)TXT_ScrubTimeReset,	{text_EN_ScrubTimeReset, text_DE_ScrubTimeReset, text_FR_ScrubTimeReset, text_IT_ScrubTimeReset, text_ES_ScrubTimeReset}},
 	{(uint8_t)TXT_ScrubTimeMode,	{text_EN_ScrubTimeMode, text_DE_ScrubTimeMode, text_FR_ScrubTimeMode, text_IT_ScrubTimeMode, text_ES_ScrubTimeMode}},
 	{(uint8_t)TXT_Percent,	    	{text_EN_Percent, text_DE_Percent, text_FR_Percent, text_IT_Percent, text_ES_Percent}},
-
+	{(uint8_t)TXT_PSCRO2Drop,	    {text_EN_PSCRO2Drop, text_DE_PSCRO2Drop, text_FR_PSCRO2Drop, text_IT_PSCRO2Drop, text_ES_PSCRO2Drop}},
+	{(uint8_t)TXT_PSCRLungRatio,	{text_EN_LungRatio, text_DE_LungRatio, text_FR_LungRatio, text_IT_LungRatio, text_ES_LungRatio}},
+	{(uint8_t)TXT_SimPpo2,			{text_EN_SimPpo2, text_DE_SimPpo2, text_FR_SimPpo2, text_IT_SimPpo2, text_ES_SimPpo2}},
+	{(uint8_t)TXT_CO2Sensor,		{text_EN_CO2Sensor, text_DE_CO2Sensor, text_FR_CO2Sensor, text_IT_CO2Sensor, text_ES_CO2Sensor}},
 };
 
 const tText text_array2[] =
@@ -1928,6 +1976,7 @@
     {(uint8_t)TXT2BYTE_Maintenance,		{text_EN_Maintenance, text_DE_Maintenance, text_FR_Maintenance, text_IT_Maintenance, text_ES_Maintenance}},
     {(uint8_t)TXT2BYTE_SetBatteryCharge,{text_EN_SetBatteryCharge, text_DE_SetBatteryCharge, text_FR_SetBatteryCharge, text_IT_SetBatteryCharge, text_ES_SetBatteryCharge}},
     {(uint8_t)TXT2BYTE_SetFactoryDefaults,{text_EN_SetFactoryDefaults, text_DE_SetFactoryDefaults, text_FR_SetFactoryDefaults, text_IT_SetFactoryDefaults, text_ES_SetFactoryDefaults}},
+    {(uint8_t)TXT2BYTE_ResetBluetooth, {text_EN_ResetBluetooth, text_DE_ResetBluetooth, text_FR_ResetBluetooth, text_IT_ResetBluetooth, text_ES_ResetBluetooth}},
 	{(uint8_t)TXT2BYTE_SetSampleIndex,  {text_EN_SetSampleIndex, text_DE_SetSampleIndex, text_FR_SetSampleIndex, text_IT_SetSampleIndex, text_ES_SetSampleIndex}},
 
     {(uint8_t)TXT2BYTE_Reboot,			{text_EN_Reboot, text_DE_Reboot, text_FR_Reboot, text_IT_Reboot, text_ES_Reboot}},
@@ -1955,4 +2004,8 @@
 	{(uint8_t)TXT2BYTE_Minimum, 		{text_EN_Minimum, text_DE_Minimum, text_FR_Minimum, text_IT_Minimum, text_ES_Minimum}},
 	{(uint8_t)TXT2BYTE_Normal, 			{text_EN_Normal, text_DE_Normal, text_FR_Normal, text_IT_Normal, text_ES_Normal}},
 	{(uint8_t)TXT2BYTE_Maximum, 		{text_EN_Maximum, text_DE_Maximum, text_FR_Maximum, text_IT_Maximum, text_ES_Maximum}},
+
+	{(uint8_t)TXT2BYTE_CheckSettings, 	{text_EN_CheckSettings, text_DE_CheckSettings, text_FR_CheckSettings, text_IT_CheckSettings, text_ES_CheckSettings}},
+
+
 };
--- a/Small_CPU/Inc/batteryCharger.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Inc/batteryCharger.h	Tue Dec 14 15:36:10 2021 +0100
@@ -31,9 +31,30 @@
 /* Includes ------------------------------------------------------------------*/
 #include <stdint.h>
 
-uint8_t get_charge_status(void);
+#define CHARGE_IN_PIN				GPIO_PIN_2
+#define CHARGE_IN_GPIO_PORT			GPIOC
+#define CHARGE_IN_GPIO_ENABLE()		__GPIOC_CLK_ENABLE()
+
+#define CHARGE_OUT_PIN				GPIO_PIN_1
+#define CHARGE_OUT_GPIO_PORT		GPIOC
+#define CHARGE_OUT_GPIO_ENABLE()	__GPIOC_CLK_ENABLE()
 
+ typedef enum
+ {
+ 	Charger_NotConnected = 0,		/* This is identified reading CHARGE_IN_PIN == HIGH */
+ 	Charger_WarmUp,					/* Charging started but counter did not yet reach a certain limit (used to debounce connect / disconnect events to avoid multiple increases of statistic charging cycle counter) */
+ 	Charger_Active,					/* Charging identified by  CHARGE_IN_PIN == LOW for a certain time */
+ 	Charger_Finished,
+ 	Charger_LostConnection,			/* Intermediate state to debounce disconnecting events (including charging error state like over temperature) */
+ 	Charger_ColdStart,				/* Cold start condition => check if an loaded battery has been inserted */
+ 	Charger_END
+ } chargerState_t;
+
+
+uint8_t get_charge_status(void);
 void init_battery_charger_status(void);
+void set_charge_state(chargerState_t newState);
+uint8_t get_charge_state(void);
 void ReInit_battery_charger_status_pins(void);
 void DeInit_battery_charger_status_pins(void);
 void battery_charger_get_status_and_contral_battery_gas_gauge(uint8_t cycleTimeBase);
--- a/Small_CPU/Inc/batteryGasGauge.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Inc/batteryGasGauge.h	Tue Dec 14 15:36:10 2021 +0100
@@ -31,6 +31,10 @@
 
 #include <stdint.h>
 
+#define BATTERY_DEFAULT_VOLTAGE					(6.0f)
+#define BATTERY_ENDOF_CHARGE_VOLTAGE			(4.05f)
+#define BATTERY_CHARGER_CONNECTED_VOLTAGE		(4.2f)
+
 void init_battery_gas_gauge(void);
 
 float get_voltage(void);
--- a/Small_CPU/Inc/externalInterface.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Inc/externalInterface.h	Tue Dec 14 15:36:10 2021 +0100
@@ -32,10 +32,24 @@
 #define MAX_ADC_CHANNEL		(3u)		/* number of channels to be read */
 #define EXTERNAL_ADC_NO_DATA	0xFF
 
+#define EXT33V_CONTROL_PIN				GPIO_PIN_7	/* PortC */
+
 void externalInterface_Init(void);
+void externalInterface_InitPower33(void);
 uint8_t externalInterface_StartConversion(uint8_t channel);
 uint8_t externalInterface_ReadAndSwitch();
 float externalInterface_CalculateADCValue(uint8_t channel);
 float getExternalInterfaceChannel(uint8_t channel);
+void externalInterface_SwitchPower33(uint8_t state);
+uint8_t externalInterface_isEnabledPower33();
+
+void externalInterface_SetCO2Value(uint16_t CO2_ppm);
+void externalInterface_SetCO2SignalStrength(uint16_t LED_qa);
+uint16_t externalInterface_GetCO2Value(void);
+uint16_t externalInterface_GetCO2SignalStrength(void);
+void externalInterface_SetCO2State(uint16_t state);
+uint16_t externalInterface_GetCO2State(void);
+
+void externalInterface_ExecuteCmd(uint16_t Cmd);
 
 #endif /* EXTERNAL_INTERFACE_H */
--- a/Small_CPU/Inc/uart.h	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Inc/uart.h	Tue Dec 14 15:36:10 2021 +0100
@@ -24,10 +24,24 @@
 
 #include "stm32f4xx_hal.h"
 
-void MX_USART2_UART_Init(void);
-void MX_USART2_UART_DeInit(void);
+
+ typedef enum
+ {
+ 	RX_Ready= 0,					/* Initial state */
+ 	RX_Data0,						/* Process incoming data */
+	RX_Data1,
+	RX_Data2,
+	RX_Data3,
+	RX_Data4,
+	RX_DataComplete
+ } receiveState_t;
+
+
+void MX_USART1_UART_Init(void);
+void MX_USART1_UART_DeInit(void);
+void MX_USART1_DMA_Init(void);
 uint8_t UART_ButtonAdjust(uint8_t *array);
-
+void HandleUARTData(void);
 
 #ifdef __cplusplus
 }
--- a/Small_CPU/Src/baseCPU2.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/baseCPU2.c	Tue Dec 14 15:36:10 2021 +0100
@@ -142,6 +142,7 @@
 #include "scheduler.h"
 #include "tm_stm32f4_otp.h"
 #include "externalInterface.h"
+#include "uart.h"
 
 // From Common/Inc:
 #include "calc_crush.h"
@@ -173,8 +174,8 @@
 		.signature = "mh",
 
 		.release_year = 21,
-		.release_month = 4,
-		.release_day = 26,
+		.release_month = 3,
+		.release_day = 30,
 		.release_sub = 0,
 
 		/* max 48 with trailing 0 */
@@ -230,6 +231,10 @@
 #define WIRELSS_POWER_GPIO_PORT     	GPIOB
 #define WIRELSS_POWER_HAL_RCC_GPIO_CLK_ENABLE()		 __HAL_RCC_GPIOB_CLK_ENABLE()
 
+
+#define LED_CONTROL_PIN          		GPIO_PIN_3		/* PortC */
+#define MAINCPU_CONTROL_PIN				GPIO_PIN_0		/* PortC */
+
 /* Private macro -------------------------------------------------------------*/
 
 /* Private variables ---------------------------------------------------------*/
@@ -353,12 +358,18 @@
 	HAL_Delay(10);
 	battery_gas_gauge_get_data();
 
+	global.lifeData.battery_voltage = get_voltage();
+	global.lifeData.battery_charge = get_charge();
+	copyBatteryData();
+
 	MX_SPI3_Init();
 
 	if(coldstart != 0xA5)	/* Not reading a 0xA5 means the memory cells has not been initialized before => cold start */
 	{
 		coldstart = 0xA5;
-		battery_gas_gauge_set(0);
+
+		set_charge_state(Charger_ColdStart);
+
 		global.dataSendToMaster.power_on_reset = 1;
 		global.deviceDataSendToMaster.power_on_reset = 1;
 
@@ -373,13 +384,16 @@
 			}
 		}
 	}
-
-	global.lifeData.battery_voltage = get_voltage();
-	global.lifeData.battery_charge = get_charge();
-	copyBatteryData();
+	else
+	{
+		set_charge_state(Charger_NotConnected);
+	}
 
 	ADCx_Init();
 	GPIO_Power_MainCPU_Init();
+
+	externalInterface_InitPower33();
+
 	global.mode = MODE_POWERUP;
 #else
 	init_pressure();
@@ -408,6 +422,7 @@
 			SPI_synchronize_with_Master();
 			MX_DMA_Init();
 			MX_SPI1_Init();
+			MX_USART1_UART_Init();
 			SPI_Start_single_TxRx_with_Master(); /* be prepared for the first data exchange */
 			Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD);
 			EXTI_Test_Button_Init();
@@ -478,7 +493,9 @@
 			 EXTI_Wakeup_Button_Init();
 			 NOT_USED_AT_THE_MOMENT_scheduleSleepMode();
 			 */
+
 			EXTI_Test_Button_DeInit();
+			externalInterface_SwitchPower33(false);
 			if (hasExternalClock())
 				SystemClock_Config_HSI();
 			sleep_prepare();
@@ -500,6 +517,11 @@
 			MX_SPI1_Init();
 			SPI_Start_single_TxRx_with_Master();
 
+			if(externalInterface_isEnabledPower33())
+			{
+				externalInterface_SwitchPower33(true);
+			}
+
 			// EXTILine0_Button_DeInit(); not now, later after testing
 			break;
 		}
@@ -793,7 +815,7 @@
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	__GPIOC_CLK_ENABLE();
-	GPIO_InitStructure.Pin = GPIO_PIN_3;
+	GPIO_InitStructure.Pin = LED_CONTROL_PIN;
 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
 	GPIO_InitStructure.Pull = GPIO_PULLUP;
 	GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
@@ -805,7 +827,7 @@
 	GPIO_InitTypeDef GPIO_InitStructure;
 
 	__GPIOC_CLK_ENABLE();
-	GPIO_InitStructure.Pin = GPIO_PIN_3;
+	GPIO_InitStructure.Pin = LED_CONTROL_PIN;
 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
 	GPIO_InitStructure.Pull = GPIO_PULLUP;
 	GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
@@ -815,33 +837,33 @@
 
 void GPIO_new_DEBUG_LOW(void) {
 #ifdef DEBUG_PIN_ACTIVE
-	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);
+	HAL_GPIO_WritePin(GPIOC,LED_CONTROL_PIN,GPIO_PIN_RESET);
 #endif
 }
 
 void GPIO_new_DEBUG_HIGH(void) {
 #ifdef DEBUG_PIN_ACTIVE
-	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);
+	HAL_GPIO_WritePin(GPIOC,LED_CONTROL_PIN,GPIO_PIN_SET);
 #endif
 }
 
 static void GPIO_Power_MainCPU_Init(void) {
 	GPIO_InitTypeDef GPIO_InitStructure;
 	__GPIOC_CLK_ENABLE();
-	GPIO_InitStructure.Pin = GPIO_PIN_0;
+	GPIO_InitStructure.Pin = MAINCPU_CONTROL_PIN;
 	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
 	GPIO_InitStructure.Pull = GPIO_PULLUP;
 	GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
 	HAL_GPIO_Init( GPIOC, &GPIO_InitStructure);
-	HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET);
 }
 
 static void GPIO_Power_MainCPU_ON(void) {
-	HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);
+	HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_RESET);
 }
 
 static void GPIO_Power_MainCPU_OFF(void) {
-	HAL_GPIO_WritePin( GPIOC, GPIO_PIN_0, GPIO_PIN_SET);
+	HAL_GPIO_WritePin( GPIOC, MAINCPU_CONTROL_PIN, GPIO_PIN_SET);
 }
 
 /**
@@ -938,11 +960,7 @@
 
 void sleep_prepare(void) {
 	EXTI_Wakeup_Button_Init();
-	/*
-	 GPIO_InitStruct.Pull = GPIO_PULLUP;
-	 GPIO_InitStruct.Pin =  GPIO_PIN_0;
-	 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-	 */
+
 	compass_sleep();
 	HAL_Delay(100);
 	accelerator_sleep();
@@ -972,8 +990,8 @@
 
 	GPIO_InitStruct.Pin =
 			GPIO_PIN_All
-					^ ( GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_14
-							| GPIO_PIN_15); /* power off & charger in & charge out & OSC32*/
+					^ ( MAINCPU_CONTROL_PIN | CHARGE_OUT_PIN | CHARGE_IN_PIN | EXT33V_CONTROL_PIN | LED_CONTROL_PIN); /* power off & charger in & charge out & OSC32 & ext33Volt */
+
 	HAL_GPIO_Init( GPIOC, &GPIO_InitStruct);
 
 	GPIO_InitStruct.Pin = GPIO_PIN_All ^ ( GPIO_PIN_0);
--- a/Small_CPU/Src/batteryCharger.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/batteryCharger.c	Tue Dec 14 15:36:10 2021 +0100
@@ -37,29 +37,12 @@
 /* Use This compile switch to select the new charger status control implementation */
 #define ENABLE_CHARGER_STATUS_V2
 
-#define CHARGE_IN_PIN							GPIO_PIN_2
-#define CHARGE_IN_GPIO_PORT				GPIOC
-#define CHARGE_IN_GPIO_ENABLE()		__GPIOC_CLK_ENABLE()
-
-#define CHARGE_OUT_PIN						GPIO_PIN_1
-#define CHARGE_OUT_GPIO_PORT			GPIOC
-#define CHARGE_OUT_GPIO_ENABLE()	__GPIOC_CLK_ENABLE()
-
-#define CHARGER_DEBOUNCE_SECONDS	(5u)		/* 5 seconds used to avoid problems with charger interrupts / disconnections */
+#define CHARGER_DEBOUNCE_SECONDS	(6u)		/* 6 seconds used to avoid problems with charger interrupts / disconnections */
 
 uint8_t battery_i_charge_status = 0;
 uint16_t battery_charger_counter = 0;
 
 #ifdef ENABLE_CHARGER_STATUS_V2
-typedef enum
-{
-	Charger_NotConnected = 0,		/* This is identified reading CHARGE_IN_PIN == HIGH */
-	Charger_WarmUp,					/* Charging started but counter did not yet reach a certain limit (used to debounce connect / disconnect events to avoid multiple increases of statistic charging cycle counter) */
-	Charger_Active,					/* Charging identified by  CHARGE_IN_PIN == LOW for a certain time */
-	Charger_Finished,
-	Charger_LostConnection			/* Intermediate state to debounce disconnecting events (including charging error state like over temperature) */
-} chargerState_t;
-
 static chargerState_t batteryChargerState = Charger_NotConnected;
 #endif
 
@@ -73,6 +56,21 @@
 	return battery_i_charge_status;
 }
 
+void set_charge_state(uint8_t newState)
+{
+#ifdef ENABLE_CHARGER_STATUS_V2
+	if(newState < Charger_END)
+	{
+		batteryChargerState = newState;
+	}
+#endif
+}
+
+uint8_t get_charge_state(void)
+{
+	return batteryChargerState;
+}
+
 void init_battery_charger_status(void)
 {
 	#ifdef OSTC_ON_DISCOVERY_HARDWARE
@@ -143,6 +141,7 @@
 {
 #ifdef ENABLE_CHARGER_STATUS_V2
 	static uint8_t notifyChargeComplete = 0;
+	static float chargeValueAtStart = 0;
 #endif 
 
 	#ifdef OSTC_ON_DISCOVERY_HARDWARE
@@ -150,115 +149,144 @@
 	#endif
 	
 #ifdef ENABLE_CHARGER_STATUS_V2
-	/* on disconnection or while disconnected */
-	if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))
+
+	if(batteryChargerState == Charger_ColdStart)	/* wait for the first valid voltage meassurement */
 	{
-		switch(batteryChargerState)
+		if(global.lifeData.battery_voltage != BATTERY_DEFAULT_VOLTAGE)
 		{
-			case Charger_Active:				global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
-												global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
-												batteryChargerState = Charger_LostConnection;
-												battery_charger_counter = CHARGER_DEBOUNCE_SECONDS;
-
-												if(get_voltage() >= 4.1f)			/* the charger stops charging when charge current is 1/10. */
-												{									/*  Basically it is OK to rate a charging as complete if a defined voltage is reached */
-													batteryChargerState = Charger_Finished;
-													global.dataSendToMaster.chargeStatus = CHARGER_complete;
-													global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
-													battery_charger_counter = 15;
-													notifyChargeComplete = 1;
-												}
-										break;
-			case Charger_WarmUp:
-			case Charger_Finished:
-			case Charger_LostConnection:		if(battery_charger_counter >= cycleTimeBase)
-												{
-													battery_charger_counter -= cycleTimeBase;
-													global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
-													global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
-													batteryChargerState = Charger_LostConnection;
-												}
-												else
-												{
-													battery_charger_counter = 0;
-													battery_i_charge_status = 0;
-													global.dataSendToMaster.chargeStatus = CHARGER_off;
-													global.deviceDataSendToMaster.chargeStatus = CHARGER_off;
-
-													if(notifyChargeComplete)
-													{
-														battery_gas_gauge_set_charge_full();
-														scheduleUpdateDeviceDataChargerFull();
-														notifyChargeComplete = 0;
-													}
-													batteryChargerState = Charger_NotConnected;
-												}
-										break;
-			default: break;
+			if(global.lifeData.battery_voltage > BATTERY_ENDOF_CHARGE_VOLTAGE) 						/* Voltage close to full state => maybe new battery inserted 	*/
+			{
+				battery_gas_gauge_set_charge_full();
+			}
+			else										/* unknown state => reset to 0% */
+			{
+				battery_gas_gauge_set(0);
+			}
+			batteryChargerState = Charger_NotConnected;
 		}
 	}
 	else
-	{
-		/* connected */
-		/* wait for disconnection to write and reset */
-		switch(batteryChargerState)
+	{	/* on disconnection or while disconnected */
+		if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))
 		{
-				case Charger_NotConnected:		battery_i_charge_status = 1;
-												battery_charger_counter = 0;
-												batteryChargerState = Charger_WarmUp;
-										break;
-				case Charger_LostConnection:		batteryChargerState = Charger_Active;
-										break;
-				case Charger_WarmUp:			battery_charger_counter += cycleTimeBase;
-												if(battery_charger_counter >= CHARGER_DEBOUNCE_SECONDS )
-												{
-													battery_i_charge_status = 2;
-													scheduleUpdateDeviceDataChargerCharging();
-													batteryChargerState = Charger_Active;
-												}
-						/* no break */
-				case Charger_Finished:
-				case Charger_Active:			global.dataSendToMaster.chargeStatus = CHARGER_running;
-												global.deviceDataSendToMaster.chargeStatus = CHARGER_running;
+			switch(batteryChargerState)
+			{
+				case Charger_Active:				global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
+													global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
+													batteryChargerState = Charger_LostConnection;
+													battery_charger_counter = CHARGER_DEBOUNCE_SECONDS;
+											break;
+				case Charger_LostConnection:		if(get_voltage() >= BATTERY_ENDOF_CHARGE_VOLTAGE)	 	/* the charger stops charging when charge current is 1/10 	*/
+																											/* Basically it is OK to rate a charging as complete if a defined voltage is reached */
+													{
+														batteryChargerState = Charger_Finished;
+														global.dataSendToMaster.chargeStatus = CHARGER_complete;
+														global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
+														notifyChargeComplete = 1;
+													}
+				/* no break */
+				case Charger_WarmUp:
+				case Charger_Finished:				if(battery_charger_counter >= cycleTimeBase)
+													{
+														battery_charger_counter -= cycleTimeBase;
+														global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
+														global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
+														batteryChargerState = Charger_LostConnection;
+													}
+													else
+													{
+														battery_charger_counter = 0;
+														battery_i_charge_status = 0;
+														global.dataSendToMaster.chargeStatus = CHARGER_off;
+														global.deviceDataSendToMaster.chargeStatus = CHARGER_off;
 
-												/* drive the output pin high to determine the state of the charger */
-												GPIO_InitTypeDef   GPIO_InitStructure;
-												GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
-												GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
-												GPIO_InitStructure.Pull = GPIO_NOPULL;
-												GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
-												HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
-												HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET);
-												HAL_Delay(1);
+														if(notifyChargeComplete)
+														{
+															battery_gas_gauge_set_charge_full();
+															scheduleUpdateDeviceDataChargerFull();
+															notifyChargeComplete = 0;
+															if(cycleTimeBase > 2)
+															{
+																HAL_Delay(50);		/* I2C operations are pending in the background. Wait to avoid data loose in caused to potential change to sleep state */
+															}
+														}
+														else
+														{
+															if(chargeValueAtStart < 1.0) /* charging started with unknown value => reset charge state reported by charger */
+															{
+																battery_gas_gauge_set(0);
+															}
+														}
+														batteryChargerState = Charger_NotConnected;
+													}
+											break;
+				default: break;
+			}
+		}
+		else
+		{
+			/* connected */
+			/* wait for disconnection to write and reset */
+			switch(batteryChargerState)
+			{
+					case Charger_NotConnected:		battery_i_charge_status = 1;
+													battery_charger_counter = 0;
+													batteryChargerState = Charger_WarmUp;
+													chargeValueAtStart = global.lifeData.battery_charge;
+											break;
+					case Charger_LostConnection:		batteryChargerState = Charger_Active;
+											break;
+					case Charger_WarmUp:			battery_charger_counter += cycleTimeBase;
+													if(battery_charger_counter >= CHARGER_DEBOUNCE_SECONDS )
+													{
+														battery_i_charge_status = 2;
+														scheduleUpdateDeviceDataChargerCharging();
+														batteryChargerState = Charger_Active;
+													}
+							/* no break */
+					case Charger_Finished:
+					case Charger_Active:			global.dataSendToMaster.chargeStatus = CHARGER_running;
+													global.deviceDataSendToMaster.chargeStatus = CHARGER_running;
 
-												if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))		/* high => charger stopped charging */
-												{
-													batteryChargerState = Charger_Finished;
-													global.dataSendToMaster.chargeStatus = CHARGER_complete;
-													global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
-													battery_charger_counter = 30;
-													notifyChargeComplete = 1;
-												}
-												else
-												{
-													if(batteryChargerState == Charger_Finished)				/* voltage dropped below the hysteresis again => charging restarted */
+													/* drive the output pin high to determine the state of the charger */
+													GPIO_InitTypeDef   GPIO_InitStructure;
+													GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+													GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+													GPIO_InitStructure.Pull = GPIO_NOPULL;
+													GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+													HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+													HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET);
+													HAL_Delay(1);
+
+													if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))		/* high => charger stopped charging */
+													{
+														batteryChargerState = Charger_Finished;
+														global.dataSendToMaster.chargeStatus = CHARGER_complete;
+														global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
+														battery_charger_counter = 30;
+														notifyChargeComplete = 1;
+													}
+													else
 													{
-														batteryChargerState = Charger_Active;
-														notifyChargeComplete = 0;
+														if(batteryChargerState == Charger_Finished)				/* voltage dropped below the hysteresis again => charging restarted */
+														{
+															batteryChargerState = Charger_Active;
+															notifyChargeComplete = 0;
+														}
 													}
-												}
 
-												/* restore high impedance to be able to detect disconnection */
-												GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
-												GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
-												GPIO_InitStructure.Pull = GPIO_NOPULL;
-												GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
-												HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
-												HAL_Delay(1);
-										break;
+													/* restore high impedance to be able to detect disconnection */
+													GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+													GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+													GPIO_InitStructure.Pull = GPIO_NOPULL;
+													GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+													HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+													HAL_Delay(1);
+											break;
 
-				default:						/* wait for disconnection */
-					break;
+					default:						/* wait for disconnection */
+						break;
+			}
 		}
 	}
 #else
--- a/Small_CPU/Src/batteryGasGauge.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/batteryGasGauge.c	Tue Dec 14 15:36:10 2021 +0100
@@ -28,7 +28,7 @@
 #include "stm32f4xx_hal.h"
 #include "i2c.h"
 
-static float battery_f_voltage = 6.0;		/* max assumed voltage */
+static float battery_f_voltage = BATTERY_DEFAULT_VOLTAGE;		/* max assumed voltage */
 static float battery_f_charge_percent = 0;
 
 #define BGG_BATTERY_OFFSET          (26123)  //; 65536-(3,35Ah/0,085mAh)
--- a/Small_CPU/Src/dma.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/dma.c	Tue Dec 14 15:36:10 2021 +0100
@@ -34,6 +34,7 @@
   */
 /* Includes ------------------------------------------------------------------*/
 #include "dma.h"
+#include "uart.h"
 
 /* USER CODE BEGIN 0 */
 
@@ -55,6 +56,7 @@
   /* DMA controller clock enable */
   __DMA2_CLK_ENABLE();
 
+  MX_USART1_DMA_Init();
   /* DMA interrupt init */
 
 }
--- a/Small_CPU/Src/externalInterface.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/externalInterface.c	Tue Dec 14 15:36:10 2021 +0100
@@ -27,8 +27,11 @@
 #include "i2c.h"
 #include "externalInterface.h"
 #include "scheduler.h"
+#include "uart.h"
+#include "data_exchange.h"
 
 extern SGlobal global;
+extern UART_HandleTypeDef huart1;
 
 #define ADC_ANSWER_LENGTH	(5u)		/* 3424 will provide addr + 4 data bytes */
 #define ADC_TIMEOUT			(10u)		/* conversion stuck for unknown reason => restart */
@@ -52,6 +55,10 @@
 static uint8_t externalInterfacePresent = 0;
 
 float externalChannel_mV[MAX_ADC_CHANNEL];
+static uint8_t  externalV33_On = 0;
+static uint16_t externalCO2Value;
+static uint16_t externalCO2SignalStrength;
+static uint16_t  externalCO2Status = 0;
 
 
 void externalInterface_Init(void)
@@ -65,6 +72,12 @@
 		global.deviceDataSendToMaster.hw_Info.extADC = 1;
 	}
 	global.deviceDataSendToMaster.hw_Info.checkADC = 1;
+
+/* init data values */
+	externalV33_On = 0;
+	externalCO2Value = 0;
+	externalCO2SignalStrength = 0;
+	externalCO2Status = 0;
 }
 
 
@@ -168,3 +181,92 @@
 	}
 	return retval;
 }
+
+void externalInterface_InitPower33(void)
+{
+	GPIO_InitTypeDef   GPIO_InitStructure;
+
+	GPIO_InitStructure.Pin = GPIO_PIN_7;
+	GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+	GPIO_InitStructure.Pull = GPIO_PULLUP;
+	GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+	HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
+	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);
+}
+
+
+uint8_t externalInterface_isEnabledPower33()
+{
+	return externalV33_On;
+}
+void externalInterface_SwitchPower33(uint8_t state)
+{
+	if(state != externalV33_On)
+	{
+		if(state)
+		{
+			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET);
+			externalV33_On = 1;
+			MX_USART1_UART_Init();
+		}
+		else
+		{
+			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);
+			externalV33_On = 0;
+			externalInterface_SetCO2Value(0);
+			externalInterface_SetCO2SignalStrength(0);
+			MX_USART1_UART_DeInit();
+		}
+	}
+}
+
+void externalInterface_SetCO2Value(uint16_t CO2_ppm)
+{
+	externalCO2Value = CO2_ppm;
+}
+
+void externalInterface_SetCO2SignalStrength(uint16_t LED_qa)
+{
+	externalCO2SignalStrength = LED_qa;
+}
+
+uint16_t externalInterface_GetCO2Value(void)
+{
+	return externalCO2Value;
+}
+
+uint16_t externalInterface_GetCO2SignalStrength(void)
+{
+	return externalCO2SignalStrength;
+}
+
+
+void externalInterface_SetCO2State(uint16_t state)
+{
+	externalCO2Status = state;
+}
+
+uint16_t externalInterface_GetCO2State(void)
+{
+	return externalCO2Status;
+}
+
+void externalInterface_ExecuteCmd(uint16_t Cmd)
+{
+	char cmdString[10];
+	uint8_t cmdLength = 0;
+
+	switch(Cmd & 0x00FF)		/* lower byte is reserved for commands */
+	{
+		case EXT_INTERFACE_CO2_CALIB:	cmdLength = snprintf(cmdString, 10, "G\r\n");
+			break;
+		default:
+			break;
+	}
+	if(cmdLength != 0)
+	{
+		HAL_UART_Transmit(&huart1,(uint8_t*)cmdString,cmdLength,10);
+	}
+	return;
+}
+
--- a/Small_CPU/Src/scheduler.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/scheduler.c	Tue Dec 14 15:36:10 2021 +0100
@@ -42,6 +42,7 @@
 #include "decom.h"
 #include "tm_stm32f4_otp.h"
 #include "externalInterface.h"
+#include "uart.h"
 
 /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */
 /* #define RESTORE_LAST_KNOWN_DATE */
@@ -90,6 +91,7 @@
 void copyDeviceData(void);
 void copyPICdata(void);
 void copyExtADCdata();
+void copyExtCO2data();
 static void schedule_update_timer_helper(int8_t thisSeconds);
 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow);
 
@@ -301,6 +303,20 @@
 	memcpy(&DeviceDataFlash, &global.dataSendToSlave.data.DeviceData, sizeof(SDevice));
 	deviceDataFlashValid = 1;
 
+
+	/* handle external interface requests */
+
+	if((global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_33V_ON) != externalInterface_isEnabledPower33())
+	{
+		externalInterface_SwitchPower33(global.dataSendToSlave.data.externalInterface_Cmd && EXT_INTERFACE_33V_ON);
+	}
+
+	if(global.dataSendToSlave.data.externalInterface_Cmd > EXT_INTERFACE_33V_ON)
+	{
+		externalInterface_ExecuteCmd(global.dataSendToSlave.data.externalInterface_Cmd);
+	}
+
+
 #if 0
 	//TODO: Temporary placed here. Duration ~210 ms.
 	if (global.I2C_SystemStatus != HAL_OK) {
@@ -501,6 +517,7 @@
 				externalInterface_CalculateADCValue(extAdcChannel);
 				copyExtADCdata();
 			}
+			copyExtCO2data();
 		}
 
 		//Evaluate pressure at 20 ms, 120 ms, 220 ms,....
@@ -761,10 +778,11 @@
 
 void scheduleSurfaceMode(void)
 {
-
 	uint32_t ticksdiff = 0; 
 	uint32_t lasttick = 0;
 	uint8_t extAdcChannel = 0;
+	uint8_t batteryToggle = 0;		/* ADC is operating in automatic 2 second cycles => consider for battery charge function call */
+
 	Scheduler.tickstart = HAL_GetTick();
 	Scheduler.counterSPIdata100msec = 0;
 	Scheduler.counterCompass100msec = 0;
@@ -787,6 +805,8 @@
 				setButtonsNow = 0;
 		}
 		
+		HandleUARTData();
+
 		/* Evaluate received data at 10 ms, 110 ms, 210 ms,... duration ~<1ms */
 		if(ticksdiff >= Scheduler.counterSPIdata100msec * 100 + 10)
 		{
@@ -801,6 +821,7 @@
 				externalInterface_CalculateADCValue(extAdcChannel);
 				copyExtADCdata();
 			}
+			copyExtCO2data();
 		}
 
 		/* Evaluate pressure at 20 ms, 120 ms, 220 ms,... duration ~22ms] */
@@ -886,8 +907,17 @@
 			{
 				global.lifeData.desaturation_time_minutes = 0;
 			}
-			battery_gas_gauge_get_data();
-			battery_charger_get_status_and_contral_battery_gas_gauge(1);
+
+			if(!batteryToggle)
+			{
+				battery_gas_gauge_get_data();
+				battery_charger_get_status_and_contral_battery_gas_gauge(2);
+				batteryToggle = 1;
+			}
+			else
+			{
+				batteryToggle = 0;
+			}
 
 			copyCnsAndOtuData();
 			copyTimeData();
@@ -1056,6 +1086,7 @@
 		if(global.mode == MODE_SLEEP)
 			secondsCount += 2;
 
+		externalInterface_InitPower33();
 		MX_I2C1_Init();
 		pressure_sensor_get_pressure_raw();
 
@@ -1069,7 +1100,6 @@
 			MX_I2C1_Init();
 			HAL_Delay(100);
 
-
 			if((global.I2C_SystemStatus == HAL_OK) && (!is_init_pressure_done()))
 			{
 				init_pressure();
@@ -1080,7 +1110,7 @@
 		{
 			pressure_sensor_get_temperature_raw();
 			battery_gas_gauge_get_data();
-//			ReInit_battery_charger_status_pins();
+			ReInit_battery_charger_status_pins();
 			battery_charger_get_status_and_contral_battery_gas_gauge(30);
 //			DeInit_battery_charger_status_pins();
 			secondsCount = 0;
@@ -1363,7 +1393,7 @@
 			}
 			break;
 
-		case	MODE_SLEEP:
+		case MODE_SLEEP:
 		case MODE_SHUTDOWN:
 			break;
 	}
@@ -1636,6 +1666,26 @@
 	}
 }
 
+void copyExtCO2data()
+{
+	uint16_t value;
+
+	if(externalInterface_GetCO2State())
+	{
+		value = externalInterface_GetCO2Value();
+		global.dataSendToMaster.data[0].CO2_ppm = value;
+		value = externalInterface_GetCO2SignalStrength();
+		global.dataSendToMaster.data[0].CO2_signalStrength = value;
+		global.dataSendToMaster.data[0].externalInterface_CmdAnswer = externalInterface_GetCO2State();
+		externalInterface_SetCO2State(EXT_INTERFACE_33V_ON); 	/* clear command responses */
+	}
+	else
+	{
+		global.dataSendToMaster.data[0].CO2_ppm = 0;
+		global.dataSendToMaster.data[0].CO2_signalStrength = 0;
+		global.dataSendToMaster.data[0].externalInterface_CmdAnswer = 0;
+	}
+}
 
 typedef enum 
 {
--- a/Small_CPU/Src/spi.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/spi.c	Tue Dec 14 15:36:10 2021 +0100
@@ -350,7 +350,6 @@
 
 		/* stop data exchange? */
 		if (global.mode == MODE_SHUTDOWN) {
-			global.mode = MODE_SLEEP;
 			global.dataSendToSlavePending = 0;
 			global.dataSendToSlaveIsValid = 1;
 			global.dataSendToSlaveIsNotValidCount = 0;
--- a/Small_CPU/Src/stm32f4xx_hal_msp_v3.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/stm32f4xx_hal_msp_v3.c	Tue Dec 14 15:36:10 2021 +0100
@@ -229,14 +229,18 @@
 {
 
   GPIO_InitTypeDef GPIO_InitStruct;
-  if(huart->Instance==USART2)
+  if(huart->Instance==USART1)
   {
-    __USART2_CLK_ENABLE();
-    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
+	  __GPIOA_CLK_ENABLE();
+    __USART1_CLK_ENABLE();
+    GPIO_InitStruct.Pin = GPIO_PIN_9;
     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
     GPIO_InitStruct.Pull = GPIO_PULLUP;
-    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
-    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
+    GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //GPIO_SPEED_LOW;
+    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    GPIO_InitStruct.Pin = GPIO_PIN_10;
     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   }
 }
@@ -244,10 +248,11 @@
 
 void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
 {
-  if(huart->Instance==USART2)
+  if(huart->Instance==USART1)
   {
-    __USART2_CLK_DISABLE();
-    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
+      HAL_NVIC_DisableIRQ(USART1_IRQn);
+    __USART1_CLK_DISABLE();
+    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
   }
 }
 
--- a/Small_CPU/Src/stm32f4xx_it_v3.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/stm32f4xx_it_v3.c	Tue Dec 14 15:36:10 2021 +0100
@@ -58,6 +58,9 @@
 extern RTC_HandleTypeDef RTCHandle;
 extern ADC_HandleTypeDef    AdcHandle;
 
+extern UART_HandleTypeDef huart1;
+extern DMA_HandleTypeDef  hdma_usart1_rx;
+
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
 
@@ -233,6 +236,11 @@
   * @retval None
   */
 
+void DMA2_Stream5_IRQHandler(void)
+{
+  HAL_DMA_IRQHandler(&hdma_usart1_rx);
+}
+
 
 /******************************************************************************/
 /*                 STM32F4xx Peripherals Interrupt Handlers                   */
@@ -295,6 +303,12 @@
   HAL_ADC_IRQHandler(&AdcHandle);
 }
 
+
+void USART1_IRQHandler(void)
+{
+  HAL_UART_IRQHandler(&huart1);
+}
+
 /**
   * @brief  This function handles PPP interrupt request.
   * @param  None
--- a/Small_CPU/Src/uart.c	Mon Nov 01 12:39:34 2021 +0100
+++ b/Small_CPU/Src/uart.c	Tue Dec 14 15:36:10 2021 +0100
@@ -20,57 +20,193 @@
   */ 
 /* Includes ------------------------------------------------------------------*/
 #include "uart.h"
+#include "externalInterface.h"
+#include "data_exchange.h"
 
 /* Private variables ---------------------------------------------------------*/
 
-UART_HandleTypeDef huart2;
+#define CHUNK_SIZE			(20u)		/* the DMA will handle chunk size transfers */
+#define CHUNKS_PER_BUFFER	(3u)
+UART_HandleTypeDef huart1;
+
+DMA_HandleTypeDef  hdma_usart1_rx;
 
+uint8_t rxBuffer[CHUNK_SIZE * CHUNKS_PER_BUFFER];		/* The complete buffer has a X * chunk size to allow fariations in buffer read time */
+static uint8_t rxWriteIndex;					/* Index of the data item which is analysed */
+static uint8_t rxReadIndex;						/* Index at which new data is stared */
+static uint8_t lastCmdIndex;					/* Index of last command which has not been completly received */
+static uint8_t dmaActive;						/* Indicator if DMA receiption needs to be started */
 
+float LED_Level = 0.0;							/* Normalized LED value which may be used as indication for the health status of the sensor */
+float LED_ZeroOffset = 0.0;
+float pCO2 = 0.0;
 /* Exported functions --------------------------------------------------------*/
 
-void MX_USART2_UART_Init(void)
+void MX_USART1_UART_Init(void)
 {
-/* pullup special */
-  GPIO_InitTypeDef   GPIO_InitStructure;
-  __GPIOA_CLK_ENABLE();
-  GPIO_InitStructure.Pin = GPIO_PIN_2;
-  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
-  GPIO_InitStructure.Pull = GPIO_PULLUP;
-  GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
-  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 
+/* regular init */	
+
+  huart1.Instance = USART1;
+  huart1.Init.BaudRate = 9600;
+  huart1.Init.WordLength = UART_WORDLENGTH_8B;
+  huart1.Init.StopBits = UART_STOPBITS_1;
+  huart1.Init.Parity = UART_PARITY_NONE;
+  huart1.Init.Mode = UART_MODE_TX_RX;
+  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+
+  HAL_UART_Init(&huart1);
+
+  rxReadIndex = 0;
+  lastCmdIndex = 0;
+  rxWriteIndex = 0;
+  dmaActive = 0;
+}
 
-/* regular init */	
-  huart2.Instance = USART2;
-  huart2.Init.BaudRate = 1200;
-  huart2.Init.WordLength = UART_WORDLENGTH_8B;
-  huart2.Init.StopBits = UART_STOPBITS_1;
-  huart2.Init.Parity = UART_PARITY_NONE;
-  huart2.Init.Mode = UART_MODE_TX_RX;
-  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
-  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
-  HAL_UART_Init(&huart2);
+void MX_USART1_UART_DeInit(void)
+{
+	HAL_DMA_DeInit(&hdma_usart1_rx);
+	HAL_UART_DeInit(&huart1);
+}
+
+void  MX_USART1_DMA_Init()
+{
+  /* DMA controller clock enable */
+  __DMA2_CLK_ENABLE();
+
+  /* Peripheral DMA init*/
+  hdma_usart1_rx.Instance = DMA2_Stream5;
+  hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
+  hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; //DMA_MEMORY_TO_PERIPH;
+  hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
+  hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
+  hdma_usart1_rx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
+  hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+  hdma_usart1_rx.Init.Mode = DMA_NORMAL;
+  hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
+  hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+  HAL_DMA_Init(&hdma_usart1_rx);
+
+  __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
+
+  /* DMA interrupt init */
+  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
+  HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
 }
 
 
-uint8_t UART_ButtonAdjust(uint8_t *array)
+uint32_t dataValue = 0;
+
+void HandleUARTData(void)
 {
-	uint8_t answer[4];
-	
-	HAL_UART_Transmit(&huart2,array,4,1000);
-	HAL_UART_Receive(&huart2,answer,4,2000);
-	if(	(answer[0] == array[0])
-		&&(answer[1] == array[1])
-		&&(answer[2] == array[2])
-		&&(answer[3] == array[3]))
-	return 1;
-	else
-	return 0;
+	uint8_t localRX = rxReadIndex;
+	uint8_t dataType = 0;
+	static receiveState_t rxState = RX_Ready;
+	static uint32_t lastReceiveTick = 0;
+
+	while(localRX != rxWriteIndex)
+	{
+		lastReceiveTick = HAL_GetTick();
+		if(rxState == RX_Ready)		/* identify data content */
+		{
+			switch(rxBuffer[localRX])
+			{
+				case 'l':
+				case 'D':
+				case 'Z':
+									dataType = rxBuffer[localRX];
+									rxState = RX_Data0;
+									dataValue = 0;
+					break;
+
+				default:			/* unknown or corrupted => ignore */
+					break;
+			}
+		}
+		else if((rxState >= RX_Data0) && (rxState <= RX_Data4))
+		{
+			if((rxBuffer[localRX] >= '0') && (rxBuffer[localRX] <= '9'))
+			{
+				dataValue = dataValue * 10 + (rxBuffer[localRX] - '0');
+				rxState++;
+			}
+		}
+		if((rxBuffer[localRX] == ' ') || (rxBuffer[localRX] == '\n'))	/* Abort data detection */
+		{
+			if(rxState == RX_DataComplete)
+			{
+				if(externalInterface_GetCO2State() == 0)
+				{
+					externalInterface_SetCO2State(EXT_INTERFACE_33V_ON);
+				}
+				switch(dataType)
+				{
+					case 'D':			externalInterface_SetCO2SignalStrength(dataValue);
+						break;
+					case 'l':			LED_ZeroOffset = dataValue;
+						break;
+					case 'Z':			externalInterface_SetCO2Value(dataValue);
+						break;
+					default: break;
+				}
+			}
+			if(rxState != RX_Data0)	/* reset state machine because message in wrong format */
+			{
+				rxState = RX_Ready;
+			}
+		}
+
+		localRX++;
+		rxReadIndex++;
+		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+		{
+			localRX = 0;
+			rxReadIndex = 0;
+		}
+	}
+
+	if(time_elapsed_ms(lastReceiveTick,HAL_GetTick()) > 2000)	/* check for communication timeout */
+	{
+		externalInterface_SetCO2State(0);
+	}
+
+	if((dmaActive == 0)	&& (externalInterface_isEnabledPower33()))	/* Should never happen in normal operation => restart in case of communication error */
+	{
+		if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
+		{
+			dmaActive = 1;
+		}
+	}
 }
 
-void MX_USART2_UART_DeInit(void)
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
 {
-	HAL_UART_DeInit(&huart2);
+    if(huart == &huart1)
+    {
+    	dmaActive = 0;
+    	rxWriteIndex+=CHUNK_SIZE;
+    	if(rxWriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+    	{
+    		rxWriteIndex = 0;
+    	}
+    	if((rxWriteIndex / CHUNK_SIZE) != (rxReadIndex / CHUNK_SIZE))	/* start next transfer if we did not catch up with read index */
+    	{
+    		if(externalInterface_isEnabledPower33())
+    		{
+				if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
+				{
+					dmaActive = 1;
+				}
+    		}
+    	}
+    }
 }
 
 
+
+
+
+
+
+
 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/