diff src/p2_deco.c @ 582:b455b31ce022

work on 2.97 stable
author heinrichsweikamp
date Mon, 26 Feb 2018 16:40:28 +0100
parents 4ce70e3f00be
children d63dec562d50
line wrap: on
line diff
--- a/src/p2_deco.c	Sun Feb 25 18:25:38 2018 +0100
+++ b/src/p2_deco.c	Mon Feb 26 16:40:28 2018 +0100
@@ -1,10 +1,10 @@
-// **************************************************************
-// p2_deco.c							REFACTORED VERSION	V2.95a2
+// ***************************************************************************
+// p2_deco.c                                         REFACTORED VERSION V2.97b
 //
 //  Created on: 12.05.2009
 //  Author: heinrichs weikamp, contributions by Ralph Lembcke and others
 //
-// **************************************************************
+// ***************************************************************************
 
 //////////////////////////////////////////////////////////////////////////////
 // OSTC - diving computer code
@@ -35,7 +35,7 @@
 // 07/xx/08 v102a: debug of bottom time routine
 // 09/xx/08 v102d: Gradient Factor Model implementation
 // 10/10/08 v104: renamed to build v103 for v118 stable
-// 10/14/08	v104: integration of char_I_depth_last_deco for Gradient Model
+// 10/14/08 v104: integration of char_I_depth_last_deco for Gradient Model
 // 03/31/09 v107: integration of FONT Incon24
 // 05/23/10 v109: 5 gas changes & 1 min timer
 // 07/13/10 v110: cns vault added
@@ -90,9 +90,9 @@
 // ** V A R I A B L E S   D E F I N I T I O N S **
 // ***********************************************
 
-#include "p2_definitions.h"
-#define  TEST_MAIN
-#include "shared_definitions.h"
+#include	"p2_definitions.h"
+#define		TEST_MAIN
+#include	"shared_definitions.h"
 
 
 // ambient pressure at different mountain heights
@@ -102,22 +102,23 @@
 
 // ambient pressure in aircraft cabin during flying - worst case according to Buhlmann
 #define P_ambient_fly					0.600	// [bar], 0.600 bar is the value used by Buhlmann for his flying-after-diving calculations
-												//		  0.735 bar is a typical cabin pressure for nowadays commercial jet aircrafts
+												//        0.735 bar is a typical cabin pressure for nowadays commercial jet aircrafts
 												//        -----
 												//        0.135 bar safety margin
 
 // constants and factors
-#define ppWater        					0.0627	// water vapor partial pressure in the lungs
-#define METER_TO_BAR   					0.09985	// conversion factor
-#define BAR_TO_METER   					10.0150	// conversion factor (1.0/METER_TO_BAR)						
-#define SURFACE_DESAT_FACTOR    		0.7042	// surface desaturation safety factor
+#define ppWater							0.0627	// water vapor partial pressure in the lungs
+#define METER_TO_BAR					0.09985	// conversion factor
+#define BAR_TO_METER					10.0150	// conversion factor (1.0/METER_TO_BAR)
+#define SURFACE_DESAT_FACTOR			0.7042	// surface desaturation safety factor
 #define HYST							1.0E-06	// threshold for tissue graphics on-gassing / off-gassing visualization
 
 // thresholds
-#define GF_warning_threshold			100		// threshold for GF   warning (attention threshold is current GF_high)
-#define CNS_warning_threshold			100		// threshold for CNS  warning
-#define CNS_prewarning_threshold		 70		// threshold for CNS  attention
-#define ppO2_prewarn_threshold			120		// threshold for ppO2 attention (master warnings come through options_table.asm)
+#define GF_WARNING_THRESHOLD			100		// threshold for GF   warning (attention threshold is current GF_high)
+#define CNS_WARNING_THRESHOLD			100		// threshold for CNS  warning
+#define CNS_ATTENTION_THRESHOLD			 70		// threshold for CNS  attention
+#define ppO2_ATTENTION_THRESHOLD		120		// threshold for ppO2 attention (thresholds for warnings come by options_table.asm)
+#define ppO2_GAP_TO_SETPOINT			 10		// gap between setpoint and max. ppO2 of the pure diluent [cbar]
 #define GAS_NEEDS_ATTENTION_THRESHOLD	0.70	// threshold for gas needs attention
 
 // deco engine states and modes - char_O_deco_status
@@ -125,7 +126,7 @@
 #define DECO_STATUS_START				0x00
 #define DECO_STATUS_FINISHED			0x00
 #define DECO_STATUS_STOPS				0x01 
-#define DECO_STATUS_ASCENT				0x02
+#define DECO_STATUS_RESULTS				0x02
 #define DECO_STATUS_INIT				0x03
 
 #define DECO_MODE_MASK					0x0C
@@ -134,23 +135,26 @@
 #define DECO_MODE_PSCR					0x08
 
 #define DECO_PLAN_ALTERNATE				0x10
-#define DECO_CNS_CALCULATE 				0x20
-#define DECO_VOLUME_CALCULATE	 		0x40
-#define DECO_ASCENT_DELAYED 			0x80
+#define DECO_CNS_CALCULATE				0x20
+#define DECO_VOLUME_CALCULATE			0x40
+#define DECO_ASCENT_DELAYED				0x80
 
 // deco engine states and modes - char_O_main_status
 //#define DECO_MODE_MASK				0x0C
 //#define DECO_MODE_LOOP				0x04
 //#define DECO_MODE_CCR					0x04	// to be used with == operator in combination with DECO_MODE_MASK only!
 //#define DECO_MODE_PSCR				0x08
-#define DECO_GASCHANGE_OVRD 			0x10
+#define DECO_GASCHANGE_OVRD				0x10
 #define DECO_BOTTOM_CALCULATE			0x40
 
+// deco engine states and modes - tissue_increment
+#define TIME_MASK						0x7F	// (127 decimal, bits 0-6)
+#define TISSUE_FLAG						0x80	// (128 decimal, bit   7 )
 
 // deco engine warnings
 #define	DECO_WARNING_IBCD				0x01
 #define	DECO_WARNING_IBCD_lock			0x02
-#define	DECO_WARNING_MBUBBLES 			0x04
+#define	DECO_WARNING_MBUBBLES			0x04
 #define	DECO_WARNING_MBUBBLES_lock		0x08
 #define	DECO_WARNING_OUTSIDE			0x10
 #define	DECO_WARNING_OUTSIDE_lock		0x20
@@ -162,7 +166,7 @@
 #define INT_FLAG_ZERO					0x0800
 #define INT_FLAG_LOW					0x1000
 #define	INT_FLAG_HIGH					0x2000
-#define INT_FLAG_PREWARNING				0x4000
+#define INT_FLAG_ATTENTION				0x4000
 #define	INT_FLAG_WARNING				0x8000
 
 
@@ -175,28 +179,26 @@
 static void calc_hauptroutine_data_input(void);
 static void calc_hauptroutine_update_tissues(void);
 static void calc_hauptroutine_calc_deco(void);
-static void calc_tissue(void);
-static void calc_limit(void);
-static void calc_nullzeit(void);
+static void calc_alveolar_pressures(void);
+static void calc_tissues(void);
+static void calc_NDL_time(void);
 static void calc_ascenttime(void);
-static void calc_dive_interval(void);
-static void calc_gradient_factor(void);
-static void calc_wo_deco_step_1_min(void);
+static void calc_CNS_increment(void);
 static void calc_desaturation_time(void);
-
-static void sim_extra_time(void);
-static void sim_ascent_to_first_stop(void);
-static void sim_limit(PARAMETER float GF_current);
-
-static void update_startvalues(void);
-static void gas_switch_set(void);
-static void compute_CNS_for_display(void);
-
+static void calc_ascent_to_first_stop(void);
+static void calc_limit(PARAMETER float GF_current);
+static void calc_interval(PARAMETER unsigned char time_increment);
+
+static void gas_find_current(void);
+static void gas_set_ratios(void);
+static void convert_CNS_for_display(void);
+static void convert_sim_CNS_for_display(void);
+static void publish_deco_table(void);
 static void clear_deco_table(void);
 static void clear_tissue(void);
 
+static unsigned char calc_nextdecodepth(void);
 static unsigned char gas_find_better(void);
-static unsigned char calc_nextdecodepth(void);
 static unsigned char update_deco_table(PARAMETER unsigned char time_increment);
 
 
@@ -217,28 +219,28 @@
 static float			low_depth_alt;					// Depth of deepest stop in alternative plan
 
 static float			float_ascent_speed;				// ascent speed from options_table (1.0 .. 10.0 m/min)
-static float			float_saturation_multiplier;    // safety factor for on-gassing rates
-static float			float_desaturation_multiplier;  // safety factor for off-gassing rates
-static float			float_deco_distance;            // additional depth below stop depth for tissue, CNS and gas volume calculation
-
-
-// real context: what we are doing now.
-
-static float			calc_lead_tissue_limit;     	// minimum tolerated ambient pressure by Buhlmann model
-static float			CNS_fraction;                   // current CNS (1.00 = 100%)
-
-static unsigned short	deco_tissue_vector;				// 32 bit vector to memories all tissues that are in decompression
-static unsigned short	IBCD_tissue_vector;				// 32 bit vector to memories all tissues that experience IBCD
-
-// simulation context: used to predict ascent.
-
-static float			sim_lead_tissue_limit;			// minimum tolerated ambient pressure by Buhlmann model
-static float			CNS_sim_norm_fraction;			// CNS at end of dive in normal plan
-static float			CNS_sim_alt_fraction;			// CNS at end of dive in alternative plan
-
-static unsigned char	temp_depth_limit;				// depth of next stop in meters, used in deco calculations
-static unsigned char	sim_lead_tissue_no;				// Leading compartment number
+static float			float_deco_distance;			// additional depth below stop depth for tissue, CNS and gas volume calculation
+static float			float_saturation_multiplier;	// safety factor for on-gassing rates
+static float			float_desaturation_multiplier;	// safety factor for off-gassing rates
+
+// real context: what we are doing now
+
+static float			ceiling;						// minimum tolerated relative pressure (i.e. without surface pressue)
+static float			CNS_fraction;					// current CNS (1.00 = 100%)
+
+static unsigned short	deco_tissue_vector;				// 16 bit vector to memories all tissues that are in decompression
+static unsigned short	IBCD_tissue_vector;				// 16 bit vector to memories all tissues that experience IBCD
+
+// simulation context: used to predict ascent
+
+static float			sim_ceiling;					// minimum tolerated relative pressure (i.e. without surface pressue)
+static float			sim_CNS_fraction;				// CNS increase during predicted ascent, 0.01 = 1%
+
+static unsigned int		int_sim_CNS_fraction;			// CNS increase during predicted ascent, in %
+
+static unsigned char	sim_depth_limit;				// depth of next stop in meters, used in deco calculations
 static unsigned char	split_N2_He[NUM_COMP];			// used for calculating the desaturation time
+static unsigned char	NDL_lead_tissue;				// used to cache tissue to start with calculating NDL
 
 
 // stops table
@@ -252,18 +254,27 @@
 
 static float			desat_factor;					// used to cache a pre-computed factor
 static float			var_ht;							// buffer for a half-time factor
-static float 			pres_target;					// target pressure for a compartment
+static float			pres_target;					// target pressure for a compartment
 static float			pres_actual;					// current pressure of the compartment
-static unsigned short	short_time;						// time it takes for the compartment to reach the target pressure
+static unsigned int		int_time;						// time it takes for the compartment to reach the target pressure
+
 
 // transfer variables between gas_volumes() and gas_volumes_helper()
+
 static float			float_depth;					// depth of the stop or half-way point
 static float			float_time;						// duration of the stop or ascent phase
 static float			volume;							// computed volume of gas
 static unsigned char	usage;							// gas usage in l/min
 
 
-// 44 byte free space left in this bank
+// auxiliary variables for data buffering
+
+static float			N2_equilibrium;					// used for N2 tissue graphics scaling
+static float			temp_tissue;					// auxiliary variable to buffer tissue pressures
+static float			float_pSCR_factor;				// pre-computed factor for pSCR ppO2 drop calculation
+
+
+// 35 byte free space left in this bank (4 bytes per float, 2 bytes per int/short, 1 byte per char)
 
 
 //---- Bank 6 parameters -----------------------------------------------------
@@ -275,74 +286,73 @@
 
 static unsigned char	ci;								// used as index to the Buhlmann tables
 static unsigned char	twosectimer = 0;				// used for timing the tissue updating
-static unsigned char	tissue_increment;				// Selector for real/simulated tissues and time increment
+static unsigned char	tissue_increment;				// selector for real/simulated tissues and time increment
 
 
 // environmental and gas data
 
-static float            pres_respiration;				// current depth in absolute pressure
-static float            pres_surface;					// absolute pressure at the surface
-static float            temp_deco;						// simulated current depth in abs.pressure, used for deco calculations
+static float			pres_surface;					// absolute pressure at the surface
 
 static unsigned char	bottom_depth;					// bottom depth in meters, used by CNS and gas needs calculation
 
-static float            O2_ratio;                       // real breathed gas oxygen ratio
-static float            N2_ratio;                       // real breathed gas nitrogen ratio
-static float            He_ratio;                       // real breathed gas helium ratio
-
-static float			calc_O2_ratio;					// simulated breathed gas oxygen ratio
-static float			calc_N2_ratio;                  // simulated breathed gas nitrogen ratio
-static float			calc_He_ratio;                  // simulated breathed gas helium ratio
+static float			pres_respiration;				// current depth in absolute pressure
+static float			O2_ratio;						// real breathed gas oxygen ratio
+static float			N2_ratio;						// real breathed gas nitrogen ratio
+static float			He_ratio;						// real breathed gas helium ratio
+static float			pSCR_drop;						// real ppO2 drop in pSCR loop
+
+static float			sim_pres_respiration;			// simulated current depth in abs.pressure, used for deco calculations
+static float			sim_O2_ratio;					// simulated breathed gas oxygen ratio
+static float			sim_N2_ratio;					// simulated breathed gas nitrogen ratio
+static float			sim_He_ratio;					// simulated breathed gas helium ratio
+static float			sim_pSCR_drop;					// simulated ppO2 drop in pSCR loop
 
 static float			O2_ppO2;						// ppO2 - calculated for pure oxygen at current depth
+static float			OC_ppO2;						// ppO2 - calculated for breathed in OC mode
 static float			pSCR_ppO2;						// ppO2 - calculated for breathed from pSCR loop
-static float			pure_ppO2;						// ppO2 - calculated for breathed in OC mode
-
-static unsigned char	char_actual_ppO2;				// ppO2 - assumed to be breathed, as integer 100 = 1.00 bar
-
-static float			breathed_ppO2;					// partial pressure of breathed oxygen
-static float            ppN2;							// partial pressure of breathed nitrogen
-static float            ppHe;							// partial pressure of breathed helium
+
+static float			ppO2;							// partial pressure of breathed oxygen
+static float			ppN2;							// partial pressure of breathed nitrogen
+static float			ppHe;							// partial pressure of breathed helium
+
+
+// Result values from calculation functions
+
+static float			CNS_fraction_inc;				// increment of CNS load, 0.01 = 1%
+
+static unsigned char	char_ppO2;						// partial pressure of breathed oxygen, as integer 100 = 1.00 bar
+static unsigned char	NDL_time;						// time in minutes until reaching NDL
+static unsigned int		ascent_time;					// time in minutes needed for the ascent
 
 
 // Buhlmann model parameters
 
-static float            var_N2_a;                       // Buhlmann a, for current N2 tissue
-static float            var_N2_b;                       // Buhlmann b, for current N2 tissue
-static float            var_He_a;                       // Buhlmann a, for current He tissue
-static float            var_He_b;                       // Buhlmann b, for current He tissue
-static float            var_N2_e;                       // exposition, for current N2 tissue
-static float            var_He_e;                       // exposition, for current He tissue
-static float            var_N2_ht;                      // half-time for current N2 tissue
-static float            var_He_ht;                      // half-time for current N2 tissue
-
-
-// gas switch history
+static float			var_N2_a;						// Buhlmann a, for current N2 tissue
+static float			var_N2_b;						// Buhlmann b, for current N2 tissue
+static float			var_He_a;						// Buhlmann a, for current He tissue
+static float			var_He_b;						// Buhlmann b, for current He tissue
+static float			var_N2_e;						// exposition, for current N2 tissue
+static float			var_He_e;						// exposition, for current He tissue
+static float			var_N2_ht;						// half-time for current N2 tissue
+static float			var_He_ht;						// half-time for current N2 tissue
+
+
+// Gas switch history
 
 static unsigned char	sim_gas_first_used;				// Number of first used gas, for bottom segment
-static unsigned char    sim_gas_last_used;              // number of last  used gas
-static unsigned char    sim_gas_last_depth;             // change depth of last used gas
-
-
-// vault to back-up & restore tissue data
+static unsigned char	sim_gas_last_used;				// number of last  used gas
+static unsigned char	sim_gas_last_depth;				// change depth of last used gas
+
+
+// Vault to back-up & restore tissue data
 
 static float			pres_tissue_N2_vault[NUM_COMP];	// stores the nitrogen tissue pressures
 static float			pres_tissue_He_vault[NUM_COMP];	// stores the helium tissue pressures
-static float			low_depth_norm_vault;			// stores a parameter of the GF model for normal plan
-static float			low_depth_alt_vault;			// stores a parameter of the GF model for alternative plan
 static float			cns_vault_float;				// stores current CNS (float representation)
-
-static unsigned int		cns_vault_int;					// stores current CNS (integer representation)
 static unsigned char	deco_warnings_vault;			// stores warnings status
 
 
-// auxiliary variables for local data buffering
-
-static float 			N2_equilibrium;					// used for N2 tissue graphics scaling
-static float            temp_tissue;					// auxiliary variable to buffer tissue pressures
-
-
-// 6 byte free space left in this bank
+// 8 byte free space left in this bank (4 bytes per float, 2 bytes per int/short, 1 byte per char)
 
 
 //---- Bank 7 parameters -----------------------------------------------------
@@ -354,32 +364,36 @@
 
 float					pres_tissue_N2[NUM_COMP];		// 16 floats = 64 bytes
 float					pres_tissue_He[NUM_COMP];		// 16 floats = 64 bytes
+
 float					sim_pres_tissue_N2[NUM_COMP];	// 16 floats = 64 bytes
 float					sim_pres_tissue_He[NUM_COMP];	// 16 floats = 64 bytes
 
+// bank is full!
+
 
 //---- Bank 8 parameters -----------------------------------------------------
 #ifndef UNIX
 #   pragma udata overlay bank8=0x800
 
-static char	  md_pi_subst[256];				// Overlay C-code data stack here, too.
+static char				md_pi_subst[256];				// Overlay C-code data stack here, too.
 
 #   define C_STACK md_pi_subst
 #endif
 
+
 // Back to bank6 for further tmp data
+// Do not delete this assignment, it is needed by the compiler/linker.
 #ifndef UNIX
 #   pragma udata bank6
 #endif
 
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
-///////////////////////////// THE LOOKUP TABLES //////////////////////////////
+////////////////              THE LOOKUP TABLES               ////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
-//
-// End of PROM code is 17F00, So push tables on PROM top...
-//
+
 #ifndef UNIX
 #   pragma romdata Buhlmann_tables = 0x1DD00  // Needs to be in UPPER bank.
 #endif
@@ -432,19 +446,19 @@
 	5.75958E-03,    1.51848E-02,  
 	2.88395E-03,    7.62144E-03,
 	1.84669E-03,    4.88315E-03,
-    1.24813E-03,    3.29997E-03,
-    8.55371E-04,    2.26041E-03,
-    6.03079E-04,    1.59437E-03,
-    4.25414E-04,    1.12479E-03,
-    3.00019E-04,    7.93395E-04,
-    2.11949E-04,    5.60641E-04,
-    1.58240E-04,    4.18555E-04,
-    1.23548E-04,    3.26795E-04,
-    9.66686E-05,    2.55722E-04,
-    7.57509E-05,    2.00387E-04,
-    5.92416E-05,    1.56716E-04,
-    4.63943E-05,    1.22734E-04,
-    3.63850E-05,    9.62538E-05
+	1.24813E-03,    3.29997E-03,
+	8.55371E-04,    2.26041E-03,
+	6.03079E-04,    1.59437E-03,
+	4.25414E-04,    1.12479E-03,
+	3.00019E-04,    7.93395E-04,
+	2.11949E-04,    5.60641E-04,
+	1.58240E-04,    4.18555E-04,
+	1.23548E-04,    3.26795E-04,
+	9.66686E-05,    2.55722E-04,
+	7.57509E-05,    2.00387E-04,
+	5.92416E-05,    1.56716E-04,
+	4.63943E-05,    1.22734E-04,
+	3.63850E-05,    9.62538E-05
 //-------------------------------------
 };
 
@@ -452,22 +466,22 @@
 // Integration constant for 1 minute,
 // Ie. 1- 2^(-1/HT)
 //----- N2 --------- e 1min He --------
-	1.59104E-01,    3.68109E-01,  	
-    8.29960E-02,   	2.05084E-01,     
-    5.39424E-02,    1.36579E-01,
-    3.67742E-02,    9.44046E-02,
-    2.53454E-02,    6.56359E-02,
-    1.79351E-02,    4.67416E-02,
-    1.26840E-02,    3.31991E-02,
-    8.96152E-03,    2.35301E-02,
-    6.33897E-03,    1.66832E-02,
-    4.73633E-03,    1.24808E-02,
-    3.69981E-03,    9.75753E-03,
-    2.89600E-03,    7.64329E-03,
-    2.27003E-03,    5.99417E-03,
-    1.77572E-03,    4.69082E-03,
-    1.39089E-03,    3.67548E-03,
-    1.09097E-03,    2.88359E-03
+	1.59104E-01,    3.68109E-01,
+	8.29960E-02,    2.05084E-01,
+	5.39424E-02,    1.36579E-01,
+	3.67742E-02,    9.44046E-02,
+	2.53454E-02,    6.56359E-02,
+	1.79351E-02,    4.67416E-02,
+	1.26840E-02,    3.31991E-02,
+	8.96152E-03,    2.35301E-02,
+	6.33897E-03,    1.66832E-02,
+	4.73633E-03,    1.24808E-02,
+	3.69981E-03,    9.75753E-03,
+	2.89600E-03,    7.64329E-03,
+	2.27003E-03,    5.99417E-03,
+	1.77572E-03,    4.69082E-03,
+	1.39089E-03,    3.67548E-03,
+	1.09097E-03,    2.88359E-03
 //-------------------------------------
 };
 
@@ -475,28 +489,28 @@
 // The 10 min Value in float notation:
 //  result of 1 - 2^(-10/ht)
 //---- N2 -------------- He -----------
-	8.23223E-01,    9.89851E-01,  
-	5.79552E-01,  	8.99258E-01,
-    4.25651E-01,    7.69737E-01,
-    3.12487E-01,    6.29027E-01,
-    2.26416E-01,    4.92821E-01,
-    1.65547E-01,    3.80407E-01,
-    1.19840E-01,    2.86538E-01,
-    8.60863E-02,    2.11886E-01,
-    6.16117E-02,    1.54849E-01,
-    4.63665E-02,    1.18026E-01,
-    3.63881E-02,    9.34005E-02,
-    2.85855E-02,    7.38569E-02,
-    2.24698E-02,    5.83504E-02,
-    1.76160E-02,    4.59303E-02,
-    1.38222E-02,    3.61528E-02,
-    1.08563E-02,    2.84646E-02
+	8.23223E-01,    9.89851E-01,
+	5.79552E-01,    8.99258E-01,
+	4.25651E-01,    7.69737E-01,
+	3.12487E-01,    6.29027E-01,
+	2.26416E-01,    4.92821E-01,
+	1.65547E-01,    3.80407E-01,
+	1.19840E-01,    2.86538E-01,
+	8.60863E-02,    2.11886E-01,
+	6.16117E-02,    1.54849E-01,
+	4.63665E-02,    1.18026E-01,
+	3.63881E-02,    9.34005E-02,
+	2.85855E-02,    7.38569E-02,
+	2.24698E-02,    5.83504E-02,
+	1.76160E-02,    4.59303E-02,
+	1.38222E-02,    3.61528E-02,
+	1.08563E-02,    2.84646E-02
 //-------------------------------------
 };
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
-////////////////////////////// THE SUBROUTINES ///////////////////////////////
+////////////////               THE SUBROUTINES                ////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 //
@@ -508,7 +522,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
-///////////////////////  U T I L I T I E S   /////////////////////////////////
+////////////////             U T I L I T I E S                ////////////////
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
@@ -676,12 +690,154 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////////////////      THE JUMP-IN CODE for the asm code       ////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_calc_hauptroutine
+//
+// called from: divemode.asm
+//
+// Called every second during diving,
+// updates tissues on every second invocation.
+//
+// Every few seconds (or slower when TTS > 16):
+// - Updates deco table (char_O_deco_time/depth) with new values,
+// - updates ascent time, and
+// - sets status to zero (so we can check there is new results).
+//
+void deco_calc_hauptroutine(void)
+{
+	RESET_C_STACK
+	calc_hauptroutine();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_clear_tissue
+//
+// called from: start.asm
+//              menu_tree.asm
+//              simulator.asm
+//
+// Sets all tissues to equilibrium with Air at ambient pressure,
+// resets all CNS values, any warnings and resets all model output.
+//
+void deco_clear_tissue(void)
+{
+	RESET_C_STACK
+	clear_tissue();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_calc_dive_interval
+//
+// called from: simulator.asm
+//
+// Updates tissues and CNS value for char_I_dive_interval minutes on Air
+// at ambient pressure and calculates resulting GF factor and ceiling for
+// a GF-high of 100% (ceiling and GF factor not used by simulator.asm)
+//
+void deco_calc_dive_interval(void)
+{
+	RESET_C_STACK
+	calc_interval(char_I_dive_interval);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_calc_dive_interval_1min
+//
+// called from: start.asm
+//              sleepmode.asm
+//              surfmode.asm
+//              menu_tree.asm
+//              ghostwriter.asm
+//
+// Updates tissues and CNS value for 1 minute on Air at ambient pressure and
+// calculates resulting GF factor and ceiling for a GF-high of 100% (ceiling
+// is not used by *.asm files).
+//
+void deco_calc_dive_interval_1min(void)
+{
+	RESET_C_STACK
+	calc_interval(1);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_calc_dive_interval_1min
+//
+// called from: sleepmode.asm
+//
+// Updates tissues and CNS value for 10 minutes on Air at ambient pressure and
+// calculates resulting GF factor and ceiling for a GF-high of 100% (ceiling
+// is not used by sleepmode.asm).
+//
+void deco_calc_dive_interval_10min(void)
+{
+	RESET_C_STACK
+	calc_interval(10);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_calc_desaturation_time
+//
+// called from: start.asm
+//              surfmode.asm
+//              menu_tree.asm
+//              ghostwriter.asm
+//
+// Computes desaturation and no-fly times.
+//
+void deco_calc_desaturation_time(void)
+{
+	RESET_C_STACK
+	calc_desaturation_time();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_push_tissues_to_vault
+//
+// called from: simulator.asm
+//
+// Makes a backup of the state of the real tissues and the deco engine.
+//
+void deco_push_tissues_to_vault(void)
+{
+	RESET_C_STACK
+	push_tissues_to_vault();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// deco_pull_tissues_from_vault
+//
+// called from: simulator.asm
+//              ghostwriter.asm
+//
+// Restores the state of the real tissues and the deco engine from the backup.
+//
+void deco_pull_tissues_from_vault(void)
+{
+	RESET_C_STACK
+	pull_tissues_from_vault();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////////////////                THE FUNCTIONS                 ////////////////
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////////
 // calc_nextdecodepth
 //
 // new in v.102
 //
 // INPUT, changing during dive:
-//      temp_deco : current depth in absolute pressure
+//      sim_pres_respiration : current depth in absolute pressure
 //
 // INPUT, fixed during dive:
 //      pres_surface
@@ -695,69 +851,66 @@
 //      low_depth_norm/_alt      : used for GF model
 //
 // OUTPUT
-//      temp_depth_limit : depth of next stop in meters        (if RETURN == true )
-//                         depth we can ascent to without stop (if RETURN == false)
+//      sim_depth_limit : depth of next stop in meters        (if RETURN == true )
+//                        depth we can ascent to without stop (if RETURN == false)
 //
 // RETURN TRUE if a stop is needed.
 //
 static unsigned char calc_nextdecodepth(void)
 {
-    overlay unsigned char need_stop;
-	
+	overlay unsigned char need_stop;
+
 	// compute current depth in meters
-    overlay float depth = (temp_deco - pres_surface) * BAR_TO_METER;
-
-    // compute depth in meters after 1 minute of ascent at float_ascent_speed (5..10 m/min)
-    overlay float min_depth = (depth > float_ascent_speed) ? (depth - float_ascent_speed) : 0.0;
-
-	
-	 // allow for 200mbar of weather dependent surface pressure change
-    assert( depth >= -0.2 );       
+	overlay float depth = (sim_pres_respiration - pres_surface) * BAR_TO_METER;
+
+	// compute depth in meters after 1 minute of ascent at float_ascent_speed (5..10 m/min)
+	overlay float min_depth = (depth > float_ascent_speed) ? (depth - float_ascent_speed) : 0.0;
+
+
+	// allow for 200mbar of weather dependent surface pressure change
+	assert( depth >= -0.2 );
 
 
 	//---- check if a stop is needed for deco reasons ----------------------------
-	
-    // switch on deco model
-    if( char_I_deco_model != 0 )
-    {
+
+	// switch on deco model
+	if( char_I_deco_model != 0 )
+	{
 		//---- ZH-L16 + GRADIENT FACTOR Model ------------------------------------
-		
+
 		overlay float locked_GF_step;
 		overlay float low_depth;
-		overlay float pres_gradient;
-
-        overlay unsigned char first_stop = 0;
-		
-				
-		// calculate minimum depth we can ascent to in absolute pressure
-        sim_limit( GF_low );
-		
-		// ...and convert the depth into relative pressure
-        pres_gradient = sim_lead_tissue_limit - pres_surface;	
+		overlay float limit_depth;
+
+		overlay unsigned char first_stop = 0;
+
+
+		// calculate minimum depth we can ascent to in bar relative pressure
+		calc_limit(GF_low);
 
 		// check if we can surface directly
-        if( pres_gradient <= 0.0 )
+		if( sim_ceiling <= 0.0 )
 		{
 			min_depth = 0.0;		// set minimum depth to 0 meters = surface
 			goto no_deco_stop;		// done.
 		}
 
 		// convert minimum depth we can ascent to from relative pressure to depth in meters
-        pres_gradient *= BAR_TO_METER;							
+		limit_depth = sim_ceiling * BAR_TO_METER;
 
 		// recall low_depth dependent on current plan
 		low_depth = (char_O_deco_status & DECO_PLAN_ALTERNATE) ? low_depth_alt : low_depth_norm;
 		
-        // Store the deepest point needing a deco stop as the LOW reference for GF.
-        // NOTE: following stops will be validated using this LOW-HIGH GF scale,
-        //       so if we want to keep coherency, we should not validate this stop
-        //       yet, but apply the search to it, as for all the following stops afterward.
-        if( pres_gradient > low_depth )
-        {
+		// Store the deepest point needing a deco stop as the LOW reference for GF.
+		// NOTE: following stops will be validated using this LOW-HIGH GF scale,
+		//       so if we want to keep coherency, we should not validate this stop
+		//       yet, but apply the search to it, as for all the following stops afterward.
+		if( limit_depth > low_depth )
+		{
 			// update GF parameters
-            low_depth      = pres_gradient;
-            locked_GF_step = GF_delta / low_depth;
-			
+			low_depth      = limit_depth;
+			locked_GF_step = GF_delta / low_depth;
+
 			// store updated GF parameters dependent on current plan
 			if( char_O_deco_status & DECO_PLAN_ALTERNATE )
 			{
@@ -769,7 +922,7 @@
 				low_depth_norm      = low_depth;
 				locked_GF_step_norm = locked_GF_step;
 			}
-        }
+		}
 		else
 		{
 			// recall locked_GF_step dependent on current plan
@@ -777,159 +930,149 @@
 		}
 
 		// invalidate this stop if we can ascent for 1 minute without going above minimum required deco depth
-        if( pres_gradient < min_depth ) goto no_deco_stop;         
-
-		
+		if( limit_depth < min_depth ) goto no_deco_stop;
+
+
 		// if program execution passes here, we need a deco stop
-		
-        // Round to multiple of 3 meters
-        first_stop = 3 * (unsigned char)(0.9995 + pres_gradient * 0.333333);
+
+		// Round to multiple of 3 meters
+		first_stop = 3 * (unsigned char)(0.9995 + limit_depth * 0.333333);
 
 		// check a constraint
-        assert( first_stop < 128 );
-
-        // apply correction for the shallowest stop, use char_I_depth_last_deco (3..6 m) instead
-        if( first_stop == 3 ) first_stop = char_I_depth_last_deco;
-
-        // We have a stop candidate.
-        // But maybe ascending to the next stop will diminish the constraint,
-        // because the GF might decrease more than the pressure gradient...
-        while(first_stop > 0)
-        {
+		assert( first_stop < 128 );
+
+		// apply correction for the shallowest stop, use char_I_depth_last_deco (3..6 m) instead
+		if( first_stop == 3 ) first_stop = char_I_depth_last_deco;
+
+		// We have a stop candidate.
+		// But maybe ascending to the next stop will diminish the constraint,
+		// because the GF might decrease more than the pressure gradient...
+		while(first_stop > 0)
+		{
 			// Next depth
-            overlay unsigned char next_stop;            
-
-            // invalidate this stop if we can ascent one more minute without going above minimum required deco depth
-            if( first_stop <= (unsigned char)min_depth ) goto no_deco_stop;
+			overlay unsigned char next_stop;
+
+			// invalidate this stop if we can ascent one more minute without going above minimum required deco depth
+			if( first_stop <= (unsigned char)min_depth ) goto no_deco_stop;
 
 			// compute depth of next stop
-            if      ( first_stop <= char_I_depth_last_deco ) next_stop = 0;
-            else if ( first_stop == 6                      ) next_stop = char_I_depth_last_deco;
-            else                                             next_stop = first_stop - 3;
-
-            // compute total pressure at the new stop candidate
-            pres_gradient = next_stop * METER_TO_BAR + pres_surface;
-
-            // compute limit for the new stop candidate
-            if( (low_depth == 0.0) || (next_stop > low_depth) ) sim_limit( GF_low );
-            else                                                sim_limit( GF_high - next_stop * locked_GF_step );
-
-            // check if ascent to the next stop candidate is possible
-            if( sim_lead_tissue_limit >= pres_gradient ) goto deco_stop_found;	// no - ascent to next_stop forbidden
-
-            // else, validate that stop and loop...
-            first_stop = next_stop;
-        }
+			if      ( first_stop <= char_I_depth_last_deco ) next_stop = 0;
+			else if ( first_stop == 6                      ) next_stop = char_I_depth_last_deco;
+			else                                             next_stop = first_stop - 3;
+
+			// compute limit with the GF of the new stop candidate
+			if( (low_depth == 0.0) || (next_stop > low_depth) ) calc_limit(GF_low);
+			else                                                calc_limit(GF_high - next_stop * locked_GF_step);
+
+			// check if ascent to the next stop candidate is possible
+			if( sim_ceiling * BAR_TO_METER >= next_stop ) goto deco_stop_found;	// no - ascent to next_stop forbidden
+
+			// else, validate that stop and loop...
+			first_stop = next_stop;
+		}
 
 no_deco_stop:
-		need_stop        = 0;              				// set flag for stop needed to 'no'
-		temp_depth_limit = (unsigned char)min_depth;	// report depth we can ascent to without stop
+		need_stop       = 0;							// set flag for stop needed to 'no'
+		sim_depth_limit = (unsigned char)min_depth;		// report depth we can ascent to without stop
 		goto done;
 
 deco_stop_found:
-		need_stop        = 1;              				// set flag for stop needed to 'yes'
-		temp_depth_limit = (unsigned char)first_stop;	// stop depth, in meters
+		need_stop       = 1;							// set flag for stop needed to 'yes'
+		sim_depth_limit = (unsigned char)first_stop;	// stop depth, in meters
 
 done:
-        ;
-    }
-    else
-    {
+		;
+	}
+	else
+	{
 		//---- ZH-L16 model -------------------------------------------------
-		
-        overlay float pres_gradient;
-
-		
-        // calculate minimum depth we can ascent to in absolute pressure
-        sim_limit(1.0);
-
-		// ...and convert the depth into relative pressure 
-        pres_gradient = sim_lead_tissue_limit - pres_surface;
+
+		overlay float limit_depth;
+
+
+		// calculate minimum depth we can ascent to in bar relative pressure
+		calc_limit(1.0);
 
 		// check if we can surface directly
-        if (pres_gradient >= 0)
-        {
+		if (sim_ceiling >= 0)
+		{
 			// no - set flag for stop needed to 'yes'
-            need_stop = 1;
+			need_stop = 1;
 
 			// convert stop depth in relative pressure to stop index
-            pres_gradient *= BAR_TO_METER / 3;
+			limit_depth = sim_ceiling * BAR_TO_METER / 3;
 
 			// convert stop index to depth in meters, rounded to multiple of 3 meters
-            temp_depth_limit = 3 * (short) (pres_gradient + 0.99);
-
-            // correct last stop to 4m/5m/6m
-            if( temp_depth_limit == 3 ) temp_depth_limit = char_I_depth_last_deco;
-        }
-        else
+			sim_depth_limit = 3 * (short)(limit_depth + 0.99);
+
+			// correct last stop to 4m/5m/6m
+			if( sim_depth_limit == 3 ) sim_depth_limit = char_I_depth_last_deco;
+		}
+		else
 		{
 			// yes - set flag for stop needed to 'no'
-			need_stop        = 0;
+			need_stop       = 0;
 			
 			// set depth we can ascent to as 0 = surface
-            temp_depth_limit = 0;
+			sim_depth_limit = 0;
 		}
-    }
-
-	
+	}
+
 	// After the first deco stop, gas changes are only done at deco stops now!
-	
+
 	// check if a stop is found and there is a better gas to switch to
 	if( need_stop && gas_find_better() )
 	{
 		// set the new calculation ratios for N2, He and O2
-		gas_switch_set();
+		gas_set_ratios();
 
 		// prime the deco stop with the gas change time
 		update_deco_table(char_I_gas_change_time); 
 	}
 
-    return need_stop;
+	return need_stop;
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// copy_deco_table
+// publish_deco_table
 //
 // Buffer the stops, once computed, so we can continue to display them
 // while computing the next set.
 //
-static void copy_deco_table(void)
+static void publish_deco_table(void)
 {
-    // Copy depth of the first (deepest) stop, because when reversing
-    // order, it will be hard to find...
-    char_O_first_deco_depth = internal_deco_depth[0];
-    char_O_first_deco_time  = internal_deco_time [0];
-
-    {
-        overlay unsigned char x, y;
-
-        for(x=0; x<NUM_STOPS; x++)
-        {
-            char_O_deco_depth[x] = internal_deco_depth[x];
-            char_O_deco_time [x] = internal_deco_time [x];
-            char_O_deco_gas  [x] = internal_deco_gas  [x];
-        }
-
-        //Now fill the char_O_deco_time_for_log array
-        //---- First: search the first non-null depth
-        for(x=(NUM_STOPS-1); x != 0; --x)
-            if( internal_deco_depth[x] != 0 ) break;
-
-        //---- Second: copy to output table (in reverse order)
-        for(y=0; y<NUM_STOPS; y++, --x)
-        {
-            char_O_deco_time_for_log[y] = internal_deco_time [x];
-
-            // Stop only once the last transfer is done.
-            if( x == 0 ) break;
-        }
-
-        //---- Third: fill table end with null
-        for(y++; y<NUM_STOPS; y++)
-        {
-            char_O_deco_time_for_log[y] = 0;
-        }
-    }
+	overlay unsigned char x, y;
+
+
+	// Copy depth of the first (deepest) stop, because when reversing
+	// order, it will be hard to find...
+	char_O_first_deco_depth = internal_deco_depth[0];
+	char_O_first_deco_time  = internal_deco_time [0];
+
+	for(x=0; x<NUM_STOPS; x++)
+	{
+		char_O_deco_depth[x] = internal_deco_depth[x];
+		char_O_deco_time [x] = internal_deco_time [x];
+		char_O_deco_gas  [x] = internal_deco_gas  [x];
+	}
+
+	//Now fill the char_O_deco_time_for_log array
+	//---- First: search the first non-null depth
+	for(x=(NUM_STOPS-1); x != 0; --x)
+		if( internal_deco_depth[x] != 0 ) break;
+
+	//---- Second: copy to output table (in reverse order)
+	for(y=0; y<NUM_STOPS; y++, --x)
+	{
+		char_O_deco_time_for_log[y] = internal_deco_time [x];
+
+		// Stop only once the last transfer is done.
+		if( x == 0 ) break;
+	}
+
+	//---- Third: fill table with null until end
+	for(y++; y<NUM_STOPS; y++)
+		char_O_deco_time_for_log[y] = 0;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -941,91 +1084,13 @@
 //
 static void temp_tissue_safety(void)
 {
-    assert( 0.0 <  float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 );
-    assert( 1.0 <= float_saturation_multiplier   && float_saturation_multiplier   <= 2.0 );
+	assert( 0.0 <  float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 );
+	assert( 1.0 <= float_saturation_multiplier   && float_saturation_multiplier   <= 2.0 );
 
 	if( temp_tissue < 0.0 ) temp_tissue *= float_desaturation_multiplier;
 	else                    temp_tissue *= float_saturation_multiplier;
 }
 
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-// ** THE JUMP-IN CODE **
-// ** for the asm code **
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-//////////////////////////////////////////////////////////////////////////////
-// Called every second during diving.
-// updates tissues every second invocation.
-//
-// Every few seconds (or slower when TTS > 16):
-//    - updates deco table (char_O_deco_time/depth) with new values.
-//    - updates ascent time,
-//    - sets status to zero (so we can check there is new results).
-//
-void deco_calc_hauptroutine(void)
-{
-    RESET_C_STACK
-    calc_hauptroutine();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Reset decompression model:
-// + Set all tissues to equilibrium with Air at ambient pressure.
-// + Reset last stop to 0m
-// + Reset all model output.
-void deco_clear_tissue(void)
-{
-    RESET_C_STACK
-    clear_tissue();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void deco_calc_wo_deco_step_1_min(void)
-{
-    RESET_C_STACK
-    calc_wo_deco_step_1_min();
- }
-
-//////////////////////////////////////////////////////////////////////////////
-
-void deco_calc_desaturation_time(void)
-{
-    RESET_C_STACK
-    calc_desaturation_time();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void deco_calc_dive_interval(void)
-{
-    RESET_C_STACK
-    calc_dive_interval();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// deco_calc_CNS_decrease_15min
-//
-// new in v.101
-//
-// calculates the half time of 90 minutes in 6 steps of 15 min
-// (Used in sleep mode, for low battery mode).
-//
-// Output: int_O_CNS_fraction
-// Uses and Updates: CNS_fraction
-//
-void deco_calc_CNS_decrease_15min(void)
-{
-    RESET_C_STACK
- 
-	// clock down CNS
-    CNS_fraction =  0.890899 * CNS_fraction;
-	
-	// compute integer copy of CNS value
-	compute_CNS_for_display();
-}
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1038,21 +1103,21 @@
 //
 static void gas_find_current(void)
 {
-    assert( 1 <= char_I_current_gas && char_I_current_gas <= 6 );
-
-    if( char_I_current_gas <= NUM_GAS )					// Gas 1-5
-    {
-        sim_gas_last_used = sim_gas_first_used = char_I_current_gas;
-
-        // If current gas is a deco gas get it's change depth.
+	assert( 1 <= char_I_current_gas && char_I_current_gas <= 6 );
+
+	if( char_I_current_gas <= NUM_GAS )					// Gas 1-5
+	{
+		sim_gas_last_used = sim_gas_first_used = char_I_current_gas;
+
+		// If current gas is a deco gas get it's change depth.
 		// Set change depth to 0 if the current gas is the first gas or 
 		// a travel/normal gas, i.e. if it can be breathed at "any" depth.
-        if( char_I_deco_gas_change[sim_gas_last_used-1] ) sim_gas_last_depth = char_I_deco_gas_change[sim_gas_last_used-1];
+		if( char_I_deco_gas_change[sim_gas_last_used-1] ) sim_gas_last_depth = char_I_deco_gas_change[sim_gas_last_used-1];
 		else                                              sim_gas_last_depth = 0;
-    }
-    else
+	}
+	else
 	{
-        sim_gas_last_used = sim_gas_first_used = 0;		// Gas 6 (the manually set one) has number 0 here
+		sim_gas_last_used = sim_gas_first_used = 0;		// Gas 6 (the manually set one) has number 0 here
 		sim_gas_last_depth                     = 0;		// handle it as a travel/normal gas
 	}
 }
@@ -1061,9 +1126,9 @@
 //////////////////////////////////////////////////////////////////////////////
 // Find the deco gas with the shallowest change depth beyond current depth
 //
-// INPUT   temp_depth_limit	        : current depth in meters
+// INPUT   sim_depth_limit          : current depth in meters
 //         char_I_deco_gas_change[] : change depths of the deco gases
-//		   sim_gas_last_depth       : change depth of the currently used gas, 0 if on the gas set as FIRST
+//         sim_gas_last_depth       : change depth of the currently used gas, 0 if on the gas set as FIRST
 //
 // OUTPUT  sim_gas_last_depth       : switch depth            - only if return value is true
 //         sim_gas_last_used        : index of the gas (1..5) - only if return value is true
@@ -1075,8 +1140,8 @@
 	overlay unsigned char switch_depth = 255;
 	overlay unsigned char switch_gas   = 0;
 	overlay unsigned char j;
-	
-	
+
+
 	// no automatic gas changes in CCR mode and - as of now - in pSCR mode
 	if( char_O_deco_status & DECO_MODE_LOOP ) return 0;
 
@@ -1091,7 +1156,7 @@
 		// If yes, skip this gas as it is not to be used yet.
 		// Remark: this check will also skip all disabled gases and the gas set
 		//         as 'first' because these have their change depth set to 0.
-		if( temp_depth_limit > char_I_deco_gas_change[j] ) continue;
+		if( sim_depth_limit > char_I_deco_gas_change[j] ) continue;
 
 		// Is the change depth of the gas deeper than the change depth of the
 		// gas we are currently one?
@@ -1118,7 +1183,7 @@
 		sim_gas_last_depth = switch_depth;				// report its change depth
 
 		assert( sim_gas_last_depth < switch_depth );
-		
+
 		return 1;										// signal a better gas was found
 	}
 	else
@@ -1130,144 +1195,210 @@
 //////////////////////////////////////////////////////////////////////////////
 // Set calc_N2/He/O2_ratios by sim_gas_last_used
 //
-// Input:  sim_gas_last_used  : index of gas to use
-//         N2_ratio, He_ratio : if gas 0 = the manually set gas is in use
+// Input:  sim_gas_last_used          : index of gas to use
+//         N2_ratio, He_ratio         : if gas =    0 (the manually set gas)
+//         char_I_deco_O2/He_ratio[]  : if gas = 1..5 (the configured gases)
 //
-// Output: calc_N2_ratio, calc_He_ratio, calc_O2ratio
+// Output: sim_N2_ratio, sim_He_ratio : ratios of the inert gases
+//         sim_pSCR_drop              : ppO2 drop in pSCR loop
 //
-static void gas_switch_set(void)
+static void gas_set_ratios(void)
 {
+	overlay float sim_IG_ratio;
+
 	assert( 0 <= sim_gas_last_used <= NUM_GAS );
 
-	if( sim_gas_last_used == 0 )    // Gas6 = manually set gas.
+
+	// get gas ratios
+	if( sim_gas_last_used == 0 )
 	{
-		calc_O2_ratio = O2_ratio;
-		calc_He_ratio = He_ratio;
+		sim_O2_ratio = O2_ratio;
+		sim_He_ratio = He_ratio;
 	}
 	else
 	{
-	calc_O2_ratio = char_I_deco_O2_ratio[sim_gas_last_used-1] * 0.01;
-	calc_He_ratio = char_I_deco_He_ratio[sim_gas_last_used-1] * 0.01;
+		sim_O2_ratio = 0.01 * char_I_deco_O2_ratio[sim_gas_last_used-1];
+		sim_He_ratio = 0.01 * char_I_deco_He_ratio[sim_gas_last_used-1];
 	}
 
-	calc_N2_ratio = 1.0 - calc_O2_ratio - calc_He_ratio;
-
-	assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 );
-	assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 1.00 );
-	assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 );
+	// inert gas ratio (local helper variable)
+	sim_IG_ratio     = 1.00 - sim_O2_ratio;
+
+	// N2 ratio
+	sim_N2_ratio     = sim_IG_ratio - sim_He_ratio;
+
+	// ppO2 drop in pSCR loop
+	sim_pSCR_drop    = sim_IG_ratio * float_pSCR_factor;
+
+
+	assert( 0.0 <=  sim_N2_ratio && sim_N2_ratio  <= 0.95 );
+	assert( 0.0 <=  sim_He_ratio && sim_He_ratio  <= 0.95 );
+	assert(        (sim_N2_ratio +  sim_He_ratio) <= 0.95 );
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// Compute ppN2 and ppHe
+// Compute respired ppN2 and ppHe
 //
-// Input: calc_N2_ratio, calc_He_ratio : simulated gas mix.
-//        temp_deco                    : simulated respiration pressure
-//        float_deco_distance          : safety factor
-//        ppWater                      : water-vapor pressure inside respiratory tract
+// Input:  tissue_increment       : selector for targeting simulated or real tissues
+//         char_O_main_status     : breathing mode for real      tissues
+//         char_O_deco_status     : breathing mode for simulated tissues
+//         (sim_)O2_ratio         : (simulated) O2 ratio breathed
+//         (sim_)N2_ratio         : (simulated) N2 ratio breathed
+//         (sim_)He_ratio         : (simulated) He ratio breathed
+//         (sim_)pres_respiration : (simulated) respiration pressure
+//         char_I_const_ppO2      : ppO2 reported from sensors or setpoint
+//         char_I_PSCR_drop       : pSCR parameter
+//         char_I_PSCR_lungratio  : pSCR parameter
+//         pres_surface           : surface pressure
+//         float_deco_distance    : safety factor
+//         ppWater                : water-vapor pressure inside respiratory tract
 //
-// Output: ppN2, ppHe.
+// Output: ppN2                   : respired N2 partial pressure
+//         ppHe                   : respired He partial pressure
 //
-static void sim_alveolar_presures(void)
+void calc_alveolar_pressures(void)
 {
-    overlay float deco_diluent = temp_deco;
-	
-	// read ppO2 reported from sensors or by setpoint		// TODO: can be deleted
-	// char_actual_ppO2 = char_I_const_ppO2;
-
-
-    // Take deco offset into account, but not at surface.
-    // Note: this should be done on ambient pressure, hence before
-    //       computing the diluent partial pressure...
-    if( deco_diluent > pres_surface ) deco_diluent += float_deco_distance;
-
-	if( char_O_deco_status & DECO_MODE_LOOP )
-    {
-		//---- Loop mode : adjust ppN2 and ppHe for change in ppO2 due to setpoint (CCR) or drop (pSCR)-------
-
-		// get current setpoint (CCR) or sensor value (CCR, for pSCR see text below) as default
-		overlay float const_ppO2 = char_I_const_ppO2 * 0.01;
-		
-		if( char_O_deco_status & DECO_MODE_PSCR )
+	overlay float pres_diluent;
+	overlay float calc_O2_ratio;
+	overlay float calc_N2_ratio;
+	overlay float calc_He_ratio;
+	overlay float calc_pSCR_drop;
+
+	overlay unsigned char status;
+
+
+	assert( 0.00 <= N2_ratio && N2_ratio <= 1.00 );
+	assert( 0.00 <= He_ratio && He_ratio <= 1.00 );
+	assert( (N2_ratio + He_ratio) <= 1.00 );
+	assert( 0.800 < pres_respiration && pres_respiration < 14.0 );
+
+	assert( 0.00 <= sim_N2_ratio && N2_ratio <= 1.00 );
+	assert( 0.00 <= sim_He_ratio && He_ratio <= 1.00 );
+	assert( (sim_N2_ratio + sim_He_ratio) <= 1.00 );
+	assert( 0.800 < sim_pres_respiration && sim_pres_respiration < 14.0 );
+
+
+	// get input data according to context
+	if( tissue_increment & TISSUE_FLAG )
+	{
+		//---- real tissues -----------------------------------------------------------
+		status         = char_O_main_status;
+		pres_diluent   = pres_respiration;
+		calc_pSCR_drop = pSCR_drop;
+
+		calc_O2_ratio  = O2_ratio;
+		calc_N2_ratio  = N2_ratio;
+		calc_He_ratio  = He_ratio;
+	}
+	else
+	{
+		//---- simulated tissues ------------------------------------------------------
+		status         = char_O_deco_status;
+		pres_diluent   = sim_pres_respiration;
+		calc_pSCR_drop = sim_pSCR_drop;
+
+		calc_O2_ratio  = sim_O2_ratio;
+		calc_N2_ratio  = sim_N2_ratio;
+		calc_He_ratio  = sim_He_ratio;
+
+		// take deco offset into account, but not at surface
+		if( pres_diluent > pres_surface ) pres_diluent += float_deco_distance;
+	}
+
+	//---- OC, CCR and Bailout Mode Gas Calculations -----------------------------------
+
+	// calculate ppO2 of pure oxygen
+	O2_ppO2 = (pres_diluent - ppWater);
+
+	// capture failure condition in case pres_respiration is < ppWater (should never happen...)
+	if( O2_ppO2 < 0.0 ) O2_ppO2 = 0.0;
+
+	// calculate ppO2 of the pure gas (diluent)
+	OC_ppO2 = O2_ppO2 * calc_O2_ratio;
+
+	// calculate pSCR ppO2
+	pSCR_ppO2 = OC_ppO2 - calc_pSCR_drop;
+
+	// capture failure condition in case pSCR_ppO2 becomes negative
+	if( pSCR_ppO2 < 0.0 ) pSCR_ppO2 = 0.0;
+
+
+	//---- Loop modes : adjust ppN2 and ppHe for change in ppO2 due to setpoint (CCR) or drop (pSCR) ---
+	if( status & DECO_MODE_LOOP )
+	{
+		overlay float const_ppO2;
+
+		// get the current sensor reading (CCR / pSCR if fitted) or the fixed setpoint (CCR) / a zero (pSCR)
+		const_ppO2 = 0.01 * char_I_const_ppO2;
+
+		// Limit the setpoint to the maximum physically possible ppO2. This prevents for
+		// example calculating with a setpoint of 1.3 bar in only 2 meters of depth.
+		// Additionally, if limiting occurs, the ppO2 can be further reduced to account
+		// for residual inert gases by the user-adjustable setting char_I_cc_max_frac_o2.
+
+		if( const_ppO2 > pres_diluent )		// no ppWater subtracted here to give some margin for
+		{									// sensors delivering data a little bit over target
+			const_ppO2 = 0.01 * char_I_cc_max_frac_o2 * (pres_diluent - ppWater);
+		}
+
+		// check which kind of loop we are on
+		if( status & DECO_MODE_PSCR )
 		{
-			//---- PSCR mode : compute loop gas ----------------------------------------
-			//
-			// As the ppO2 in the loop changes with water depth, we can not use the current
-			// sensor value as with CCR mode, but need to compute the ppO2 for the given depth.
-			// Then we continue with the CCR mode code which calculates the increases of ppN2
-			// and ppH2 due to the reduction of the ppO2 in the loop. Essentially, diving a
-			// PSCR is like diving a CCR with a setpoint lower than the ambient pressure x the
-			// O2 fraction of the diluent would yield...
-			//
-
-			// deco_diluent          is 0.0 ...     in bar
-			// calc_O2_ratio         is 0.0 ...   1 as factor
-			// char_I_PSCR_drop      is 0   ...  15 as %
-			// char_I_PSCR_lungratio is 5   ...  20 as %
-			// const_ppO2		     is 0.0 ...     in bar
-
-			const_ppO2 = (deco_diluent * calc_O2_ratio) - (1 - calc_O2_ratio) * 0.01 * char_I_PSCR_drop * char_I_PSCR_lungratio;
-		
-			// capture failure condition
-			if( const_ppO2 < 0.0 ) const_ppO2 = 0.0;
-		}		
+			//---- pSCR Mode --------------------------------------------------------------------------
+
+			// Use the sensor value if available, but only in real tissue context!
+			// In all other cases use calculated ppO2.
+			if( char_I_const_ppO2 && (tissue_increment & TISSUE_FLAG)) ppO2 = const_ppO2;
+			else                                                       ppO2 = pSCR_ppO2;
+		}
 		else
 		{
-			
-			//---- CCR mode ------------------------------------------------------------ 
-		
-			// Limit the setpoint to the maximum physically possible ppO2. This prevents for
-			// example calculating with a setpoint of 1.3 bar in only 2 meters of depth.
-			// Additionally, if limiting occurs, the ppO2 can be further reduced to account
-			// for residual inert gases by the user-adjustable setting char_I_cc_max_frac_o2.
-		
-			if( const_ppO2 > deco_diluent )		// no ppWater subtracted here to give some margin for
-			{										// sensors delivering data a little bit over target
-			
-				const_ppO2 = 0.01 * char_I_cc_max_frac_o2 * (deco_diluent - ppWater);
-			}
+			//---- CCR Mode ---------------------------------------------------------------------------
+
+			// derive breathed ppO2 from (char_I_)const_ppO2,
+			// which holds sensor reading or fixed setpoint
+			ppO2 = const_ppO2;
 		}
 
-		if      ( const_ppO2 == 0.0   ) char_actual_ppO2 =   0;
-		else if ( const_ppO2 >  2.545 )	char_actual_ppO2 = 255;
-		else                            char_actual_ppO2 = (unsigned char)(const_ppO2*100 + 0.5);
-
-        // Note: ppO2 and ratios are known outside the lungs, so there is no ppWater in the equations below:
-        deco_diluent -= const_ppO2;
-        deco_diluent /= calc_N2_ratio + calc_He_ratio;
-        
-		// capture all failure conditions, including div/0 in case diluent is pure O2
- 		if( (deco_diluent < 0.0) || (calc_O2_ratio > 99.5) )
+		// adjust diluent pressure (ppN2 + ppHe) for change
+		// in ppO2 due to setpoint (CCR) or drop (pSCR)
+		pres_diluent -= const_ppO2;
+		pres_diluent /= calc_N2_ratio + calc_He_ratio;
+
+		// capture all failure conditions, including div/0
+		// in case diluent is pure O2
+		if( (pres_diluent < 0.0) || (calc_O2_ratio > 99.5) )
 		{
-			deco_diluent = 0.0;
-			
-			char_actual_ppO2 = (unsigned char)(temp_deco*100 + 0.5);	// without float_deco_distance here as this situation
-																		// is likely to occur only at 6 meters or shallower
+			pres_diluent = 0.0;
+			ppO2         = OC_ppO2;
 		}
-    }
-	else 
-	{
-		//---- OC mode: char_actual_ppO2 will be needed for CNS calculation later --------------------------------
-
-		overlay float ppO2 = pres_respiration * calc_O2_ratio;
-		
-		if   ( ppO2 > 2.545 ) char_actual_ppO2 = 255;
-		else                  char_actual_ppO2 = (unsigned char)(ppO2*100 + 0.5);
+	}
+	else
+	{	//---- OC mode ---------------------------------------------------------------------------------
+
+		// breathed ppO2 is ppO2 of pure gas
+		ppO2 = OC_ppO2;
 	}
 
-	
-    if( deco_diluent > ppWater )
-    {
-        ppN2 = calc_N2_ratio * (deco_diluent - ppWater);
-        ppHe = calc_He_ratio * (deco_diluent - ppWater);
-    }
-    else
-    {
-        ppN2 = 0.0;
-        ppHe = 0.0;
-    }
-
-    assert( 0.0 <= ppN2 && ppN2 < 14.0 );
-    assert( 0.0 <= ppHe && ppHe < 14.0 );
+
+	// derive char_ppO2 in [cbar], used for calculating CNS%
+	if      ( ppO2 <  0.01  ) char_ppO2  =   0;
+	else if ( ppO2 >= 2.545 ) char_ppO2  = 255;
+	else                      char_ppO2  = (unsigned char)(100 * ppO2 + 0.5);
+
+
+	//---- calculate ppN2 and ppHe ---------------------------------------------------------------------
+
+	if( pres_diluent > ppWater )
+	{
+		ppN2 = calc_N2_ratio * (pres_diluent - ppWater);
+		ppHe = calc_He_ratio * (pres_diluent - ppWater);
+	}
+	else
+	{
+		ppN2 = 0.0;
+		ppHe = 0.0;
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1276,65 +1407,62 @@
 // optimized in v.101 (var_N2_a)
 //
 // preload tissues with standard pressure for the given ambient pressure.
-// Note: fixed N2_ratio for standard air.
 //
 static void clear_tissue(void)
 {
 	pres_respiration = 0.001  * int_I_pres_respiration;
 	N2_equilibrium   = 0.7902 * (pres_respiration - ppWater);
-	
-    for(ci=0; ci<NUM_COMP; ci++)
-    {
-        // cycle through the 16 Buhlmann N2 tissues
-		pres_tissue_N2[ci] 				= N2_equilibrium;	// initialize data for "real" tissue
+
+	for(ci=0; ci<NUM_COMP; ci++)
+	{
+		// cycle through the 16 Buhlmann N2 tissues
+		pres_tissue_N2[ci]              = N2_equilibrium;	// initialize data for "real" tissue
 		char_O_tissue_N2_saturation[ci] = 11;				// initialize data for tissue graphics
-			
-
-        // cycle through the 16 Buhlmann He tissues
-        pres_tissue_He[ci] 				= 0.0;				// initialize data for "real" tissue
+
+		// cycle through the 16 Buhlmann He tissues
+		pres_tissue_He[ci]              = 0.0;				// initialize data for "real" tissue
 		char_O_tissue_He_saturation[ci] = 0;				// initialize data for tissue graphics
-    }
-
-	clear_CNS_fraction();
-	
-    clear_deco_table();
-	
-	char_O_main_status		= 0;
-    char_O_deco_status		= 0;
-    char_O_nullzeit			= 0;
-	char_O_gtissue_no		= 0;
-	char_O_deco_warnings	= 0;
-
-    int_O_ascenttime		= 0;
-    int_O_gradient_factor	= 0;
-
-	calc_lead_tissue_limit	= 0.0;
+	}
+
+	// reset CNS values
+	CNS_fraction = 0.0;
+	int_O_CNS_fraction = int_O_normal_CNS_fraction = int_O_alternate_CNS_fraction = 0;
+
+
+	// reset any warnings
+	char_O_deco_warnings		= 0;
+
+	// reset some more vars to their defaults
+	char_O_nullzeit				= 240;
+	int_O_ascenttime			= 0;
+	int_O_alternate_ascenttime	= 0;
+	int_O_gradient_factor		= 0;
 }
 
+
 //////////////////////////////////////////////////////////////////////////////
 // calc_hauptroutine
 //
 // this is the major code in dive mode calculates:
-// 		the tissues,
-//		the bottom time,
-//		and simulates the ascend with all deco stops.
-//
+//      the tissues,
+//      the bottom time,
+//      and simulates the ascend with all deco stops.
 //
 static void calc_hauptroutine(void)
 {
-	unsigned int int_ppO2_min;
-	unsigned int int_ppO2_max;
-
+	overlay unsigned int int_ppO2_min;
+	overlay unsigned int int_ppO2_max;
+	overlay unsigned int int_ppO2_max_dil;
 
 	//--- set-up part --------------------------------------------------------------------------------
-	
+
 	// twosectimer:
 	// calc_hauptroutine is now invoked every second to speed up the deco planning.
 	// Because the tissue and CNS calculations are based on a 2 seconds period, the
 	// the following toggle-timer will be used by the respective routines to skip
 	// every 2nd invocation.
 	twosectimer = (twosectimer) ? 0 : 1;			// toggle the toggle-timer
-	
+
 
 	// set up normal tissue updating or "fast forward" updating for simulator sim+5' function
 	// and deco calculator bottom time calculation
@@ -1342,7 +1470,7 @@
 	{
 		// configure char_I_sim_advance_time minutes of tissue updating
 		tissue_increment = char_I_sim_advance_time	// given number of minutes, limited to 127
-						 | 128;						// set flag for updating the "real" tissues & CNS
+						 | TISSUE_FLAG;				// set flag for updating the "real" tissues & CNS
 
 		char_I_sim_advance_time = 0;				// clear "mailbox"
 	}
@@ -1350,337 +1478,390 @@
 	{
 		// configure 2 seconds of tissue updating
 		tissue_increment = 0						// encoding for 2 seconds update
-						 | 128;						// set flag for updating the "real" tissues & CNS
+						 | TISSUE_FLAG;				// set flag for updating the "real" tissues & CNS
 	}
 
+
 	//---- calculate the real tissue's data -----------------------------------------------------------------
-	
-	calc_hauptroutine_data_input();			// acquire current environment data 
-	
-	calc_hauptroutine_update_tissues();		// update tissue pressures, also sets char_actual_ppO2
-	
-	calc_CNS_fraction();					// calculate CNS% for the real tissues
-	
-	compute_CNS_for_display();				// compute integer copy of CNS value for display purpose
-		
-	calc_gradient_factor();					// compute current GF
+
+	// acquire current environment data
+	calc_hauptroutine_data_input();
+
+	// update tissue pressures, also sets char_ppO2 for calc_CNS_increment()
+	calc_hauptroutine_update_tissues();
+
+	// calculate CNS value increment for the real tissues
+	calc_CNS_increment();
+
+	// update the CNS value for the real tissues
+	CNS_fraction += CNS_fraction_inc;
+
+	// compute integer copy of CNS value for display purpose
+	convert_CNS_for_display();
 
 
 	//---- compute ppO2 warnings ------------------------------------------------------------------------------
-	
+
 	// compute conditional min/max values
 	int_ppO2_min = (char_O_main_status   & DECO_MODE_LOOP) ? (unsigned int)char_I_ppO2_min_loop : (unsigned int)char_I_ppO2_min;
 	int_ppO2_max = (char_O_deco_warnings & DECO_FLAG     ) ? (unsigned int)char_I_ppO2_max_deco : (unsigned int)char_I_ppO2_max;
 
+	// default value for the upper diluent ppO2 warning threshold is the normal upper warning threshold
+	int_ppO2_max_dil = int_ppO2_max;
+
+	// when in CCR mode, the upper diluent warning threshold gets adjust according to the current setpoint
+	if( (char_O_main_status & DECO_MODE_MASK) == DECO_MODE_CCR )
+	{
+		overlay unsigned int max_dil;
+
+		//  The upper diluent ppO2 threshold is ppO2_GAP_TO_SETPOINT below the setpoint...
+		// (the condition protects from negative numbers which would cause a wrap-around)
+		max_dil = (char_I_const_ppO2 > ppO2_GAP_TO_SETPOINT) ? (unsigned int)(char_I_const_ppO2 - ppO2_GAP_TO_SETPOINT) : 0;
+
+		// ...but never above int_ppO2_max.
+		if( max_dil < int_ppO2_max ) int_ppO2_max_dil = max_dil;
+
+		// We do not need to guard int_ppO2_max_dil against becoming lower than char_I_ppO2_min because the check
+		// against char_I_ppO2_min is done first and will then raise a low warning and inhibit further checks.
+	}
+
 	// check for safe range of pure oxygen
-	if		( int_O_O2_ppO2   	  >=           int_ppO2_max    ) int_O_O2_ppO2 		 |= INT_FLAG_WARNING + INT_FLAG_HIGH;
+	if		( int_O_O2_ppO2       >=           int_ppO2_max     ) int_O_O2_ppO2       |= INT_FLAG_WARNING + INT_FLAG_HIGH;
 
 	// check for safe range of breathed gas
-	if		( int_O_breathed_ppO2 <=           int_ppO2_min    ) int_O_breathed_ppO2 |= INT_FLAG_WARNING + INT_FLAG_LOW;
-	else if ( int_O_breathed_ppO2 >=           int_ppO2_max    ) int_O_breathed_ppO2 |= INT_FLAG_WARNING + INT_FLAG_HIGH;
-	else if ( char_O_main_status  &            DECO_MODE_LOOP  ) ; // no attention generated in loop modes
-	else if ( int_O_breathed_ppO2 >= ppO2_prewarn_threshold    ) int_O_breathed_ppO2 |= INT_FLAG_PREWARNING;
-		
+	if		( int_O_breathed_ppO2 <=           int_ppO2_min     ) int_O_breathed_ppO2 |= INT_FLAG_WARNING + INT_FLAG_LOW;
+	else if ( int_O_breathed_ppO2 >=           int_ppO2_max     ) int_O_breathed_ppO2 |= INT_FLAG_WARNING + INT_FLAG_HIGH;
+	else if ( char_O_main_status  &            DECO_MODE_LOOP   ) ; // no attention generated in loop modes
+	else if ( int_O_breathed_ppO2 >=   ppO2_ATTENTION_THRESHOLD ) int_O_breathed_ppO2 |= INT_FLAG_ATTENTION;
+
 	// check for safe range of pure diluent
-	if		( int_O_pure_ppO2 <= (unsigned int)char_I_ppO2_min ) int_O_pure_ppO2 	 |= INT_FLAG_WARNING + INT_FLAG_LOW;
-	else if	( int_O_pure_ppO2 >=               int_ppO2_max    ) int_O_pure_ppO2 	 |= INT_FLAG_WARNING + INT_FLAG_HIGH;
-		
+	if		( int_O_pure_ppO2 <= (unsigned int)char_I_ppO2_min  ) int_O_pure_ppO2     |= INT_FLAG_WARNING + INT_FLAG_LOW;
+	else if ( int_O_pure_ppO2 >=               int_ppO2_max     ) int_O_pure_ppO2     |= INT_FLAG_WARNING + INT_FLAG_HIGH;
+	else if ( int_O_pure_ppO2 >=               int_ppO2_max_dil ) int_O_pure_ppO2     |= INT_FLAG_ATTENTION;
+
 	// check for safe range of calculated pSCR loop gas
-	if		( int_O_pSCR_ppO2 <=               int_ppO2_min    ) int_O_pSCR_ppO2 	 |= INT_FLAG_WARNING + INT_FLAG_LOW;
-	else if	( int_O_pSCR_ppO2 >=               int_ppO2_max    ) int_O_pSCR_ppO2 	 |= INT_FLAG_WARNING + INT_FLAG_HIGH;
-	
-
-    //---- toggle between calculation for NDL (bottom time), deco stops and more deco stops (continue) ------
-
+	if		( int_O_pSCR_ppO2 <=               int_ppO2_min     ) int_O_pSCR_ppO2     |= INT_FLAG_WARNING + INT_FLAG_LOW;
+	else if ( int_O_pSCR_ppO2 >=               int_ppO2_max     ) int_O_pSCR_ppO2     |= INT_FLAG_WARNING + INT_FLAG_HIGH;
+
+
+
+	//---- toggle between calculation for NDL (bottom time),  ------
+	//---- deco stops and more deco stops (continue)          ------
+
+
+	// done with the real tissues, all following operations
+	// target the simulated tissues so clear flag in bit 7
+	tissue_increment = 0;
+
+	// branch to the code for the current phase the deco calculations are in
 	switch( char_O_deco_status & DECO_STATUS_MASK )
-    {
+	{
 		overlay unsigned char i;
 
-	case DECO_STATUS_INIT: //---- At surface: start a new dive ---------------------
-
+	case DECO_STATUS_INIT: //---- At surface: Start a new dive ---------------------
+
+		// clear the internal stops table from remains lasting from the last dive
 		clear_deco_table();
-        copy_deco_table();
-
-
-		char_I_gas_change_time = 1;		// TODO: validate proper operation before enabling this options-table parameter		
-
-		char_I_ascent_speed    = 10;	// TODO: validate proper operation before enabling this options-table parameter,
-										//       caution: values < 10 may have an impact on the deco calculation run-times!
-
-		
-		float_ascent_speed            = 1.00 * char_I_ascent_speed;
-		float_desaturation_multiplier = 0.01 * char_I_desaturation_multiplier;
-		float_saturation_multiplier   = 0.01 * char_I_saturation_multiplier;
-		float_deco_distance           = 0.01 * char_I_deco_distance;
-		
-        int_O_ascenttime			  = 0;		// reset ascent time in normal plan
-		int_O_alternate_ascenttime    = 0; 		// reset ascent time in alternative plan
-		char_O_nullzeit               = 0;		// reset no decompression limit (NDL) in normal plan
-		char_O_alternate_nullzeit     = 0;		// reset no decompression limit (NDL) in alternative plan
-		char_O_deco_warnings          = 0;		// reset all deco warning flags
-		deco_tissue_vector		      = 0;		// reset tissue deco vector
-		IBCD_tissue_vector            = 0;		// reset tissue IBCD vector
-		
-		int_O_desaturation_time       = 65535;	// tag desaturation time as invalid (it will not be computed during a dive)
-		
-
+
+		// publish the cleared stops table to the display functions
+		publish_deco_table();
+
+		// clear the gas needs table
 		for(i=0; i<NUM_GAS; ++i)
 		{
 			int_O_gas_volumes[i]    = 0;
-			int_O_tank_pres_need[i] = 0 + INT_FLAG_ZERO;	// 0 bar + flag for 0 bar
+			int_O_tank_pres_need[i] = 0 + INT_FLAG_ZERO;
 		}
 
+		// initialize the balancing between N2 and He for later no-fly time calculation
 		for(i=0; i<NUM_COMP; ++i)
-		{		
-			split_N2_He[i] = 90;							// used for calculation of no-fly time
+		{
+			split_N2_He[i] = 90;	// assumes 90% of total tissue pressure will be needed for N2
 		}
 		
-		
-		// init CNS counters
-		CNS_sim_norm_fraction     = CNS_sim_alt_fraction         = CNS_fraction;		// the floats
-		int_O_normal_CNS_fraction = int_O_alternate_CNS_fraction = int_O_CNS_fraction;	// the integers
-
-		
-        // Values that should be reset just once for the full real dive.
-        // This is used to record the lowest stop for the whole dive,
-        // including ACCROSS all simulated ascents.
-        low_depth_norm      = low_depth_alt      = 0.0;
-        locked_GF_step_norm = locked_GF_step_alt = 0.0;
-
-
-		// continue in state DECO_STATUS_START to calculate the bottom-part of the dive and the NDL
-		char_O_deco_status &= ~DECO_STATUS_MASK;	
-		
-		// code execution continues in state DECO_STATUS_START
-		
-		
-	case DECO_STATUS_START: //---- bottom time -------------------------------------
-    default:
-
-		// reread the GF settings in case there was a switch between GF/aGF
-		GF_low   = char_I_GF_Low_percentage  * 0.01;
-		GF_high  = char_I_GF_High_percentage * 0.01;
-		GF_delta = GF_high - GF_low;
-
-        // Lookup current gas and store it also as the first gas used. This gas will be used for the bottom
-		// segment of the dive and for the period of delayed ascent when calculating fTTS or bailout.
-		gas_find_current();		
-		
-		// setup the calculation ratio's calc_N2_ratio, calc_He_ratio and calc_O2_ratio
-        gas_switch_set();		
-
-		// calculate ppN2 and ppHe from calc_N2_ratio & calc_He_ratio
-		sim_alveolar_presures();
+		// ** UNDER CONSTRUCTION - temporary code only **
+		char_I_gas_change_time = 1;		// TODO: validate proper operation before enabling this options-table parameter		
+		char_I_ascent_speed    = 10;	// TODO: validate proper operation before enabling this options-table parameter,
+										//       caution: values < 10 may have an impact on the deco calculation run-times!
+
+		// initialize values that are constant during the course of the dive
+		float_ascent_speed            = 1.00  * char_I_ascent_speed;
+		float_desaturation_multiplier = 0.01  * char_I_desaturation_multiplier;
+		float_saturation_multiplier   = 0.01  * char_I_saturation_multiplier;
+		float_deco_distance           = 0.01  * char_I_deco_distance;
+
+		// initialize values that will be recalculated later on periodically
+		char_O_nullzeit               = 0;	// reset NDL time for the normal plan
+		char_O_alternate_nullzeit     = 0;	// reset NDL time for the alternative plan
+		int_O_ascenttime              = 0;	// reset ascent time for the normal plan
+		int_O_alternate_ascenttime    = 0;	// reset ascent time for the alternative plan
+		char_O_deco_warnings          = 0;	// reset all deco warnings
+		deco_tissue_vector            = 0;	// reset tissue deco vector
+		IBCD_tissue_vector            = 0;	// reset tissue IBCD vector
+		NDL_lead_tissue               = 0;	// reset first tissue to look at during NDL calculation
+
+		// tag desaturation time as invalid (it will not be computed during a dive)
+		int_O_desaturation_time       = 65535;
+
+		// initialize CNS values
+		int_O_normal_CNS_fraction = int_O_alternate_CNS_fraction = int_O_CNS_fraction;
+
+		// Values that should be reset just once for the full real dive.
+		// This is used to record the lowest stop for the whole dive,
+		// including ACCROSS all simulated ascents.
+		low_depth_norm      = low_depth_alt      = 0.0;
+		locked_GF_step_norm = locked_GF_step_alt = 0.0;
+
+		//
+		// --> code execution continues in state DECO_STATUS_START
+		//
+
+	case DECO_STATUS_START: //---- Bottom Time & initial Ascent --------------------
+	default:
 
 		// clear the internal(!) stops table
-		clear_deco_table();		
+		clear_deco_table();
 		
 		// initialize the simulated tissues with the current state of the real tissues
-		update_startvalues();	
-
-		// calculate the effect of extended bottom time due to delayed ascent / fTTS on current gas
-		if( char_O_deco_status & DECO_ASCENT_DELAYED ) sim_extra_time();
-		
-		// calculate if we are within no decompression limit (NDL)
-        calc_nullzeit();
-
-		// check which plan we are on
-		if( char_O_deco_status & DECO_PLAN_ALTERNATE )
+		for(i=0; i<NUM_COMP; i++)
 		{
-			//---- alternate dive plan --------------------------------------------------------------------
-			
-			// Some NDL time left in alternate plan?
-			if( char_O_alternate_nullzeit > 0 )
-			{
-				// clear tank pressure needs
-				if( char_O_deco_status & DECO_VOLUME_CALCULATE )
-					for(i=0; i<NUM_GAS; ++i) int_O_tank_pres_need[i] = 0 + INT_FLAG_ZERO; // 0 bar + flag for 0 bar
-
-				// calculate the CNS% at the end of the dive if requested:
-				// as we are in no stop, CNS at end of dive is more or less the same CNS we have now
-				if( char_O_deco_status & DECO_CNS_CALCULATE ) int_O_alternate_CNS_fraction = int_O_CNS_fraction;
-				
-				// clear fTTS ascent time
-				int_O_alternate_ascenttime = 0;
-
-				// YES - computation of alternate plan completed
-				char_O_deco_status &= ~DECO_STATUS_MASK;
-			}
-			else
-			{
-				// NO - clear status bits and set status bits for
-				//      calculation of ascent on next invocation
-				char_O_deco_status &= ~DECO_STATUS_MASK;
-				char_O_deco_status |=  DECO_STATUS_ASCENT;
-			}
+			sim_pres_tissue_N2[i] = pres_tissue_N2[i];
+			sim_pres_tissue_He[i] = pres_tissue_He[i];
+		}
+
+		// Lookup the current gas and store it also as the first gas used.
+		// This gas will be used for the bottom segment of the dive and for
+		// the period of delayed ascent when calculating fTTS or bailout.
+		gas_find_current();
+
+		// setup the calculation ratio's for N2, He and O2 (sim_N2/He/O2_ratio)
+		gas_set_ratios();
+
+		// initialize depth in absolute pressure, it is needed by
+		// - calc_alveolar_pressures(),
+		// - calc_ascent_to_first_stop(), and
+		// - calc_hauptroutine_calc_deco()
+		sim_pres_respiration = pres_respiration;
+
+		// calculate ppN2 and ppHe from sim_N2/He_ratio (<- tissue_increment has been set to 0)
+		calc_alveolar_pressures();
+
+		// calculate the effect of extended bottom time due to delayed ascent
+		if( char_O_deco_status & DECO_ASCENT_DELAYED )
+		{
+			// program interval on simulated tissues (flag bit 7 = 0)
+			tissue_increment = char_I_extra_time;
+
+			// update the tissues
+			calc_tissues();
+		}
+
+		// calculate if we are within no decompression limit (NDL)
+		calc_NDL_time();
+
+		// Calculate the initial ascent if in deco. calc_NDL_time() is very fast
+		// in detecting being beyond NDL, so there is enough time left in this
+		// phase to do the initial ascent calculation.
+		if( NDL_time == 0 )
+		{
+			//--- in deco --------------------------------------------------------
+
+			// calculate ascent to first stop
+			calc_ascent_to_first_stop();
+
+			// continue with calculating the stops
+			char_O_deco_status &= ~DECO_STATUS_MASK;	// clear status bits and set status bits for
+			char_O_deco_status |=  DECO_STATUS_STOPS;	// calculation of stops on next invocation
 		}
 		else
 		{
-			//---- normal dive plan -------------------------------------------------------------------------
-			
-			// Some NDL time left in normal plan?
-			if( char_O_nullzeit > 0 )
+			//--- within NDL -----------------------------------------------------
+
+			// continue with gathering all results
+			char_O_deco_status &= ~DECO_STATUS_MASK;
+			char_O_deco_status |=  DECO_STATUS_RESULTS;
+		}
+
+		break;
+
+
+	case DECO_STATUS_STOPS: //---- Calculate Stops ---------------------------------
+
+		// calculate the stops
+		calc_hauptroutine_calc_deco();
+
+		// calc_hauptroutine_calc_deco iterates in this phase as long as it is
+		// calculating the stops. Once done, it will set the status to doing the
+		// results gathering.
+
+		break;
+
+
+	case DECO_STATUS_RESULTS: //--- Gathering of all Results -----------------------
+
+		// if in normal plan, publish the stops table to the display functions
+		if( !(char_O_deco_status & DECO_PLAN_ALTERNATE) ) publish_deco_table();
+
+		// The current depth is needed by calc_CNS_planning() and gas_volumes().
+		// As it may be needed in different code blocks below but we don't want
+		// it to be in the code multiple times, it's done here on stockpile.
+		bottom_depth = (unsigned char)((pres_respiration - pres_surface) * BAR_TO_METER);
+
+		// Calculate the ascent time.
+		// When within NDL, potential gas switches will be treated as done "on the fly".
+		calc_ascenttime();
+
+		// results to publish depend whether within NDL or in deco
+		if( NDL_time )
+		{
+			//---- within NDL ----------------------------------------------
+
+			// Calculate the initial ascent (not yet done when within NDL) - 
+			// just to get potential gas switches into the stops table for use
+			// by gas_volumes(). The stops table can be polluted by now because
+			// the clean table has already been published to the display
+			// functions before.
+			calc_ascent_to_first_stop();
+
+			// check which plan we are on
+			if( char_O_deco_status & DECO_PLAN_ALTERNATE )
 			{
-				// published (erased) stops table
-				copy_deco_table();
-
-				// ** commented out - char_O_deco_last_stop is not used for anything
-				//
-				// // set last stop to 0 (for OSTC menu animation)
-				// char_O_deco_last_stop = 0;
-				
-				// clear tank pressure needs
-				if( char_O_deco_status & DECO_VOLUME_CALCULATE )
-					for(i=0; i<NUM_GAS; ++i) int_O_tank_pres_need[i] = 0 + INT_FLAG_ZERO; // 0 bar + flag for 0 bar
-
-				// calculate the CNS% at the end of the dive if requested:
-				// as we are in no stop, CNS at end of dive is more or less the same CNS we have now
-				if( char_O_deco_status & DECO_CNS_CALCULATE ) int_O_normal_CNS_fraction = int_O_CNS_fraction;
-
-				// YES - computation of normal plan completed
-				char_O_deco_status &= ~DECO_STATUS_MASK;
+				//---- alternate dive plan ---------------------------------
+
+				// As we are in no stop, CNS at end of dive is more or less
+				// the same CNS as we have right now. It's so simple that we
+				// don't check if it requested to be computed or not...
+				int_O_alternate_CNS_fraction = int_O_CNS_fraction;
+
+				// output NDL time
+				char_O_alternate_nullzeit  = NDL_time;
+
+				// clear ascent time
+				int_O_alternate_ascenttime = 0;
 			}
 			else
 			{
-				// NO - clear status bits and set status bits for
-				//      calculation of ascent on next invocation
-				char_O_deco_status &= ~DECO_STATUS_MASK;
-				char_O_deco_status |=  DECO_STATUS_ASCENT;
+				//---- normal dive plan ------------------------------------
+
+				// As we are in no stop, CNS at end of dive is more or less
+				// the same CNS as we have right now. It's so simple that we
+				// don't check if it requested to be computed or not...
+				int_O_normal_CNS_fraction = int_O_CNS_fraction;
+
+				// output NDL time
+				char_O_nullzeit = NDL_time;
+
+				// clear ascent time
+				int_O_ascenttime = 0;
 			}
-		}
-
-		break;
-
-		
-	case DECO_STATUS_ASCENT: //---- Simulate ascent to first stop -------------------
-		
-		// initialize depth (in abs.pressure) for ascent and deco simulation, start from current real depth
-		temp_deco = pres_respiration;
-		
-		// calculate ascent to first stop
-        sim_ascent_to_first_stop();
-
-        // calculate all further stops next time
-		char_O_deco_status &= ~DECO_STATUS_MASK;	// clear status bits and set status bits
-		char_O_deco_status |=  DECO_STATUS_STOPS;	// for calculation of stops on next invocation
-		
-        break;
-
-
-	case DECO_STATUS_STOPS: //---- Simulate stops ----------------------------------
-	
-        calc_hauptroutine_calc_deco();
-
-		// If simulation is finished, do some more computations if requested
-		// and restore the GF low reference so that the next ascent simulation
-		// is done from the current depth: 
-		if( !(char_O_deco_status & DECO_STATUS_MASK) )
-        {
-			// Calculate ascent time, result in int_O_ascenttime or int_O_alternate_ascenttime
-            calc_ascenttime();
-
-			// the current depth is needed by calc_CNS_planning() and gas_volumes()
-			bottom_depth = (unsigned char)((pres_respiration - pres_surface)*BAR_TO_METER);
-			
-			// if requested, calculate the CNS% at the end of the dive (including the deco stops)
-			if( char_O_deco_status & DECO_CNS_CALCULATE    ) calc_CNS_planning();
-			
-			// if requested, calculate the required gas volumes and tank pressures at the end of the dive.
-			if( char_O_deco_status & DECO_VOLUME_CALCULATE ) gas_volumes();			
-			
-			// some more aftermath dependent on the current plan
-			if( char_O_deco_status & DECO_PLAN_ALTERNATE   )
+		} // NDL
+		else
+		{
+			//---- in DECO -------------------------------------------------
+
+			// check which plan we are on
+			if( char_O_deco_status & DECO_PLAN_ALTERNATE )
 			{
 				//---- alternative plan ----------------------------------------------------
 
-				// was CNS at end of dive calculated?
+				// shall the CNS at the end of the dive be calculated?
 				if( char_O_deco_status & DECO_CNS_CALCULATE )
 				{
-					// yes - compute CNS value to display
-					if		( CNS_sim_alt_fraction < 0.01  ) int_O_alternate_CNS_fraction = 0;
-					else if ( CNS_sim_alt_fraction > 9.985 ) int_O_alternate_CNS_fraction = 999 + INT_FLAG_WARNING;
-					else
-					{	
-						// convert float to integer
-						int_O_alternate_CNS_fraction = (unsigned short)(100 * CNS_sim_alt_fraction + 0.5);
-	
-						// set warning flag if CNS is >= 100%
-						if( int_O_alternate_CNS_fraction >= 100 )
-						int_O_alternate_CNS_fraction |= INT_FLAG_WARNING;
-				
-						// set invalid flag if there is an overflow in the stops table
-						if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW )
-						int_O_alternate_CNS_fraction |= INT_FLAG_INVALID;
-					}
+					// calculate the CNS for the predicted ascent, result in sim_CNS_fraction
+					calc_CNS_planning();
+
+					// add current CNS value
+					sim_CNS_fraction += CNS_fraction;
+
+					// convert to integer value
+					convert_sim_CNS_for_display();
+
+					// export result
+					int_O_alternate_CNS_fraction = int_sim_CNS_fraction;
 				}
-				else
-				{
-					// no - invalidate value (value = 0, invalid flag set)
-					int_O_alternate_CNS_fraction = INT_FLAG_INVALID;
-				}
-			}
+
+				// clear NDL time
+				char_O_alternate_nullzeit  = 0;
+
+				// output ascent time
+				int_O_alternate_ascenttime = ascent_time;
+
+			} // alternative plan
 			else
 			{
 				//---- normal plan ---------------------------------------------------------
 
-				// publish the stops table
-				copy_deco_table();
-
-				// was CNS at end of dive calculated?
+				// shall the CNS at the end of the dive be calculated?
 				if( char_O_deco_status & DECO_CNS_CALCULATE )
 				{
-					// yes - compute CNS value to display
-					if		( CNS_sim_norm_fraction <  0.01  ) int_O_normal_CNS_fraction = 0;
-					else if ( CNS_sim_norm_fraction >= 9.985 ) int_O_normal_CNS_fraction = 999 + INT_FLAG_WARNING;
-					else
-					{	
-						// convert float to integer
-						int_O_normal_CNS_fraction = (unsigned short)(100 * CNS_sim_norm_fraction + 0.5);
-	
-						// set warning flag if CNS is >= 100%
-						if( int_O_normal_CNS_fraction >= 100 )
-							int_O_normal_CNS_fraction |= INT_FLAG_WARNING;
-				
-						// set invalid flag if there is an overflow in the stops table
-						if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW )
-							int_O_normal_CNS_fraction |= INT_FLAG_INVALID;
-					}
+					// calculate the CNS for the predicted ascent, result in sim_CNS_fraction
+					calc_CNS_planning();
+
+					// add current CNS value
+					sim_CNS_fraction += CNS_fraction;
+
+					// convert to integer value
+					convert_sim_CNS_for_display();
+
+					// export result
+					int_O_normal_CNS_fraction = int_sim_CNS_fraction;
 				}
-				else
-				{
-					// no - invalidate value (value = 0, invalid flag set)
-					int_O_normal_CNS_fraction = INT_FLAG_INVALID;
-				}
-
-			} // aftermath
-		} // if
-		
-        break;
-		
-    } // switch
+
+				// clear NDL time
+				char_O_nullzeit  = 0;
+
+				// output ascent time
+				int_O_ascenttime = ascent_time;
+
+			} // normal plan
+		} // DECO
+
+		// if requested, calculate the required gas volumes and tank pressures at the end of the dive
+		if( char_O_deco_status & DECO_VOLUME_CALCULATE ) gas_volumes();
+
+		// signal that the computation cycle is finished
+		char_O_deco_status &= ~DECO_STATUS_MASK;
+
+		break;
+
+	} // switch
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // calc_hauptroutine_data_input
 //
-// Reset all C-code dive parameters from their ASM-code values.
+// Set all C-code dive parameters from their ASM-code values.
 // Detect gas change condition.
 //
 void calc_hauptroutine_data_input(void)
 {
+	overlay float IG_ratio;
+
 	// get the current pressures
-	pres_respiration = 0.001 * int_I_pres_respiration;
-    pres_surface     = 0.001 * int_I_pres_surface;
+	pres_surface     = 0.001  * int_I_pres_surface;
+	pres_respiration = 0.001  * int_I_pres_respiration;
+
+	// N2 tissue pressure at surface equilibrium, used for tissue graphics scaling
+	N2_equilibrium   = 0.7902 * (pres_surface - ppWater);
+
+	// read the GF settings (they may have been switch between GF/aGF)
+	GF_high  = 0.01 * char_I_GF_High_percentage;
+	GF_low   = 0.01 * char_I_GF_Low_percentage;
+	GF_delta = GF_high - GF_low;
 
 	// get the currently breathed gas mixture
-	O2_ratio         = 0.01 * char_I_O2_ratio;
-    He_ratio         = 0.01 * char_I_He_ratio;
-
-	// N2 ratios are computed within p2_deco.c from the O2 and He ratios
-	N2_ratio         = 1.0 - O2_ratio - He_ratio;
-	
-	// N2 tissue pressure at surface equilibrium, used for tissue graphics scaling
-	N2_equilibrium   = 0.7902 * (pres_surface - ppWater);
+	O2_ratio = 0.01 * char_I_O2_ratio;
+	He_ratio = 0.01 * char_I_He_ratio;
+
+	// inert gas ratio (local helper variable)
+	IG_ratio = 1.00 - O2_ratio;
+
+	// N2 ratio
+	N2_ratio = IG_ratio - He_ratio;
+
+	// precomputed values for ppO2 drop in pSCR loop
+	float_pSCR_factor = 0.01 * char_I_PSCR_drop * char_I_PSCR_lungratio;
+	pSCR_drop         = IG_ratio * float_pSCR_factor;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1688,212 +1869,60 @@
 //
 void calc_hauptroutine_update_tissues(void)
 {
-    overlay float pres_diluent = pres_respiration;
-
-	
-    assert( 0.00 <= N2_ratio && N2_ratio <= 1.00 );
-    assert( 0.00 <= He_ratio && He_ratio <= 1.00 );
-    assert( (N2_ratio + He_ratio) <= 1.00 );
-    assert( 0.800 < pres_respiration && pres_respiration < 14.0 );
-
-	
-	//---- OC, CCR and Bailout Mode Gas Calculations ------------------------------------------------------------
-	
-	// calculate ppO2 of pure oxygen
-	O2_ppO2 = (pres_respiration - ppWater);
-
-	// capture failure condition in case pres_respiration is < ppWater (should never happen...)
-	if( O2_ppO2 < 0.0 ) O2_ppO2 = 0.0;
-	
-	// calculate ppO2 of the pure gas (diluent)
-	pure_ppO2 = O2_ppO2 * O2_ratio;
-
-	
-	//---- PSCR Mode Gas Calculation-----------------------------------------------------------
-	
-	// With flags set for PSCR we compute the ppO2 in the loop from the diluent's O2
-	// ratio and the PSCR parameters. This figure will be used in the pSCR custom view.
-	// If sensors are used (char_I_const_ppO2 > 0), we will override the calculated ppO2
-	// with the sensor data. Then we continue with the CCR mode code which calculates
-	// the increase of ppN2 and ppH2 due to the reduction of the ppO2 in the loop.
-	// Essentially, diving a pSCR is like diving a CCR with a setpoint set lower than
-	// the ambient pressure multiplied with the O2 fraction of the diluent...
-			
-	// calculate pSCR ppO2
-	//
-	// pres_respiration      is 0.0 ...       in bar
-	// O2_ratio              is 0.0 ...   1.0 as factor
-	// char_I_PSCR_drop      is 0   ...  15   as %
-	// char_I_PSCR_lungratio is 5   ...  20   as %
-	// pSCRppO2				 is 0.0 ...       in bar
-
-	pSCR_ppO2 = (pres_respiration * O2_ratio) - (1 - O2_ratio) * 0.01 * char_I_PSCR_drop * char_I_PSCR_lungratio;
-
-	// capture failure condition if case pSCR_ppO2 becomes negative
-	if( pSCR_ppO2 < 0.0 ) pSCR_ppO2 = 0.0;	
-	
-	
-	//---- Loop modes : adjust ppN2 and ppHe for change in ppO2 due to setpoint (CCR) or drop (pSCR) ------------
-	if ( char_O_main_status & DECO_MODE_LOOP )
-    {
-		overlay float const_ppO2;
-
-		// get the current sensor reading (CCR / pSCR if fitted) or the fixed setpoint (CCR) / a zero (pSCR)
-        const_ppO2 = 0.01 * char_I_const_ppO2;
-		
-		// Limit the setpoint to the maximum physically possible ppO2. This prevents for
-		// example calculating with a setpoint of 1.3 bar in only 2 meters of depth.
-		// Additionally, if limiting occurs, the ppO2 can be further reduced to account
-		// for residual inert gases by the user-adjustable setting char_I_cc_max_frac_o2.
-		
-		if( const_ppO2 > pres_respiration )	// no ppWater subtracted here to give some margin for
-		{									// sensors delivering data a little bit over target
-			
-			const_ppO2 = 0.01 * char_I_cc_max_frac_o2 * (pres_respiration - ppWater);
-		}
-				
-		// check which kind of loop we are on
-		if( char_O_main_status & DECO_MODE_PSCR ) 
-		{
-			//---- pSCR Mode --------------------------------------------------------------------------
-
-			// check if a sensor is fitted
-			if( char_I_const_ppO2 ) breathed_ppO2 = const_ppO2;	// yes - derive ppO2s from (char_I_)const_ppO2
-			else                    breathed_ppO2 = pSCR_ppO2;	// no  - derive ppO2s from calculated ppO2
-		}
-		else
-		{
-			//---- CCR Mode ---------------------------------------------------------------------------
-
-			// derive breathed ppO2 from (char_I_)const_ppO2, which holds sensor reading or fixed setpoint
-			breathed_ppO2 = const_ppO2;
-		}
-
-		// adjust diluent pressure (ppN2 + ppHe) for change in ppO2 due to setpoint (CCR) or drop (pSCR)
-        pres_diluent -= const_ppO2;
-        pres_diluent /= N2_ratio + He_ratio;
-
-		// capture all failure conditions, including div/0 in case diluent is pure O2
-		if( (pres_diluent < 0.0) || (char_I_O2_ratio == 100) )
-		{
-			pres_diluent  = 0.0;
-			breathed_ppO2 = pure_ppO2;
-		}
-
-	}
-	else
-	{	//---- OC mode -----------------------------------------------------------------------------------------
-	
-		// breathed ppO2 is ppO2 of pure gas
-		breathed_ppO2 = pure_ppO2;
-	}
-
-
-	// derive char_actual_ppO2 in [cbar], used for calculating CNS%
-	if      ( breathed_ppO2 <  0.01  ) char_actual_ppO2  =   0;
-	else if ( breathed_ppO2 >= 2.545 ) char_actual_ppO2  = 255;
-	else                               char_actual_ppO2  = (unsigned char)(100 * breathed_ppO2 + 0.5);
-
-	
-	//---- export ppO2 values in [cbar] for warning generation and display purpose ------------------------------
+	overlay float EAD, END;
+
+	//---- calculations part ----------------------------------------------------------------------
+
+	// calculate ppN2 and ppHe
+	calc_alveolar_pressures();
+
+	// calculate the tissues
+	calc_tissues();
+
+	// calculate ceiling (at GF_high) and current GF
+	calc_limit(GF_high);
+
+	// calculate EAD (Equivalent Air Depth): equivalent depth for the same N2 level with plain air
+	EAD = (ppN2 / 0.7902 + ppWater - pres_surface) * BAR_TO_METER;
+
+	// calculate END (Equivalent Narcotic Depth): here O2 is treated as narcotic, too
+	// Source cited: The Physiology and Medicine of Diving by Peter Bennett and David Elliott,
+	//               4th edition, 1993, W.B.Saunders Company Ltd, London.
+	END = (pres_respiration - ppHe - pres_surface) * BAR_TO_METER;
+
+
+	//---- export ppO2 values in [cbar] for warning generation and display purpose ----------------
 
 	// pure oxygen ppO2
 	if		( O2_ppO2       <  0.01  ) int_O_O2_ppO2       =   0;
 	else if ( O2_ppO2       >= 9.995 ) int_O_O2_ppO2       = 999;
-	else                               int_O_O2_ppO2       = (unsigned int)(100 *       O2_ppO2 + 0.5);
+	else                               int_O_O2_ppO2       = (unsigned int)(100 *   O2_ppO2 + 0.5);
 	
 	// pure gas ppO2
-	if      ( pure_ppO2     <  0.01  ) int_O_pure_ppO2     =   0;
-	else if ( pure_ppO2     >= 9.995 ) int_O_pure_ppO2     = 999;
-	else                               int_O_pure_ppO2     = (unsigned int)(100 *     pure_ppO2 + 0.5);
+	if      ( OC_ppO2       <  0.01  ) int_O_pure_ppO2     =   0;
+	else if ( OC_ppO2       >= 9.995 ) int_O_pure_ppO2     = 999;
+	else                               int_O_pure_ppO2     = (unsigned int)(100 *   OC_ppO2 + 0.5);
 	
 	// calculated pSCR ppO2
 	if		( pSCR_ppO2     <  0.01  ) int_O_pSCR_ppO2     =   0;
 	else if ( pSCR_ppO2     >= 9.995 ) int_O_pSCR_ppO2     = 999;
-	else                               int_O_pSCR_ppO2     = (unsigned int)(100 *     pSCR_ppO2 + 0.5);
+	else                               int_O_pSCR_ppO2     = (unsigned int)(100 * pSCR_ppO2 + 0.5);
 
 	// breathed ppO2
-	if		( breathed_ppO2 <  0.01  ) int_O_breathed_ppO2 =   0;
-	else if ( breathed_ppO2 >= 9.995 ) int_O_breathed_ppO2 = 999;
-	else                               int_O_breathed_ppO2 = (unsigned int)(100 * breathed_ppO2 + 0.5);
-	
-
-	//---- calculate ppN2, ppHe and EAD, END -------------------------------------------------------------------
-	
-    if( pres_diluent > ppWater )
-    {
-        overlay float EAD, END;
-
-        ppN2 = N2_ratio * (pres_diluent - ppWater);
-        ppHe = He_ratio * (pres_diluent - ppWater);
-
-        // EAD : Equivalent Air Depth. Equivalent depth for the same N2 level with plain air.
-        //       ppN2 = 79% * (P_EAD - ppWater)
-        //       EAD = (P_EAD - Psurface) * 10
-        //   ie: EAD = (ppN2 / 0.7902 + ppWater -Psurface) * 10
-
-        EAD = (ppN2 / 0.7902 + ppWater - pres_surface) * BAR_TO_METER;
-
-        if( (EAD < 0.0) || (EAD > 245.5) ) EAD = 0.0;
-
-        char_O_EAD = (unsigned char)(EAD + 0.5);
-
-		
-        // END : Equivalent Narcotic Depth.
-        //       Here we count O2 as narcotic too. Hence everything but helium (has a narcosis
-        //       factor of 0.23 btw). Hence the formula becomes:
-        //       END * BarPerMeter * (1.0 - 0.0) - ppWater + Psurface == Pambient - ppHe - ppWater
-        //  ie:  END = (Pambient - ppHe - Psurface) * BAR_TO_METER
-        //
-        // Source cited:
-        //       The Physiology and Medicine of Diving by Peter Bennett and David Elliott,
-        //       4th edition, 1993, W.B.Saunders Company Ltd, London.
-
-        END = (pres_respiration - ppHe - pres_surface) * BAR_TO_METER;
-
-        if( (END < 0.0) || (END > 245.5) ) END = 0.0;
-
-		char_O_END = (unsigned char)(END + 0.5);
-    }
-    else
-    {
-        ppN2 = ppHe = 0.0;
-		
-		char_O_EAD = char_O_END = 0;
-    }
-
-
-	//---- calculate decompression status ----------------------------------------------------------------------
-		
-	// Calculate tissues
-	calc_tissue();
-
-    // Calculate limit for surface, ie. GF_high.
-    calc_limit();
-	
-
-    // Fill int_O_ceiling (in mbar) if ceiling is below the surface
-    if( (calc_lead_tissue_limit - pres_surface) > 0 )
-	{	
-
-// compatibility version
-        int_O_ceiling = (short)((calc_lead_tissue_limit - pres_surface) * 1000);
-
-// new version
-//		// Round up to next 10 cm so that the ceiling disappears on the display only when the ceiling
-//		// limit is really zero. This will coincident then with TTS switching back to NDL time.
-//		int_O_ceiling = (short)((calc_lead_tissue_limit - pres_surface) * 1000 + 9);
-				
-
-		// limit int_O_ceiling to 16000 mbar (150 m)
-		if( int_O_ceiling > 16000) int_O_ceiling = 16000;
-	}
-    else
-	{
-        int_O_ceiling = 0;
-	}
-
-    int_O_gtissue_press = (short)((pres_tissue_N2[char_O_gtissue_no] + pres_tissue_He[char_O_gtissue_no]) * 1000);
+	if		( ppO2          <  0.01  ) int_O_breathed_ppO2 =   0;
+	else if ( ppO2          >= 9.995 ) int_O_breathed_ppO2 = 999;
+	else                               int_O_breathed_ppO2 = (unsigned int)(100 *      ppO2 + 0.5);
+
+
+	//---- export EAD and END ---------------------------------------------------------------------
+
+	// EAD
+	if( (EAD < 0.0) || (EAD > 245.5) ) char_O_EAD = 0;
+	else                               char_O_EAD = (unsigned char)(EAD + 0.5);
+
+	// END
+	if( (END < 0.0) || (END > 245.5) ) char_O_END = 0;
+	else                               char_O_END = (unsigned char)(END + 0.5);
 }
 
 
@@ -1910,6 +1939,7 @@
 {
 	overlay unsigned char loop;
 
+
 	for(loop = 0; loop < 16; ++loop)
 	{
 		// limit loops to 512ms, using timer 5
@@ -1917,8 +1947,8 @@
 
 		// calc_nextdecodepth()
 		//
-		// INPUT  temp_deco        : current depth in absolute pressure
-		// OUTPUT temp_depth_limit : depth of next stop in meters
+		// INPUT  sim_pres_respiration : current depth in absolute pressure
+		// OUTPUT sim_depth_limit      : depth of next stop in meters
 		// RETURN true if a stop is needed
 		//
 		// The function manages gas changes by itself, including priming
@@ -1926,13 +1956,13 @@
 		//
 		if( calc_nextdecodepth() )
 		{
-			if( temp_depth_limit == 0 ) goto Surface;	// this check should not bee needed as in
+			if( sim_depth_limit == 0 ) goto Surface;	// this check should not bee needed as in
 														// this case the RETURN value will be false
 
-			//---- stop required at temp_depth_limit -------------------------------------
+			//---- stop required at sim_depth_limit -------------------------------------
 
 			// convert stop depth in meters to absolute pressure
-			temp_deco = temp_depth_limit * METER_TO_BAR + pres_surface;
+			sim_pres_respiration = sim_depth_limit * METER_TO_BAR + pres_surface;
 
 			// add one minute to the current stop, or add a new stop,
 			// or abort deco calculation if the deco table is full.
@@ -1941,22 +1971,18 @@
 		else
 		{
 			//---- no stop required --------------------------------------
-			
+
 			// ascend by float_ascent_speed for 1 minute
-			temp_deco -= float_ascent_speed * METER_TO_BAR;
+			sim_pres_respiration -= float_ascent_speed * METER_TO_BAR;
 
 			// finish deco calculation if surface is reached
-			if( temp_deco <= pres_surface )
+			if( sim_pres_respiration <= pres_surface )
 			{
 Surface:
-				// set deco engine status to done (DECO_STATUS_FINISHED)
+				// continue with gathering all results in the next calculation phase
 				char_O_deco_status &= ~DECO_STATUS_MASK;
-			
-				// ** commented out - char_O_deco_last_stop is not used for anything
-				//
-				// // surface reached (to animate menu)
-				// if( !(char_O_deco_status & DECO_PLAN_ALTERNATE)) char_O_deco_last_stop = 0;
-				
+				char_O_deco_status |=  DECO_STATUS_RESULTS;
+
 				return;
 			}
 		}
@@ -1966,55 +1992,50 @@
 
 		// program 1 minute interval on simulated tissues (Flagbit 7 = 0)
 		tissue_increment = 1;
-		
+
 		// compute current ppN2 and ppHe
-		sim_alveolar_presures();
-		
+		calc_alveolar_pressures();
+
 		// update the tissues
-		calc_tissue();
+		calc_tissues();
 	}
-
-	// ** commented out - char_O_deco_last_stop is not used for anything
-	//
-	// // surface not reached, need more stops... store reached depth for menu animation.
-	// if( !(char_O_deco_status & DECO_PLAN_ALTERNATE) ) char_O_deco_last_stop = temp_depth_limit;
 }
 
 
 //////////////////////////////////////////////////////////////////////////////
-// Simulate ascent to first deco stop.
+// Calculate ascent to first deco stop.
 //
 //
-// Modified: temp_deco : current depth in ascent and deco simulation, in bar absolute pressure
+// Modified: sim_pres_respiration : current depth in ascent and deco simulation, in bar absolute pressure
 //
-void sim_ascent_to_first_stop(void)
+void calc_ascent_to_first_stop(void)
 {
 	overlay unsigned char fast      = 1;	// 1 = 1 minute steps,  0 = 2 seconds steps
 	overlay unsigned char gaschange = 0;	// 1 = do a gas change, 0 = no better gas available
-	
-	
+
+
 	//---- Loop until first deco stop or surface is reached ----------
 	for(;;)
 	{
 		// depth in absolute pressure we came from
-		overlay float old_deco = temp_deco;
-		
+		overlay float old_deco = sim_pres_respiration;
+
 		// try ascending 1 full minute (fast) or 2 seconds (!fast)
-		if	( fast ) temp_deco -=  float_ascent_speed       * METER_TO_BAR;	// 1 min at float_ascent_speed ( 5 .. 10  m/min)
-		else         temp_deco -= (float_ascent_speed/30.0) * METER_TO_BAR;	// 2 sec at float_ascent_speed (17 .. 33 cm/min)
+		if	( fast ) sim_pres_respiration -=  float_ascent_speed       * METER_TO_BAR;	// 1 min at float_ascent_speed ( 5 .. 10  m/min)
+		else         sim_pres_respiration -= (float_ascent_speed/30.0) * METER_TO_BAR;	// 2 sec at float_ascent_speed (17 .. 33 cm/min)
 
 		// but don't go over surface
-		if( temp_deco < pres_surface ) temp_deco = pres_surface;
-
-		// compute sim_lead_tissue_limit
-		if   ( char_I_deco_model != 0 ) sim_limit(GF_low);
-		else                            sim_limit(1.0);
+		if( sim_pres_respiration < pres_surface ) sim_pres_respiration = pres_surface;
+
+		// compute current ceiling of the simulated tissues
+		if   ( char_I_deco_model != 0 ) calc_limit(GF_low);
+		else                            calc_limit(1.0);
 
 		// did we overshoot the first deco stop?
-		if( temp_deco < sim_lead_tissue_limit )
+		if( sim_pres_respiration < (sim_ceiling + pres_surface) )
 		{
 			// YES - back to last depth below first stop
-			temp_deco = old_deco;
+			sim_pres_respiration = old_deco;
 
 			// switch to 2 seconds ascent if not yet in, else done
 			if( fast )
@@ -2029,13 +2050,13 @@
 		}
 
 		// If code execution passes along here, we did not overshoot the first stop.
-		
+
 		// did we reach the surface? if yes, done!
-		if( temp_deco == pres_surface ) break;
+		if( sim_pres_respiration == pres_surface ) break;
 
 		// depth in meters where we are now (no round-up)
-		temp_depth_limit = (unsigned char)((temp_deco - pres_surface) * BAR_TO_METER);
-		
+		sim_depth_limit = (unsigned char)((sim_pres_respiration - pres_surface) * BAR_TO_METER);
+
 		// Check if there is a better gas to switch to, but only in alternative plan mode
 		// or if override is set. If yes, introduce a stop for the gas change.
 		if(    ((char_O_deco_status & DECO_PLAN_ALTERNATE) || (char_O_main_status & DECO_GASCHANGE_OVRD))
@@ -2043,35 +2064,35 @@
 		{
 			// depth in meters we came from
 			overlay unsigned char old_depth_limit = (unsigned char)((old_deco - pres_surface) * BAR_TO_METER);			
-			
-			// adjust temp_depth_limit to the gas change depth, but not deeper than the depth we came from
-			temp_depth_limit = (sim_gas_last_depth < old_depth_limit) ? sim_gas_last_depth : old_depth_limit;
-			
+
+			// adjust sim_depth_limit to the gas change depth, but not deeper than the depth we came from
+			sim_depth_limit = (sim_gas_last_depth < old_depth_limit) ? sim_gas_last_depth : old_depth_limit;
+
 			// create a stop for the gas change
 			update_deco_table(char_I_gas_change_time);
 
 			// set the new calculation values for N2, He and O2
-			gas_switch_set();
-			
+			gas_set_ratios();
+
 			// signal to create a stop for the gas change and update the tissues
 			gaschange = char_I_gas_change_time;
-			
+
 			// Adjust the depth for the tissue update to the stop depth. In case of fast mode, this
 			// imposes that the ascent from the 'old_deco' depth to this stop took 1 minute although
 			// we might have only ascended one or two meters...
-			temp_deco = temp_depth_limit * METER_TO_BAR + pres_surface;
-		}	
-		
+			sim_pres_respiration = sim_depth_limit * METER_TO_BAR + pres_surface;
+		}
+
 		// Did one minute pass by and/or do we have a gas change?
 		// Remark: The 2 seconds ascent iterations towards the first deco stop in !fast speed may take
 		// up to 28 seconds in total - for this rough half of a minute no tissue updates will be computed.
 		// Well, it could be done by setting tissue_increment = 0 in !fast condition and making calls to
-		// sim_alveolar_presures() and calc_tissue() - see code commented out below.
+		// calc_alveolar_pressures() and calc_tissues() - see code commented out below.
 		if( fast || gaschange )
 		{
 			// program interval on simulated tissues (flag bit 7 = 0)
 			tissue_increment = fast + gaschange;
-			
+
 			// clear gas change signal
 			gaschange = 0;
 	//	}
@@ -2081,92 +2102,83 @@
 	//		tissue_increment = 0;
 	//	}
 	//	{
-			// compute ppN2/ppHe for current depth from temp_deco
-			sim_alveolar_presures();
+			// compute ppN2/ppHe for current depth from sim_pres_respiration
+			calc_alveolar_pressures();
 			
 			// update the tissues
-			calc_tissue();
+			calc_tissues();
 		}
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// Simulate extra time at the current depth.
-//
-// This routine is used for the futureTTS / delayed ascent feature.
-//
-void sim_extra_time(void)
-{
- 	overlay unsigned char backup = tissue_increment;	// back-up tissue_increment
-
-	tissue_increment  = char_I_extra_time;				// program interval on simulated tissues (Flagbit 7 = 0)
-	
-	calc_tissue();										// update the tissues
-	
-	tissue_increment = backup;							// restore tissue_increment
-}
 
 //////////////////////////////////////////////////////////////////////////////
-// calc_tissue
+// calc_tissues
 //
-// optimized in v.101
+// INPUT:    ppN2                          : partial pressure of inspired N2
+//           ppHe                          : partial pressure of inspired He
+//           tissue_increment              : integration time and tissue selector (real or simulated)
 //
-// INPUT:	 ppN2, ppHe, tissue_increment
-// MODIFIED: pres_tissue_N2[], pres_tissue_He[]
-// OUTPUT:	 char_O_tissue_N2_saturation[], char_O_tissue_He_saturation[]
+// MODIFIED: pres_tissue_N2[]              : tissue N2 pressures (in real tissues context)
+//           pres_tissue_He[]              : tissue He pressures (in real tissues context)
+//           sim_pres_tissue_N2[]          : tissue N2 pressures (in simulated tissues context)
+//           sim_pres_tissue_He[]          : tissue He pressures (in simulated tissues context)
 //
-static void calc_tissue()
+// OUTPUT:   char_O_tissue_N2_saturation[] : tissue N2 pressures scaled for display purpose (in real tissues context)
+//           char_O_tissue_He_saturation[] : tissue He pressures scaled for display purpose (in real tissues context)
+//
+static void calc_tissues()
 {
 	overlay float			temp_tissue_N2;
 	overlay float			temp_tissue_He;
 	overlay unsigned char	period;
 	overlay unsigned char	i;
-		
-		
-    assert( 0.00 <= ppN2 && ppN2 < 11.2 );  // 80% N2 at 130m
-    assert( 0.00 <= ppHe && ppHe < 12.6 );  // 90% He at 130m
-	
-	
-    for (ci=0;ci<NUM_COMP;ci++)			// iterate through all compartments
-    {
-		i = tissue_increment & 127;		// extract number of minutes to do    (if i > 0)
-										// or if one 2 second period is to do (if i = 0)
-		
-		if( i == 0 )					// check if we shall do one 2-seconds period
+
+
+	assert( 0.00 <= ppN2 && ppN2 < 11.2 );  // 80% N2 at 130m
+	assert( 0.00 <= ppHe && ppHe < 12.6 );  // 90% He at 130m
+
+
+	for (ci=0;ci<NUM_COMP;ci++)				// iterate through all compartments
+	{
+		i = tissue_increment & TIME_MASK;	// extract number of minutes to do    (if i > 0)
+											// or if one 2 second period is to do (if i = 0)
+
+		if( i == 0 )						// check if we shall do one 2-seconds period
 		{
-			read_Buhlmann_times(0); 	// YES, program coefficients for a 2 seconds period
-			period = 1;					//      set period length (in cycles)
-			i      = 1;					//      and one cycle to do
+			read_Buhlmann_times(0);			// YES, program coefficients for a 2 seconds period
+			period = 1;						//      set period length (in cycles)
+			i      = 1;						//      and one cycle to do
 		}
-		else if( i > 9 )				// check if we can start with 10 minutes periods
+		else if( i > 9 )					// check if we can start with 10 minutes periods
 		{
-			read_Buhlmann_times(2);		// YES, program coefficients for 10 minutes periods
-			period = 10;				//      set period length (in cycles) to ten
+			read_Buhlmann_times(2);			// YES, program coefficients for 10 minutes periods
+			period = 10;					//      set period length (in cycles) to ten
 		}
-		else							// we shall do 1 to 9 minutes
+		else								// we shall do 1 to 9 minutes
 		{
-			read_Buhlmann_times(1);		//      program coefficients for 1 minute periods
-			period = 1;					//      set period length (in cycles) to one
+			read_Buhlmann_times(1);			//      program coefficients for 1 minute periods
+			period = 1;						//      set period length (in cycles) to one
 		}
 
 		do
 		{
 			//---- N2 -------------------------------------------------------------------------------
 
-			temp_tissue = (tissue_increment & 128) ? pres_tissue_N2[ci] : sim_pres_tissue_N2[ci];
+			temp_tissue = (tissue_increment & TISSUE_FLAG) ? pres_tissue_N2[ci] : sim_pres_tissue_N2[ci];
 
 			temp_tissue = (ppN2 - temp_tissue) * var_N2_e;
 
 			temp_tissue_safety();
 
-			if( tissue_increment & 128 )
+			if( tissue_increment & TISSUE_FLAG )
 			{
 				// The temp variable takes on purpose just the tissue increment from the last loop's iteration.
 				temp_tissue_N2 = temp_tissue;
 				
 				// Update the real tissues if either we are on the 2 seconds interval,
 				// or if we shall advance the tissues on a one or several minutes basis.
-				if( twosectimer || (tissue_increment & 127) ) pres_tissue_N2[ci] += temp_tissue;
+				if( twosectimer || (tissue_increment & TIME_MASK) ) pres_tissue_N2[ci] += temp_tissue;
 			}
 			else
 			{
@@ -2177,22 +2189,21 @@
 
 
 			//---- He -------------------------------------------------------------------------------
-			
-			temp_tissue = (tissue_increment & 128) ? pres_tissue_He[ci] : sim_pres_tissue_He[ci];
+
+			temp_tissue = (tissue_increment & TISSUE_FLAG) ? pres_tissue_He[ci] : sim_pres_tissue_He[ci];
 
 			temp_tissue = (ppHe - temp_tissue) * var_He_e;
 
 			temp_tissue_safety();
 
-			if( tissue_increment & 128 )
+			if( tissue_increment & TISSUE_FLAG )
 			{
 				// The temp variable takes on purpose just the tissue increment from the last loop's iteration.
 				temp_tissue_He = temp_tissue;
 				
 				// Update the real tissues if either we are on the 2 seconds interval,
 				// or if we shall advance the tissues on a one or several minutes basis.
-				if( twosectimer || (tissue_increment & 127) ) pres_tissue_He[ci] += temp_tissue;
-
+				if( twosectimer || (tissue_increment & TIME_MASK) ) pres_tissue_He[ci] += temp_tissue;
 			}
 			else
 			{
@@ -2200,38 +2211,37 @@
 				// so we do not need to check of the 2 seconds interval.
 				sim_pres_tissue_He[ci] += temp_tissue;
 			}
-			
 
 			// decrement loop counter
 			i -= period;
-			
+
 			// check if we need to switch from 10 minute periods to 1 minute periods
 			if( (i > 0) && (period = 10) && (i < 10) )
 			{
-				read_Buhlmann_times(1); 	// program coefficients for 1 minute periods
+				read_Buhlmann_times(1);		// program coefficients for 1 minute periods
 				period = 1;					// set period length (in cycles) to one
 			}
 		}
 		while( i );
-			
-			
+
+
 		// have the computations been done for the "real" tissues?
-		if( (tissue_increment & 128) && (twosectimer || (tissue_increment & 127)) )
+		if( (tissue_increment & TISSUE_FLAG) && (twosectimer || (tissue_increment & TIME_MASK)) )
 		{
 			// net tissue balance
 			temp_tissue = temp_tissue_N2 + temp_tissue_He;
-			
+
 			// check tissue on-/off-gassing and IBCD with applying a threshold of +/-HYST
 			//
-			if		( temp_tissue < -HYST )				// Check if the tissue is off-gassing
+			if      ( temp_tissue < -HYST )				// Check if the tissue is off-gassing
 			{
-				deco_tissue_vector	|=  (1 << ci);		// tag tissue as being in decompression
-				IBCD_tissue_vector	&= ~(1 << ci);		// tag tissue as not experiencing mentionable IBCD
+				deco_tissue_vector |=  (1 << ci);		// tag tissue as being in decompression
+				IBCD_tissue_vector &= ~(1 << ci);		// tag tissue as not experiencing mentionable IBCD
 			}
 			else if ( temp_tissue > +HYST )				// check if the tissue in on-gassing
 			{
-				deco_tissue_vector	&= ~(1 << ci);		// tag tissue as not being in decompression
-				
+				deco_tissue_vector &= ~(1 << ci);		// tag tissue as not being in decompression
+
 				if(		((temp_tissue_N2 > 0.0) && (temp_tissue_He < 0.0))		// check for counter diffusion
 					||	((temp_tissue_N2 < 0.0) && (temp_tissue_He > 0.0)) )
 				{
@@ -2239,19 +2249,19 @@
 				}
 			}
 
-			
+
 			// keep the saturating / desaturating flags from last invocation
 			char_O_tissue_N2_saturation[ci] &= 128;
 			char_O_tissue_He_saturation[ci]	&= 128;
-			
+
 			// flip the flags applying a hysteresis of HYST (actual value: see #define of HYST)
 				 if( temp_tissue_N2 > +HYST ) char_O_tissue_N2_saturation[ci] = 128; // set flag for tissue pressure is increasing
 			else if( temp_tissue_N2 < -HYST ) char_O_tissue_N2_saturation[ci] =   0; // clear flag (-> tissue pressure is decreasing)
 
 				 if( temp_tissue_He > +HYST ) char_O_tissue_He_saturation[ci] = 128; // set flag for tissue pressure is increasing
 			else if( temp_tissue_He < -HYST ) char_O_tissue_He_saturation[ci] =   0; // clear flag (-> tissue pressure is decreasing)
-			
-			
+
+
 			// For N2 tissue display purpose:
 			// Scale tissue press so that saturation in 70m on AIR gives a value of approx. 80.
 			// The surface steady-state tissue loading of [0.7902 * (pres_respiration - ppWater)] bar
@@ -2259,13 +2269,13 @@
 			// This scaling is adapted to the capabilities of the tissue graphics in the custom views.
 			temp_tissue = (pres_tissue_N2[ci] / N2_equilibrium) * 10;
 
-			 // limit to 127 to leave space for sat/desat flag
+			// limit to 127 to leave space for sat/desat flag
 			if (temp_tissue > 127) temp_tissue = 127;
 
 			// export as integer
 			char_O_tissue_N2_saturation[ci] += (unsigned char)temp_tissue;
 
-			
+
 			// For H2 tissue display purpose:
 			// Scale tissue press so that saturation in 120m on TMX 10/70 gives a value of approx. 70.
 			// With no He in a tissue, result will be 0.
@@ -2274,122 +2284,205 @@
 
 			// limit to 127 to leave space for sat/desat flag
 			if (temp_tissue > 127) temp_tissue = 127; 
-			
+
 			// export as integer
 			char_O_tissue_He_saturation[ci] += (unsigned char)temp_tissue;
-		}
-				
-    }// for
+		} //if
+
+	} // for
+
+
+	// set   deco flag if we are in deco and at least one of the real tissues is off-gassing
+	// clear deco flag if all of the real tissues are on-gassing
+	if      ( (char_O_nullzeit == 0) &&  deco_tissue_vector ) char_O_deco_warnings |=  DECO_FLAG;
+	else if (                           !deco_tissue_vector ) char_O_deco_warnings &= ~DECO_FLAG; 
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // calc_limit
 //
-// New in v.111 : separated from calc_tissue(), and depends on GF value.
+// Input:
+//        tissue_increment       : selector for context: real or simulated tissues
+//        sim_pres_tissue_N2/_He : tissue pressures (used in simulated tissues context)
+//        pres_tissue_N2/_He     : tissue pressures (used in real      tissues context)
 //
-static void calc_limit(void)
+// Output:
+//        sim_ceiling            : ceiling in bar  relative pressure (only in simulated tissues context)
+//        ceiling                : ceiling in bar  relative pressure (only in real      tissues context)
+//        int_O_ceiling          : ceiling in mbar relative pressure (only in real      tissues context)
+//        int_O_gradient_factor  : gradient factor in %              (only in real      tissues context)
+//
+// Modified:
+//        char_O_deco_warnings   : for IBCD, microbubbles and outside warning (only in real tissues context)
+//
+static void calc_limit(PARAMETER float GF_parameter)
 {
-    char_O_gtissue_no 		= 0;
-    calc_lead_tissue_limit 	= 0.0;
-
-	// clear IBCD, microbubbles and outside warning flags (locked warnings will be preserved)
-	char_O_deco_warnings &= ~(DECO_WARNING_IBCD + DECO_WARNING_MBUBBLES + DECO_WARNING_OUTSIDE);
-
-
-    for(ci=0; ci<NUM_COMP; ci++)
-    {
-        overlay float N2 = pres_tissue_N2[ci];
-        overlay float He = pres_tissue_He[ci];
-		overlay float pres_tissue = N2 + He;
+	overlay float lead_tissue_limit = 0.0;
+	overlay float lead_supersat     = 0.0;
+
+	overlay unsigned char lead_tissue_no = 0;
+
+
+	// check context
+	if( tissue_increment & TISSUE_FLAG )
+	{
+		// clear IBCD, microbubbles and outside warning flags (locked warnings will be preserved)
+		char_O_deco_warnings &= ~(DECO_WARNING_IBCD + DECO_WARNING_MBUBBLES + DECO_WARNING_OUTSIDE);
+	}
+
+
+	// loop over all tissues
+	for(ci=0; ci<NUM_COMP; ci++)
+	{
+		overlay float calc_pres_tissue_N2;
+		overlay float calc_pres_tissue_He;
+		overlay float pres_tissue;
 		overlay float pres_min;
-		overlay float gf;
-		overlay float threshold;
-
-        read_Buhlmann_coefficients();
-        var_N2_a = (var_N2_a * N2 + var_He_a * He) / pres_tissue;
-        var_N2_b = (var_N2_b * N2 + var_He_b * He) / pres_tissue;
-
-		// calculate minimum ambient pressure that the tissue can withstand according to straight Buhlmann
-		pres_min = (pres_tissue - var_N2_a) * var_N2_b;
-		
-		// calculate current gf value (1.0 = 100%) of this tissue
-		gf = (pres_tissue - pres_respiration) / (pres_tissue - pres_min);
-		if( gf < 0.0 ) gf = 0.0;
-		
-		// calculate a threshold value for use below
-		// ToDo: finalize the definition of the threshold
-		threshold = 0.02 * ci + 0.9;
-
-		// check if this tissue is likely to develop microbubbles
-		// and/or if this tissue is outside the Buhlmann model
-		if( ci <= 5 )
+
+		// get the tissue pressures
+		if( tissue_increment & TISSUE_FLAG )
 		{
-			if( gf >= threshold )
-			{
-				char_O_deco_warnings |= (DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock);
-				
-				if( gf >= 1.0 )
-				{
-					char_O_deco_warnings |= (DECO_WARNING_OUTSIDE + DECO_WARNING_OUTSIDE_lock);
-				}
-			}
+			// context is real tissues
+			calc_pres_tissue_N2 = pres_tissue_N2[ci];
+			calc_pres_tissue_He = pres_tissue_He[ci];
 		}
 		else
 		{
-			if( gf >= 1.0 )
-			{
-				char_O_deco_warnings |= (DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock);
+			// context is simulated tissues
+			calc_pres_tissue_N2 = sim_pres_tissue_N2[ci];
+			calc_pres_tissue_He = sim_pres_tissue_He[ci];
+		}
+
+		// overall tissue pressure
+		pres_tissue = calc_pres_tissue_N2 + calc_pres_tissue_He;
+
+		// get the coefficients for tissue ci
+		read_Buhlmann_coefficients();
+
+		// adapt the coefficients according to the N2/He ratio in the tissue
+		var_N2_a = (var_N2_a * calc_pres_tissue_N2 + var_He_a * calc_pres_tissue_He) / pres_tissue;
+		var_N2_b = (var_N2_b * calc_pres_tissue_N2 + var_He_b * calc_pres_tissue_He) / pres_tissue;
+
+		// calculate minimum ambient pressure that the tissue can withstand according to straight Buhlmann
+		pres_min = (pres_tissue - var_N2_a) * var_N2_b;
+
+		// next calculations are only relevant when invoked on the real tissues
+		if( tissue_increment & TISSUE_FLAG )
+		{
+			overlay float supersat;
+			overlay float threshold;
 	
-				if( gf >= threshold )
+			// calculate current supersaturation value (1.0 = 100%) of this tissue
+			supersat = (pres_tissue - pres_respiration) / (pres_tissue - pres_min);
+
+			// check if tissue is in supersaturation
+			if( supersat > 0.0 )
+			{
+				// memorize highest supersaturation found
+				if( supersat > lead_supersat ) lead_supersat = supersat;
+
+				// set a threshold value for the microbubbles and outside warnings
+				// ToDo: finalize the definition of the threshold
+				threshold = 0.02 * ci + 0.9;
+
+				// check if this tissue is likely to develop microbubbles
+				// and/or if this tissue is outside of the Buhlmann model
+				if( ci <= 5 )
 				{
-					char_O_deco_warnings |= (DECO_WARNING_OUTSIDE + DECO_WARNING_OUTSIDE_lock);
+					if( supersat >= threshold )
+					{
+						char_O_deco_warnings |= (DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock);
+
+						if( supersat >= 1.0 )
+						{
+							char_O_deco_warnings |= (DECO_WARNING_OUTSIDE + DECO_WARNING_OUTSIDE_lock);
+						}
+					}
+				}
+				else // ci > 5
+				{
+					if( supersat >= 1.0 )
+					{
+						char_O_deco_warnings |= (DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock);
+
+						if( supersat >= threshold )
+						{
+							char_O_deco_warnings |= (DECO_WARNING_OUTSIDE + DECO_WARNING_OUTSIDE_lock);
+						}
+					}
 				}
 			}
 		}
-		
-		
-        // Apply the Eric Baker's varying gradient factor correction if the GF-Model is selected.
-        // Note: the correction factor depends both on GF and b,
-        //       Actual values are in the 1.5 .. 1.0 range (for a GF=30%),
-        //       so that can change who is the leading gas...
-        // Note: Also depends of the GF. So the calculus is different for GF_low, current GF, or GF_high...
-        //       *BUT* calc_tissue() is used to compute bottom time, hence what would happen at surface,
-        //       hence at GF_high.
-		if( char_I_deco_model != 0 ) pres_min =   ( pres_tissue - var_N2_a * (      GF_high) ) * var_N2_b
-		                                        / ( GF_high     + var_N2_b * (1.0 - GF_high) );
+
+		// Apply the Eric Baker's varying gradient factor correction if the GF-Model is selected.
+		// Note: the correction factor depends both on GF and b, so that can change who is the
+		//       leading gas...
+		if( char_I_deco_model != 0 ) pres_min =   ( pres_tissue        - (var_N2_a     * GF_parameter) )
+		                                        / ( 1.0 - GF_parameter + (GF_parameter / var_N2_b    ) );
 
 		// check if this tissue requires a higher ambient pressure than was found to be needed up to now
-        if( pres_min > calc_lead_tissue_limit )
-        {
-            char_O_gtissue_no      = ci;
-            calc_lead_tissue_limit = pres_min;
-        }
-    }
-	
-	// check IBCD condition
-	if( !IBCD_tissue_vector )
+		if( pres_min > lead_tissue_limit )
+		{
+			lead_tissue_limit = pres_min;
+			lead_tissue_no    = ci;
+		}
+	} // for
+
+
+	// compile outputs
+	if( tissue_increment & TISSUE_FLAG )
 	{
-		char_O_deco_warnings &= ~DECO_WARNING_IBCD;					// no IBCD in any tissue, clear flag
+		//--- real tissues -----------------------------------------------------
+
+		// check if leading tissue is in IBCD condition
+		if(    (IBCD_tissue_vector & (1 << lead_tissue_no))
+		    && ((pres_tissue_N2[lead_tissue_no] + pres_tissue_He[lead_tissue_no]) > pres_respiration) )
+		{
+			// leading tissue is in IBCD condition and in super-saturation, so issue a warning.
+			char_O_deco_warnings |= (DECO_WARNING_IBCD + DECO_WARNING_IBCD_lock);
+		}
+
+
+		// compute ceiling in bar relative pressure
+		ceiling = lead_tissue_limit - pres_surface;
+
+		// convert ceiling to int_O_ceiling in mbar
+		if      ( ceiling <=  0 ) int_O_ceiling = 0;
+		else if ( ceiling >  16 ) int_O_ceiling = 16000;
+	// Compatibility version
+		else                      int_O_ceiling = (short)(ceiling * 1000);
+
+	// New version: Rounds up to next 10 cm so that the ceiling disappears on the display only when the
+	// ceiling limit is really zero. This will coincident then with TTS switching back to NDL time.
+	//	else                      int_O_ceiling = (short)(ceiling * 1000 + 9);
+
+
+		// convert highest supersaturation found to int_O_gradient_factor in % (1.0 = 100%)
+		// limit to 255 because of constraints in ghostwriter code
+		if     ( lead_supersat <= 0.0   ) int_O_gradient_factor = 0;
+		else if( lead_supersat >  2.545 ) int_O_gradient_factor = 255 + INT_FLAG_WARNING;
+		else
+		{
+			int_O_gradient_factor = (unsigned int)(100 * lead_supersat + 0.5);
+
+			if      ( int_O_gradient_factor >= GF_WARNING_THRESHOLD      )
+				int_O_gradient_factor |= INT_FLAG_WARNING;
+
+			else if ( int_O_gradient_factor >= char_I_GF_High_percentage )
+				int_O_gradient_factor |= INT_FLAG_ATTENTION;
+		}
 	}
-	else if(    (IBCD_tissue_vector & (1 << char_O_gtissue_no))
-	         && ((pres_tissue_N2[char_O_gtissue_no] + pres_tissue_He[char_O_gtissue_no]) > pres_respiration) )
+	else
 	{
-		// leading tissue is in IBCD condition and in super-saturation, set flags.
-		char_O_deco_warnings |= (DECO_WARNING_IBCD + DECO_WARNING_IBCD_lock);
+		//--- simulated tissues ------------------------------------------------
+		
+		// compute ceiling for the simulated tissues in bar relative pressure
+		sim_ceiling = lead_tissue_limit - pres_surface;
 	}
-	
-	// set   deco flag if we are in deco and at least one of the real tissues is off-gassing
-	// clear deco flag if all of the real tissues are on-gassing
-	if      ( (char_O_nullzeit == 0) &&  deco_tissue_vector ) char_O_deco_warnings |=  DECO_FLAG;
-	else if (                    !deco_tissue_vector ) char_O_deco_warnings &= ~DECO_FLAG; 
-
-
-    assert( char_O_gtissue_no < NUM_COMP );
-    assert( 0.0 <= calc_lead_tissue_limit && calc_lead_tissue_limit <= 14.0);
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// calc_nullzeit
+// calc_NDL_time
 //
 // calculates the remaining bottom time
 //
@@ -2397,97 +2490,153 @@
 //       exponential term to the M-value equation, making it impossible to
 //       invert... So we have to make a fast-simu until we find a better way.
 //
-// Input:  pres_respiration
-// Output: char_O_nullzeit / char_O_alternate_nullzeit
+// Input:  ppN2
+//         ppHe
 //
-static void calc_nullzeit(void)
+// Output: NDL_time
+//
+static void calc_NDL_time(void)
 {
-	overlay unsigned char nullzeit = 240;
-	
-	
-    //---- Compute ppN2 and ppHe ---------------------------------------------
-    temp_deco = pres_respiration;
-    sim_alveolar_presures();
-	
-    for(ci=0; ci<NUM_COMP; ci++)
-    {
-        //---- Read A/B values and loading factor for N2 and He --------------
-
-		overlay float tN2 = sim_pres_tissue_N2[ci];
-        overlay float tHe = sim_pres_tissue_He[ci];
+	overlay unsigned char new_NDL_lead_tissue = 0;
+	overlay unsigned char i;
+
+
+	// initialize NDL_time to 240 minutes
+	NDL_time = 240;
+
+	for(i=0; i<NUM_COMP; i++)
+	{
+		overlay float calc_pres_tissue_N2;
+		overlay float calc_pres_tissue_He;
+		overlay float pres_tissue;
+
+		overlay unsigned char NDL_tissue;
+		overlay unsigned char period = 10;		// start with 10 minute periods
+
+
+		// check lead tissue from last NDL computation first
+		ci = i + NDL_lead_tissue;
+
+		// wrap around after the 16th tissue
+		if( ci >= NUM_COMP ) ci -= NUM_COMP;
+
+		// read Buhlmann a and b coefficients for tissue ci
+		read_Buhlmann_coefficients();
+
+		// read the loading factors for 10 minute periods
+		read_Buhlmann_times(2);
 		
-        overlay float t = tN2 + tHe;
-        overlay unsigned char ndl;
-        overlay unsigned char period = 10;
-
-        read_Buhlmann_coefficients();
-        read_Buhlmann_times(2);             // Starts with a 10min period.
-
-        //---- Simulate for that tissue --------------------------------------
-        // NOTE: No need to simulate for longer than the already found NDL.
-		for(ndl=0; ndl<nullzeit;)
-        {
-			//---- Compute updated mix M-value at surface
-			overlay float a = (var_N2_a * tN2 + var_He_a * tHe) / t;
-			overlay float b = (var_N2_b * tN2 + var_He_b * tHe) / t;
-			overlay float M0 = (a + pres_surface/b);
-
-			//---- Add 10min/1min to N2/He tissues
-			overlay float dTN2 = (ppN2 - tN2) * var_N2_e;
-			overlay float dTHe = (ppHe - tHe) * var_He_e;
-
-			//---- Apply safety margin for both models
-			// NDL can be computed while ascending... SO we have
-			// to check if we are saturating or desaturating.
-			if( dTN2 > 0.0 ) dTN2 *= float_saturation_multiplier;
-			else             dTN2 *= float_desaturation_multiplier;
-
-			if( dTHe > 0.0 ) dTHe *= float_saturation_multiplier;
-			else             dTHe *= float_saturation_multiplier;
-
-			// adopt M0 value when using the GF extension
-			if (char_I_deco_model != 0 ) M0 = GF_high * (M0 - pres_surface) + pres_surface;
-
-            //---- Simulate off-gassing while going to surface
-            // TODO !
-            // dTN2 -= exp( ... ascent time ... ppN2...)
-            // dTHe -= exp( ... ascent time ... ppHe...)
-
-            //---- Ok now, and still ok to surface after 1 or 10 minutes ?
-            if( (t <= M0) && (t + dTN2 + dTHe <= M0) )
-            {
-                tN2 += dTN2;		// YES: apply gas loadings,
-                tHe += dTHe;
-				t    = tN2 + tHe;				
+		// get the tissue pressures for N2 and He
+		calc_pres_tissue_N2 = sim_pres_tissue_N2[ci];
+		calc_pres_tissue_He = sim_pres_tissue_He[ci];
+
+		// calculate the total pressure tissue
+		pres_tissue = calc_pres_tissue_N2 + calc_pres_tissue_He;
+
+
+		// simulate an increasing bottom time and check when we hit the NDL ------------------------
+		for( NDL_tissue = 0; NDL_tissue < NDL_time; )	// not needed to simulate for longer than the already found NDL
+		{
+			overlay float var_a;
+			overlay float var_b;
+			overlay float pres_limit;
+			overlay float delta_pres_tissue_N2;
+			overlay float delta_pres_tissue_He;
+
+
+			// adopt a and b coefficients to current N2/He ratio inside the tissue
+			var_a = (var_N2_a * calc_pres_tissue_N2 + var_He_a * calc_pres_tissue_He) / pres_tissue;
+			var_b = (var_N2_b * calc_pres_tissue_N2 + var_He_b * calc_pres_tissue_He) / pres_tissue;
+
+			// compute pressure limit for tissues under surface pressure conditions
+			pres_limit = (var_a + pres_surface / var_b);
+
+			// adopt pressure limit when using the GF extension
+			if (char_I_deco_model != 0 ) pres_limit = GF_high * (pres_limit - pres_surface) + pres_surface;
+
+			//---- Check if this tissue is already beyond the NDL
+			if( pres_tissue > pres_limit)
+			{
+				// NO - finish the outer loop,
+				i = NUM_COMP;
+
+				// and finish the inner loop
+				break;
+			}
+
+			// compute delta to tissue pressures in 10 or 1 minutes of time ahead
+			delta_pres_tissue_N2 = (ppN2 - calc_pres_tissue_N2) * var_N2_e;
+			delta_pres_tissue_He = (ppHe - calc_pres_tissue_He) * var_He_e;
+
+			// apply safety factors to the pressure deltas
+			// NDL can be computed while ascending, so we have to check if we are saturating or desaturating
+			if( delta_pres_tissue_N2 > 0.0 ) delta_pres_tissue_N2 *= float_saturation_multiplier;
+			else                             delta_pres_tissue_N2 *= float_desaturation_multiplier;
+
+			if( delta_pres_tissue_He > 0.0 ) delta_pres_tissue_He *= float_saturation_multiplier;
+			else                             delta_pres_tissue_He *= float_saturation_multiplier;
+
+			// Simulate off-gassing while going to surface
+			// TODO !
+			// delta_pres_tissue_N2 -= exp( ... ascent time ... ppN2...)
+			// delta_pres_tissue_He -= exp( ... ascent time ... ppHe...)
+
+			// within NDL now, but still within in 10 or 1 minutes from now?
+			if( pres_tissue + delta_pres_tissue_N2 + delta_pres_tissue_He <= pres_limit )
+			{
+				// YES - apply the pressure deltas to tissues
+				calc_pres_tissue_N2 += delta_pres_tissue_N2;
+				calc_pres_tissue_He += delta_pres_tissue_He;
 				
-                ndl += period;		// increment NDL,
-
-                continue;			// and loop.
-            }
-
-            //---- Should we retry with smaller steps ?
-            if( period == 10 )
-            {
-                read_Buhlmann_times(1); // 1min coefs.
-                period = 1;
-
-                continue;
-            }
-
-            //---- ELSE make a linear approx for the last minute
-            // Useful to have a meaningful rounding of NDL.
-            // But ONLY if positive (negative casted to unsigned is bad).
-            if( M0 > t ) ndl += (unsigned char)(0.5f + (M0-t)/(dTN2+dTHe));
-			
-            break;
-        }
-
-        // Keep the shortest NDL found
-		if ( ndl < nullzeit ) nullzeit = ndl;
-    }
-	
-	if( char_O_deco_status & DECO_PLAN_ALTERNATE) char_O_alternate_nullzeit = nullzeit;
-	else                                          char_O_nullzeit           = nullzeit;
+				// update the overall tissue pressure
+				pres_tissue = calc_pres_tissue_N2 + calc_pres_tissue_He;
+
+				// increment the NDL
+				NDL_tissue += period;
+
+				// do next loop
+				continue;
+			}
+
+			// NO - if delta pressures were for 10 minutes of time ahead, try with 1 minute ahead
+			if( period == 10 )
+			{
+				// reduce period to 1 minute
+				period = 1;
+
+				// read the loading factors for 1 minute periods
+				read_Buhlmann_times(1);
+
+				// do next loop
+				continue;
+			}
+
+			// NO - not even within NDL in just one more minute, so make a linear approx for the last minute
+			// (make a meaningful rounding of NDL, but ONLY if positive: negative casted to unsigned is bad)
+			if( pres_limit > pres_tissue )
+				NDL_tissue += (unsigned char)(0.5 +    (pres_limit           - pres_tissue         )
+			                                  / (delta_pres_tissue_N2 + delta_pres_tissue_He) );
+
+			// finish the inner loop
+			break;
+		}
+
+		// is the current NDL short than the shortest so far?
+		if ( NDL_tissue < NDL_time )
+		{
+			// keep the current's tissue NDL as the new shortest NDL
+			NDL_time = NDL_tissue;
+
+			// store the causing tissue
+			new_NDL_lead_tissue = ci;
+		}
+		
+		// if NDL is > 0 the outer loop will continues with the next tissue
+		// if NDL found to be overrun, outer loop will be terminated through i = NUM_COMP statement
+	}
+
+	// store the NDL dominating tissue for to start with in the next NDL calculation
+	NDL_lead_tissue = new_NDL_lead_tissue;
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -2496,22 +2645,27 @@
 // Sum up ascent from bottom to surface at float_ascent_speed,
 // but 1 minute per meter for the final ascent, and all stops.
 //
-// Result in int_O_ascenttime,
-//        or int_O_alternate_ascenttime if doing the alternative plan.
+// Input:  char_I_depth_last_deco
+//         pres_respiration
+//         pres_surface
+//         float_ascent_speed
+//         internal_deco_depth[]
+//
+// Output: ascent_time
 //
 static void calc_ascenttime(void)
 {
-    overlay unsigned char  x;
-    overlay unsigned short sum;
-	
+	overlay unsigned char x;
+
+
 	// preset final ascent
 	overlay float final  = (float)char_I_depth_last_deco;
 
-    // calculate depth
-    overlay float ascent = (pres_respiration - pres_surface) * BAR_TO_METER;
-	
+	// calculate depth
+	overlay float ascent = (pres_respiration - pres_surface) * BAR_TO_METER;
+
 	// check if we are already in final ascent
-    if (ascent <= final)
+	if (ascent <= final)
 	{
 		// yes - all ascent is final ascent
 		final  = ascent;
@@ -2521,99 +2675,28 @@
 	{
 		// no - subtract final ascent part from overall ascent
 		ascent -= final;
-		
+
 		// compute time for ascent part without final ascent
-		ascent /= float_ascent_speed;		
+		ascent /= float_ascent_speed;
 	}
-	
-	// add 1 minute for each meter of  final ascent
+
+	// add 1 minute for each meter of final ascent
 	ascent += final;
-	
+
 	// convert to integer
-    sum = (unsigned short)(ascent + 0.5);
+	ascent_time = (unsigned short)(ascent + 0.5);
 
 	// add all stop times
-    for(x=0; x<NUM_STOPS && internal_deco_depth[x]; x++)
-        sum += (unsigned short)internal_deco_time[x];
+	for(x=0; x<NUM_STOPS && internal_deco_depth[x]; x++)
+		ascent_time += (unsigned short)internal_deco_time[x];
 
 	// limit result to display max.
-	if( sum > 999) sum = 999;
-	
+	if( ascent_time > 999) ascent_time = 999;
+
 	// tag result as invalid if there is an overflow in the stops table
-	if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW ) sum |= INT_FLAG_INVALID;
-	
-	// route result to output variable
-	if( char_O_deco_status & DECO_PLAN_ALTERNATE ) int_O_alternate_ascenttime = sum;
-    else                                           int_O_ascenttime           = sum;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// update_startvalues
-//
-// updated in v.102
-//
-void update_startvalues(void)
-{
-    overlay unsigned char x;
-
-    // Start ascent simulation with current tissue partial pressures.
-    for(x=0; x<NUM_COMP; x++)
-    {
-        sim_pres_tissue_N2[x] = pres_tissue_N2[x];
-        sim_pres_tissue_He[x] = pres_tissue_He[x];
-    }
-
-    // No leading tissue (yet) for this ascent simulation.
-    sim_lead_tissue_limit = 0.0;
-    sim_lead_tissue_no    = 1;
+	if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW ) ascent_time |= INT_FLAG_INVALID;
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// sim_limit()
-//
-// New in v.111
-//
-// Function separated from calc_tissue() to allow recomputing limit on
-// different depth, because it depends on current gradient factor.
-//
-static void sim_limit(PARAMETER float GF_current)
-{
-    assert( 0.0 < GF_current && GF_current <= 1.0 );
-
-    sim_lead_tissue_limit = 0.0;
-    sim_lead_tissue_no    = 0;		// If no one is critic, keep first tissue.
-
-    for(ci=0; ci<NUM_COMP; ci++)
-    {
-        overlay float N2 = sim_pres_tissue_N2[ci];
-        overlay float He = sim_pres_tissue_He[ci];
-        overlay float p = N2 + He;
-
-        read_Buhlmann_coefficients();
-        var_N2_a = (var_N2_a * N2 + var_He_a * He) / p;
-        var_N2_b = (var_N2_b * N2 + var_He_b * He) / p;
-
-        // Apply the Eric Baker's varying gradient factor correction.
-        // Note: the correction factor depends both on GF and b,
-        //       Actual values are in the 1.5 .. 1.0 range (for a GF=30%),
-        //       so that can change who is the leading gas...
-        // Note: Also depends of the GF_current...
-		if( char_I_deco_model != 0 )  p =   ( p                - (var_N2_a   * GF_current) )
-		                                  / ( 1.0 - GF_current + (GF_current / var_N2_b  ) );
-
-		else                          p =   (p - var_N2_a) * var_N2_b;
-
-
-        if( p > sim_lead_tissue_limit )
-        {
-            sim_lead_tissue_no    = ci;
-            sim_lead_tissue_limit = p;
-        }
-    } // for ci
-
-    assert( sim_lead_tissue_no < NUM_COMP );
-    assert( 0.0 <= sim_lead_tissue_limit && sim_lead_tissue_limit <= 14.0 );
-}
 
 //////////////////////////////////////////////////////////////////////////////
 // clear_deco_table
@@ -2621,14 +2704,14 @@
 //
 static void clear_deco_table(void)
 {
-    overlay unsigned char x;
-
-    for(x=0; x<NUM_STOPS; ++x)
-    {
-        internal_deco_time [x] = 0;
-        internal_deco_depth[x] = 0;
-    }
-	
+	overlay unsigned char x;
+
+	for(x=0; x<NUM_STOPS; ++x)
+	{
+		internal_deco_time [x] = 0;
+		internal_deco_depth[x] = 0;
+	}
+
 	// clear stop table overflow warning
 	char_O_deco_warnings &= ~DECO_WARNING_STOPTABLE_OVERFLOW;
 }
@@ -2636,15 +2719,15 @@
 //////////////////////////////////////////////////////////////////////////////
 // update_deco_table
 //
-// Add time to a stop at temp_depth_limit
+// Add time to a stop at sim_depth_limit
 //
 // It is possible to create stops with a duration of 0 minutes, e.g. to
 // note a gas change "on the fly" while ascending. Therefore the criteria
 // to have reached the end of the list needs always to be depth == 0.
 //
-// Input:   temp_depth_limit  : stop's depth, in meters.
+// Input:   sim_depth_limit  : stop's depth, in meters.
 //          sim_gas_last_used : gas used at stop, as index 1..5 or 0 for gas 6
-//			PARAMETER time_increment    : number of minutes to add to the stop
+//          PARAMETER time_increment    : number of minutes to add to the stop
 //
 // Updated: internal_deco_depth[] : depth    (in meters)  of each stop
 //          internal_deco_time [] : time     (in minutes) of each stop
@@ -2654,16 +2737,16 @@
 {
 	overlay unsigned char x;
 
-	assert( temp_depth_limit > 0 );		// No stop at surface...
+	assert( sim_depth_limit > 0 );		// No stop at surface...
 
 	// loop through internal deco table
 	for(x=0; x<NUM_STOPS; ++x)
 	{
 		// Make sure deco-stops are recorded in order:
-		assert( !internal_deco_depth[x] || temp_depth_limit <= internal_deco_depth[x] );
+		assert( !internal_deco_depth[x] || sim_depth_limit <= internal_deco_depth[x] );
 
 		// Is there already a stop entry for our current depth?
-		if( internal_deco_depth[x] == temp_depth_limit )
+		if( internal_deco_depth[x] == sim_depth_limit )
 		{
 			// Yes - increment stop time if possible
 			// Stop time entries are limited to 99 minutes because of display constraints.
@@ -2681,82 +2764,21 @@
 		if( internal_deco_depth[x] == 0 )
 		{
 			internal_deco_time[x]  = time_increment;		// initialize entry with first stop's time,
-			internal_deco_depth[x] = temp_depth_limit;		// ... depth, and
+			internal_deco_depth[x] = sim_depth_limit;		// ... depth, and
 			internal_deco_gas[x]   = sim_gas_last_used;		// ... gas
 			return 1;										// return with status 'success'
 		}
 	}
 
 	// If program flow passes here, all deco table entries are used up.
-	
+
 	// set overflow warning
 	char_O_deco_warnings |= DECO_WARNING_STOPTABLE_OVERFLOW;
-	
-	
+
 	// return with status 'failed'.
 	return 0;
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// calc_gradient_factor
-//
-// optimized in v.101 (var_N2_a)
-// new code in v.102
-//
-static void calc_gradient_factor(void)
-{
-    overlay float gf;
-    overlay float N2 = pres_tissue_N2[char_O_gtissue_no];
-    overlay float He = pres_tissue_He[char_O_gtissue_no];
-
-    assert( char_O_gtissue_no < NUM_COMP );
-    assert( 0.800 <= pres_respiration && pres_respiration < 14.0 );
-
-    // tissue > respiration (currently off-gassing)
-    // GF = 0.00 when respiration == tissue, ie. dissolved gases are at equilibrium.
-    // GF = 1.00 when respiration == limit.
-    temp_tissue = N2 + He;
-    if( temp_tissue <= pres_respiration )
-	{
-        gf = 0.0;
-		int_O_gradient_factor = 0;
-	}
-    else
-    {
-        overlay float limit = calc_lead_tissue_limit;
-        // NOTE: in GF model, calc_lead_tissue_limit include already the
-        //       correction due to gradient factor. To compute the actual
-        //       current GF, we need to (re-)compute the raw ambient-pressure
-        //       limit from the Buhlmann model.
-        if( char_I_deco_model != 0 )
-        {
-            ci = char_O_gtissue_no;
-
-            read_Buhlmann_coefficients();
-
-            var_N2_a = (var_N2_a * N2 + var_He_a * He) / temp_tissue;
-            var_N2_b = (var_N2_b * N2 + var_He_b * He) / temp_tissue;
-
-            limit    = (temp_tissue - var_N2_a) * var_N2_b;
-        }
-
-        gf = (temp_tissue - pres_respiration) / (temp_tissue - limit);
-		
-		// limit to 255 because of constraints in ghostwriter code
-		if     ( gf <= 0.0   ) int_O_gradient_factor = 0;
-        else if( gf >  2.545 ) int_O_gradient_factor = 255 + INT_FLAG_WARNING;
-        else
-		{
-			int_O_gradient_factor = (unsigned int)(100 * gf + 0.5);
-		
-			if 		( int_O_gradient_factor >= GF_warning_threshold      )
-				int_O_gradient_factor |= INT_FLAG_WARNING;
-
-			else if ( int_O_gradient_factor >= char_I_GF_High_percentage )
-				int_O_gradient_factor |= INT_FLAG_PREWARNING;
-		}
-	}
-}
 
 //////////////////////////////////////////////////////////////////////////////
 // calc_desaturation_time
@@ -2768,21 +2790,22 @@
 //
 void calc_desaturation_time_helper(void)
 {
-	if( pres_actual > pres_target )					// check if actual pressure is higher then target pressure
-	{												// YES - compute remaining time
+	if( pres_actual > pres_target )		// check if actual pressure is higher then target pressure
+	{									// YES - compute remaining time
 		overlay	float pres_ratio;
-		
+
 		pres_ratio = pres_actual / pres_target;
 
 		// Compute desaturation time with result rounded up to multiples of 10 minutes.
-		// Main purpose is to avoid confusion, because the times do not clock down in one minute steps any more
-		// but get constantly re-computed according to current ambient pressure and may therefor make steps of
-		// several minutes forwards and backwards as ambient pressure rises and falls.
-		short_time = (unsigned short)( (var_ht * log(pres_ratio) / desat_factor) + 0.9 );
+		// Main purpose is to avoid confusion, because the times do not clock down in
+		// one minute steps any more but get constantly re-computed according to current
+		// ambient pressure and may therefor make steps of several minutes forwards and
+		// backwards as ambient pressure rises and falls.
+		int_time = (unsigned int)( (var_ht * log(pres_ratio) / desat_factor) + 0.9 );
 	}
 	else
-	{												// NO  - desaturation state reached, no remaining time
-		short_time = 0;
+	{									// NO  - desaturation state reached, no remaining time
+		int_time = 0;
 	}
 }
 
@@ -2791,34 +2814,42 @@
 //
 void calc_desaturation_time(void)
 {
-    assert( 800 < int_I_pres_surface             && int_I_pres_surface             < 1100 );
-    assert( 0   < char_I_desaturation_multiplier && char_I_desaturation_multiplier <= 100 );
-
-
-    N2_ratio       = 0.7902; 															// fraction of N2 in respired air
-	pres_surface   = 0.001    * int_I_pres_surface;										// surface pressure in bar
-	N2_equilibrium = N2_ratio * (pres_surface - ppWater); 								// partial pressure of N2 in respired air
-	desat_factor   = 0.06931  * char_I_desaturation_multiplier * SURFACE_DESAT_FACTOR;	// pre-computed term for later use: 
-																						// 10 [Min] * 0.01 [%] * 0.6931 [ln(2)] * ...
+	assert( 800 < int_I_pres_surface             && int_I_pres_surface             < 1100 );
+	assert( 0   < char_I_desaturation_multiplier && char_I_desaturation_multiplier <= 100 );
+
+	// fraction of inert gases in respired air
+	N2_ratio       = 0.7902;
+	He_ratio       = 0.0;
+
+	// surface pressure in bar
+	pres_surface   = 0.001    * int_I_pres_surface;
+
+	// partial pressure of N2 in respired air
+	N2_equilibrium = N2_ratio * (pres_surface - ppWater);
+
+	// pre-computed term for later use: 10 [Min] * 0.01 [%] * 0.6931 [=log(2)] * ...
+	desat_factor   = 0.06931  * char_I_desaturation_multiplier * SURFACE_DESAT_FACTOR;
+
+	// initialize vars
 	int_O_desaturation_time = 0;
-	int_O_nofly_time		= 0;
-	
-
-    for(ci=NUM_COMP; ci>0;)
-    {
-		overlay float			pres_tissue_max;
-		overlay float			P_ambient_altitude;
-		overlay signed char		search_direction;
-		overlay unsigned short	nofly_N2   =  0;
-		overlay unsigned short	nofly_He   =  0;
-		overlay unsigned short	nofly_last = ~0;
-
-		
+	int_O_nofly_time        = 0;
+
+
+	for(ci=NUM_COMP; ci>0;)
+	{
+		overlay float        pres_tissue_max;
+		overlay float        P_ambient_altitude;
+		overlay signed char  search_direction;
+		overlay unsigned int nofly_N2   =  0;
+		overlay unsigned int nofly_He   =  0;
+		overlay unsigned int nofly_last = ~0;
+
+
 		ci -= 1;
-		
-        read_Buhlmann_ht();
+
+		read_Buhlmann_ht();
 		read_Buhlmann_coefficients();
-		
+
 		// get selected target altitude
 		switch( char_I_altitude_wait )
 		{
@@ -2827,19 +2858,18 @@
 			case 3:  P_ambient_altitude = P_ambient_3000m;	break;
 			default: P_ambient_altitude = P_ambient_fly;	break;
 		}
-		
+
 		// Target pressure for the tissue is the Buhlmann limit. We use the Buhlmann
 		// coefficients for N2 also for He because it is easier to calculate and the
 		// N2 coefficients are more conservative than those for He, so we are on the
 		// safe side, too.
-        pres_tissue_max = (P_ambient_altitude/var_N2_b + var_N2_a);
-		
+		pres_tissue_max = (P_ambient_altitude/var_N2_b + var_N2_a);
+
 		// Adjust target pressure in case the GF model is in use by GF-high
 		if( char_I_deco_model != 0 )
-		{
-			pres_tissue_max = ((pres_tissue_max - P_ambient_altitude) * char_I_GF_High_percentage * 0.01) + P_ambient_altitude;			
-		}
-		
+			pres_tissue_max = P_ambient_altitude +
+			                  0.01 * char_I_GF_High_percentage * (pres_tissue_max - P_ambient_altitude);
+
 
 		//
 		// Desaturation time
@@ -2849,7 +2879,7 @@
 		pres_actual = pres_tissue_N2[ci] - N2_equilibrium;
 		
 		// N2: half-time of the current tissue
-		var_ht		= var_N2_ht;
+		var_ht      = var_N2_ht;
 
 		// Calculate desaturation time for N2 in tissue.
 		// Desaturated state is defined as residual tissue pressure <= 1.05 x ppN2 respired
@@ -2858,15 +2888,15 @@
 
 		calc_desaturation_time_helper();
 
-		if( short_time > int_O_desaturation_time) int_O_desaturation_time = short_time;
-
-
-		// He: actual amount of tissue pressure above equilibrium.
-		pres_actual = pres_tissue_He[ci];								// equilibrium for He is 0 bar
+		if( int_time > int_O_desaturation_time) int_O_desaturation_time = int_time;
+
+
+		// He: actual amount of tissue pressure above equilibrium: equilibrium for He is 0 bar
+		pres_actual = pres_tissue_He[ci];
 
 		// He: half-time of the current tissue
-		var_ht		= var_He_ht;
-		
+		var_ht      = var_He_ht;
+
 		// Calculate desaturation time for He in the tissue.
 		// Desaturated state is defined as residual tissue pressure <= 0.05 x ppN2 respired
 
@@ -2874,7 +2904,7 @@
 
 		calc_desaturation_time_helper();
 
-		if( short_time > int_O_desaturation_time) int_O_desaturation_time = short_time;			
+		if( int_time > int_O_desaturation_time) int_O_desaturation_time = int_time;
 
 
 		//
@@ -2883,15 +2913,15 @@
 
 		// initialize search direction
 		search_direction = 0;
-		
+
 		for(;;)
 		{
 			// N2: actual amount of tissue pressure above equilibrium.
 			pres_actual = pres_tissue_N2[ci] - N2_equilibrium;
-		
+
 			// N2: half-time of the current tissue
-			var_ht		= var_N2_ht;
-		
+			var_ht      = var_N2_ht;
+
 			// Calculate no-fly time for N2 in the tissue.
 			// Flying is permitted when the N2 pressure fits into the assigned fraction above equilibrium.
 
@@ -2905,22 +2935,22 @@
 			else 
 			{
 				calc_desaturation_time_helper();
-				nofly_N2 = short_time;
+				nofly_N2 = int_time;
 			}
-		
+
 			// He: actual amount of tissue pressure above equilibrium - equilibrium for He is 0 bar.
 			pres_actual = pres_tissue_He[ci];
 
 			// He: half-time of the current tissue
-			var_ht		= var_He_ht;
-		
+			var_ht      = var_He_ht;
+
 			// Calculate no-fly time for He in the tissue.
 			// Flying is permitted when the He pressure fits into the assigned fraction.
 
-			pres_target = ((100 - split_N2_He[ci]) * 0.01) * (pres_tissue_max - N2_equilibrium);
+			pres_target = (0.01 * (100 - split_N2_He[ci])) * (pres_tissue_max - N2_equilibrium);
 
 			calc_desaturation_time_helper();
-			nofly_He = short_time;
+			nofly_He = int_time;
 
 
 			// Because the sum of N2 and He tissue pressures needs to fit into the Buhlmann limit for
@@ -2931,12 +2961,12 @@
 			// in the deco calculation code (although we tackle the same base problem here), so we just let
 			// the computer try out which split will balance the no-fly times induced by the N2 and the He
 			// at best.
-			
+
 			// first of all, skip any optimization in case the current compartment is not the leading one
 			if( (nofly_N2 <= int_O_nofly_time) && (nofly_He <= int_O_nofly_time) ) break;
 
 			// check if the N2 requires more waiting time than the He
-			if( nofly_N2 >= nofly_He )							
+			if( nofly_N2 >= nofly_He )
 			{
 				// check if the search direction has changed, which means we are beyond the
 				// optimum now, or if we are at the upper stop limit of split_N2_He
@@ -2949,8 +2979,8 @@
 				}
 
 				// store the no-fly time found in this iteration
-				nofly_last = nofly_N2;				
-				
+				nofly_last = nofly_N2;
+
 				// increase the N2 fraction of the split and set search direction towards more N2
 				split_N2_He[ci]  +=  1;
 				search_direction  = +1;
@@ -2960,7 +2990,7 @@
 				// check if the search direction has changed, which means we are beyond the
 				// optimum now, or if we are at the lower stop limit of split_N2_He
 				if( (search_direction > 0) || (split_N2_He[ci] == 1) )
-				{	
+				{
 					// Either the just completed iteration was more close to the optimum or the one before
 					// was, so we take the best (i.e. shortest) time of both as the final no-fly time.
 					int_O_nofly_time = (nofly_He < nofly_last) ? nofly_He : nofly_last;
@@ -2968,388 +2998,292 @@
 				}
 
 				// store the no-fly time found in this iteration
-				nofly_last = nofly_He;				
-				
+				nofly_last = nofly_He;
+
 				// decrease the N2 fraction of the split and set search direction towards less N2
 				split_N2_He[ci]  -=  1;
 				search_direction  = -1;	
 			}
-			
+
 		} // for(;;)
 
 	} // for(compartments)
 
-		
+
 	// Rescale int_O_desaturation_time and int_O_nofly_time to full minutes for display purpose
 	int_O_desaturation_time *= 10;
 	int_O_nofly_time		*= 10;
-		
+
 	// Limit int_O_desaturation_time and int_O_nofly_time to 5999 = 99 hours + 59 minutes
 	// because of display space constraints and rounding done above.
 	if( int_O_desaturation_time > 5999 ) int_O_desaturation_time = 5999;
 	if( int_O_nofly_time        > 5999 ) int_O_nofly_time        = 5999;
 
 
-	// Clear the microbubbles warning when the current gradient factor is < GF_warning_threshold.
+	// Clear the microbubbles warning when the current gradient factor is < GF_WARNING_THRESHOLD.
 	// As the locked warning will stay set, this will cause the warning be be displayed in attention
 	// color instead of warning color.
-	if( int_O_gradient_factor < GF_warning_threshold ) char_O_deco_warnings &= ~DECO_WARNING_MBUBBLES;
-	
+	if( int_O_gradient_factor < GF_WARNING_THRESHOLD )
+		char_O_deco_warnings &= ~DECO_WARNING_MBUBBLES;
+
 	// clear some warnings when the desaturation time has become zero
-	if( int_O_desaturation_time == 0 ) char_O_deco_warnings &= ~(   DECO_WARNING_IBCD     + DECO_WARNING_IBCD_lock
-																  + DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock
-																  + DECO_WARNING_OUTSIDE  + DECO_WARNING_OUTSIDE_lock  );
+	if( int_O_desaturation_time == 0 )
+		char_O_deco_warnings &= ~(   DECO_WARNING_IBCD     + DECO_WARNING_IBCD_lock
+		                           + DECO_WARNING_MBUBBLES + DECO_WARNING_MBUBBLES_lock
+		                           + DECO_WARNING_OUTSIDE  + DECO_WARNING_OUTSIDE_lock  );
 
 }
 
 //////////////////////////////////////////////////////////////////////////////
-// calc_wo_deco_step_1_min
+// Calculate desaturation of the real tissues for a given time interval
 //
-// optimized in v.101 (...saturation_multiplier)
-// desaturation slowed down to 70,42%
+// Caution: Works on the real tissues!
+//          If in doubt, use this function only inside a context surrounded with
+//          push_tissues_to_vault() / pull_tissues_from_vault() !
+//
+// Input:    int_I_pres_surface : surface pressure in mbar
+//           time_interval      : time interval in minutes, must be limited to 254 at max
 //
-// Input: int_I_pres_surface [mbar]
+// Modified: tissue pressures
+//           CNS value
+//           ceiling and current GF
 //
-static void calc_wo_deco_step_1_min(void)
+static void calc_interval(PARAMETER unsigned char time_interval)
 {
-    assert( 800 <  int_I_pres_surface             && int_I_pres_surface             <  1100 );
-    assert( 100 <= char_I_saturation_multiplier   && char_I_saturation_multiplier   <  200  );
-    assert( 0   <  char_I_desaturation_multiplier && char_I_desaturation_multiplier <= 100  );
+	overlay unsigned char time;
+
+
+	assert( 800 <  int_I_pres_surface             && int_I_pres_surface             <  1100 );
+	assert( 100 <= char_I_saturation_multiplier   && char_I_saturation_multiplier   <  200  );
+	assert( 0   <  char_I_desaturation_multiplier && char_I_desaturation_multiplier <= 100  );
+
 
 	// setup input data for deco routines
-    pres_respiration = pres_surface = int_I_pres_surface * 0.001;
-	
-	N2_ratio       = 0.7902; 									// according to Buhlmann
+	pres_respiration = pres_surface = 0.001 * int_I_pres_surface ;
+
+	N2_ratio       = 0.7902;									// according to Buhlmann
 	N2_equilibrium = N2_ratio * (pres_surface     - ppWater);	// used for N2 tissue graphics scaling
-    ppN2           = N2_ratio * (pres_respiration - ppWater);
-    ppHe           = 0.0;
-
-    float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01 * SURFACE_DESAT_FACTOR;
-    float_saturation_multiplier   = char_I_saturation_multiplier   * 0.01;
-
-
-	// program what to do: 128 = Flag for "real" tissues, 1 = 1 minute
-	tissue_increment = 128 + 1;
-
-	// update the pressure in the tissues N2/He in accordance with the new ambient pressure
-	calc_tissue();
-
-	// clock down CNS by a 1 minute step
-	//CNS_fraction *= 0.992327946;				// is done in deco_calc_CNS_decrease_15min
-
-	// compute integer copy of CNS value
-	//compute_CNS_for_display();				// is done in deco_calc_CNS_decrease_15min
-
-	// reset deco engine start condition (probably not needed to be done here...)
-	char_O_deco_status &= ~DECO_STATUS_MASK;	// clear bits
-	char_O_deco_status |= DECO_STATUS_INIT;		// set bits
-
-	// reset some more data that are not applicable in surface mode
-    char_O_nullzeit            = 0;
-    int_O_ascenttime           = 0;
-	int_O_alternate_ascenttime = 0;
-	clear_deco_table();
-	
-	// calculate gradient factor
-    calc_gradient_factor();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// calc_dive_interval
-//
-// Prepare tissue for delay before the next dive simulation.
-//
-// Inputs:   char_I_dive_interval == delay before dive (in 1 Minute steps).
-// Modified: CNS_fraction, int_O_CNS_fraction
-// 			 pres_tissue_N2/He[]
-//
-// Should be protected by deco_push_tissues_to_vault(),
-//                        deco_pull_tissues_from_vault()
-//
-// desaturation slowed down to 70,42%.
-//
-static void calc_dive_interval(void)
-{
-    overlay unsigned char t;
-    
-    //---- Initialize simulation parameters ----------------------------------
-    pres_respiration = pres_surface = int_I_pres_surface * 0.001;
-	
-	N2_ratio       = 0.7902; 									// according to buehlmann
-	N2_equilibrium = N2_ratio * (pres_surface     - ppWater);	// used for N2 tissue graphics scaling
-    ppN2           = N2_ratio * (pres_respiration - ppWater);
-    ppHe           = 0.0;
-	
-    float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01 * SURFACE_DESAT_FACTOR;
-    float_saturation_multiplier   = char_I_saturation_multiplier   * 0.01;
-	
-    //---- Perform simulation ------------------------------------------------
-
-	// Calculate tissues:
-	// Because tissue_increment is limited to 127 minutes, we have to do two passes
-	// in case char_I_dive_interval is bigger than 127.
-	// Ops: char_I_dive_interval must be limited to 254!
-
-	t = char_I_dive_interval;
-
-	if ( t == 255 ) t = 254;
-
-	if ( t > 127 )							// extra pass needed?
+	ppN2           = N2_ratio * (pres_respiration - ppWater);
+	ppHe           = 0.0;
+
+	float_desaturation_multiplier = 0.01 * char_I_desaturation_multiplier * SURFACE_DESAT_FACTOR;
+	float_saturation_multiplier   = 0.01 * char_I_saturation_multiplier;
+
+
+	// Calculate the tissues:
+	// Because calc_tissues() can calculate for 127 minutes at max,
+	// the tissue updating may need to be done in two chunks.
+
+	time = time_interval;
+
+	// first chunk for the part exceeding 127 minutes
+	if( time > 127)
 	{
-		tissue_increment = 127				// dive interval length in minutes
-						 | 128;				// Flag to update the "real" tissues			
-		
-		calc_tissue();						// update tissues
-		
-		t -= 127;							// calculate remaining dive interval length
+		// do a full 127 minutes on the real tissues
+		tissue_increment = 127 | TISSUE_FLAG;
+		calc_tissues();
+
+		// determine the remaining part
+		time -= 127;
 	}
 
-	tissue_increment = t 					// dive interval length in minutes to do
-					 | 128;					// Flag to update the "real" tissues
-	calc_tissue();							// update tissues
-	
+	// program the remaining part (or full part if not exceeding 127 minutes)
+	tissue_increment = time | TISSUE_FLAG;
+
+	// update the N2 and He pressures in the tissues for the remaining part of the time interval
+	calc_tissues();
+
 
 	// Calculate CNS:
 	// To speed up things and because on most invocations of this code char_I_dive_interval
 	// is a multiple of 10 minutes, we loop the loop-counter down using two speeds.
 
-	t = char_I_dive_interval;
-
-	while ( t )
+	time = time_interval;
+
+	while ( time )
 	{
-		if( t > 9 )
+		if( time > 9 )
 		{
 			CNS_fraction *= 0.925874712;	// Half-time = 90min -> 10 min: (1/2)^(1/9)
-			t            -= 10;				// fast speed looping
+			time         -= 10;				// fast speed looping
 		}
 		else
 		{
 			CNS_fraction *= 0.992327946;	// Half-time = 90min ->  1 min: (1/2)^(1/90)
-			t            -= 1;				// slow speed looping
+			time         -= 1;				// slow speed looping
 		}
-	}	
+	}
 
 	// compute integer copy of CNS value
-	compute_CNS_for_display();
+	convert_CNS_for_display();
+
+
+	// calculate ceiling (for a GF high of 100%) and gradient factor
+	calc_limit(1.0);
 }
 
-//////////////////////////////////////////////////////////////////////////////
-// clear_CNS_fraction
-//
-// new in v.101
-//
-void clear_CNS_fraction(void)
-{
-	CNS_fraction       = CNS_sim_norm_fraction     = CNS_sim_alt_fraction         = 0;
-	int_O_CNS_fraction = int_O_normal_CNS_fraction = int_O_alternate_CNS_fraction = 0;
-}
 
 //////////////////////////////////////////////////////////////////////////////
-// calc_CNS_fraction
+// calc_CNS_increment
 //
-// Input:  char_actual_ppO2     : current ppO2 [decibars]
-//         tissue_increment  	: time increment and tissue selector
-//         CNS_fraction         : current CNS% as float before period
+// Input:  char_ppO2        : current ppO2 [decibars]
+//         tissue_increment : time increment and tissue selector
+//
+// Output: CNS_fraction_inc : increment of the CNS value
 //
-// Output: CNS_fraction,          int_O_CNS_fraction 			- for the real tissues
-//         CNS_sim_norm_fraction, int_O_normal_CNS_fraction		- in simulation mode, normal plan
-//         CNS_sim_alt_fraction,  int_O_alternate_CNS_fraction  - in simulation mode, alternative plan
-//
-void calc_CNS_fraction(void)
+void calc_CNS_increment(void)
 {
-    overlay float time_factor       = 1.0;		// default is 2sec
-	overlay float CNS_fraction_temp = 0.0;
-	
-    assert( char_actual_ppO2 > 15 );
-	
+	overlay float time_factor = 1.0;	// default is 2sec
+
+	assert( char_ppO2 > 15 );
+
 	// All deco code is now invoked every second. But as the CNS update is based on
 	// 2 seconds periods, we skip every 2nd seconds-based invocation of this function.
-	// 128 = 128 (flag for "real" CNS) + 0 (2 seconds period)
+	// TISSUE_FLAG = 128 (flag for "real" CNS) + 0 (2 seconds period)
 	// To distribute computational load, the CNS% is calculated in "the other second"
 	// than the tissues.
-	if( (tissue_increment == 128) && (twosectimer) ) return;
-	
+	if( (tissue_increment == TISSUE_FLAG) && (twosectimer) ) return;
+
 	// adjust time factor if minute-based stepping is commanded, mask out flag bit
-	if( tissue_increment & 127 ) time_factor = 30.0 * (float)(tissue_increment & 127);
-
-		
-    //------------------------------------------------------------------------
-    // Don't increase CNS below 0.5 bar, but keep it steady.
-    if (char_actual_ppO2 < 50)
-        ;   // no changes
-    //------------------------------------------------------------------------
-    // Below (and including) 1.60 bar
-    else if (char_actual_ppO2 < 61)
-        CNS_fraction_temp = time_factor/(-533.07 * char_actual_ppO2 + 54000.0);
-    else if (char_actual_ppO2 < 71)
-        CNS_fraction_temp = time_factor/(-444.22 * char_actual_ppO2 + 48600.0);
-    else if (char_actual_ppO2 < 81)
-        CNS_fraction_temp = time_factor/(-355.38 * char_actual_ppO2 + 42300.0);
-    else if (char_actual_ppO2 < 91)
-        CNS_fraction_temp = time_factor/(-266.53 * char_actual_ppO2 + 35100.0);
-    else if (char_actual_ppO2 < 111)
-        CNS_fraction_temp = time_factor/(-177.69 * char_actual_ppO2 + 27000.0);
-    else if (char_actual_ppO2 < 152)
-        CNS_fraction_temp = time_factor/( -88.84 * char_actual_ppO2 + 17100.0);
-    else if (char_actual_ppO2 < 167)
-        CNS_fraction_temp = time_factor/(-222.11 * char_actual_ppO2 + 37350.0);
-    //------------------------------------------------------------------------
-    // Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity:
-    // J Appl Physiol 92: 248--256, 2002, doi:10.1152/japplphysiol.00434.2001
-    // Formula (A1) based on value for 1.55 and c=20
-    // example calculation: Sqrt((1.7/1.55)^20)*0.000404
-    else if (char_actual_ppO2 < 172)
-        CNS_fraction_temp = time_factor*0.00102;
-    else if (char_actual_ppO2 < 177)
-        CNS_fraction_temp = time_factor*0.00136;
-    else if (char_actual_ppO2 < 182)
-        CNS_fraction_temp = time_factor*0.00180;
-    else if (char_actual_ppO2 < 187)
-        CNS_fraction_temp = time_factor*0.00237;
-    else if (char_actual_ppO2 < 192)
-        CNS_fraction_temp = time_factor*0.00310;
-    else if (char_actual_ppO2 < 198)
-        CNS_fraction_temp = time_factor*0.00401;
-    else if (char_actual_ppO2 < 203)
-        CNS_fraction_temp = time_factor*0.00517;
-    else if (char_actual_ppO2 < 233)
-        CNS_fraction_temp = time_factor*0.0209;
-    else
-        CNS_fraction_temp = time_factor*0.0482; // value for 2.5 bar, used for 2.33 bar and above
-
-
-	// Check from where we were called:
-	// flag (bit 7) is  set -> we were called from calc_hauptroutine()
-	// flag (bit 7) not set -> we were called from the deco planning routines
-	if       ( tissue_increment   & 128                 ) CNS_fraction          += CNS_fraction_temp;	// real tissues
-	else if  ( char_O_deco_status & DECO_PLAN_ALTERNATE ) CNS_sim_alt_fraction  += CNS_fraction_temp;	// alternative plan
-	     else                                             CNS_sim_norm_fraction += CNS_fraction_temp;	// normal plan
-
+	if( tissue_increment & TIME_MASK ) time_factor = 30.0 * (float)(tissue_increment & TIME_MASK);
+
+
+	//------------------------------------------------------------------------
+	// Don't increase CNS below 0.5 bar, but keep it steady.
+	if      (char_ppO2 <  50) CNS_fraction_inc = 0;				// no CNS increase below 0.5 bar ppO2
+	//------------------------------------------------------------------------
+	// Below (and including) 1.60 bar
+	else if (char_ppO2 <  61) CNS_fraction_inc = time_factor/(-533.07 * char_ppO2 + 54000.0);
+	else if (char_ppO2 <  71) CNS_fraction_inc = time_factor/(-444.22 * char_ppO2 + 48600.0);
+	else if (char_ppO2 <  81) CNS_fraction_inc = time_factor/(-355.38 * char_ppO2 + 42300.0);
+	else if (char_ppO2 <  91) CNS_fraction_inc = time_factor/(-266.53 * char_ppO2 + 35100.0);
+	else if (char_ppO2 < 111) CNS_fraction_inc = time_factor/(-177.69 * char_ppO2 + 27000.0);
+	else if (char_ppO2 < 152) CNS_fraction_inc = time_factor/( -88.84 * char_ppO2 + 17100.0);
+	else if (char_ppO2 < 167) CNS_fraction_inc = time_factor/(-222.11 * char_ppO2 + 37350.0);
+	//------------------------------------------------------------------------
+	// Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity:
+	// J Appl Physiol 92: 248--256, 2002, doi:10.1152/japplphysiol.00434.2001
+	// Formula (A1) based on value for 1.55 and c=20
+	// example calculation: Sqrt((1.7/1.55)^20)*0.000404
+	else if (char_ppO2 < 172) CNS_fraction_inc = time_factor*0.00102;
+	else if (char_ppO2 < 177) CNS_fraction_inc = time_factor*0.00136;
+	else if (char_ppO2 < 182) CNS_fraction_inc = time_factor*0.00180;
+	else if (char_ppO2 < 187) CNS_fraction_inc = time_factor*0.00237;
+	else if (char_ppO2 < 192) CNS_fraction_inc = time_factor*0.00310;
+	else if (char_ppO2 < 198) CNS_fraction_inc = time_factor*0.00401;
+	else if (char_ppO2 < 203) CNS_fraction_inc = time_factor*0.00517;
+	else if (char_ppO2 < 233) CNS_fraction_inc = time_factor*0.0209;
+	else                      CNS_fraction_inc = time_factor*0.0482; // value for 2.5 bar, used for 2.33 bar and above
 }
 
 //////////////////////////////////////////////////////////////////////////////
 // calc_CNS_planning
 //
-// Compute CNS during predicted ascent.
+// Compute CNS increase during predicted ascent
 //
-// Note:    Needs a call to deco_push_tissues_to_vault(),
-//          deco_pull_tissues_from_vault() to avoid trashing everything...
-//
-// Input:   CNS_fraction, internal_deco_time[], internal_deco_depth[], internal_deco_gas[]
-// Output:  CNS_fraction, int_O_normal_CNS_fraction / int_O_alternate_CNS_fraction
+// Input:   internal_deco_time[], internal_deco_depth[], internal_deco_gas[]
+// Output:  sim_CNS_fraction
 //
 void calc_CNS_planning(void)
 {
-	// start with CNS% we already have
-	if( char_O_deco_status & DECO_PLAN_ALTERNATE ) CNS_sim_alt_fraction  = CNS_fraction;
-	else                                           CNS_sim_norm_fraction = CNS_fraction;
-
-	
-    //---- CCR mode : do the full TTS at once ---------------------------------
+	// null sim_CNS_fraction
+	sim_CNS_fraction = 0.0;
+
+	//---- CCR mode : do the full TTS at once ---------------------------------
 
 	if( ((char_O_deco_status & DECO_MODE_MASK) == DECO_MODE_CCR) )
-    {
-		overlay unsigned short t;       				// needs 16 bits here !
+	{
+		overlay unsigned short t;						// needs 16 bits here !
 
 		// get current ppO2 from sensors or setpoint
-        char_actual_ppO2 = char_I_const_ppO2;
+		char_ppO2 = char_I_const_ppO2;
 
 		// calculate CNS% for the period of additional staying at bottom depth (fTTS / delayed ascent)
 		if( char_O_deco_status & DECO_ASCENT_DELAYED)
 		{
-			tissue_increment  = char_I_extra_time;		// must be limited to 127, is limited by range of char_I_extra_time
-			calc_CNS_fraction();
+			tissue_increment = char_I_extra_time;		// must be limited to 127, is limited by range of char_I_extra_time
+			calc_CNS_increment();						// calculate the CNS increment
+			sim_CNS_fraction += CNS_fraction_inc;		// sum up
 		}
-		
+
 		// get the ascent time dependent on the current plan
 		t = (char_O_deco_status & DECO_PLAN_ALTERNATE) ? int_O_alternate_ascenttime : int_O_ascenttime;
-		
+
 		// start simulating CNS% in chunks of 127 minutes
 		tissue_increment = 127;
 
 		while( t > 127 )
 		{
 			t -= 127;									// tissue_increment is limited to 127 minutes because of flag in bit 7
-			calc_CNS_fraction();						// calculate CNS in chunks of full 127 minutes
+			calc_CNS_increment();						// calculate CNS in chunks of full 127 minutes
+			sim_CNS_fraction += CNS_fraction_inc;		// sum up
 		}
 
 		tissue_increment = (char)t;						// get the remaining minutes <= 127
-		calc_CNS_fraction();							// calculate CNS for the remaining minutes
-    }
+		calc_CNS_increment();							// calculate CNS for the remaining minutes
+		sim_CNS_fraction += CNS_fraction_inc;			// sum up
+	}
 	else //---- OC mode and pSCR without sensors: have to follow all gas switches... -----
-    {
+	{
 		overlay float float_actual_ppO2;
 		overlay float abs_pres;
 
 		overlay unsigned char stop_depth;
 		overlay unsigned char last_gas;
-		overlay unsigned char i;    					// stop table index
-
-		
+		overlay unsigned char i;						// stop table index
+
+
 		// retrieve bottom gas: 1-5 for the configured gases or 0 for the manually set gas
 		last_gas = sim_gas_last_used = sim_gas_first_used;
 
 		// get the calc_N2/He/O2_ratios of the bottom gas
-		gas_switch_set();             
+		gas_set_ratios();
 
 		// calculate absolute pressure
 		abs_pres = pres_surface + bottom_depth * METER_TO_BAR;
-		
-		// switch on deco mode pSCR / OC
-		if( char_O_deco_status & DECO_MODE_PSCR )
-		{
-			//---- pSCR calculated --------------------------------------------
-
-			// abs_pres              is 0.0 ...     in bar
-			// calc_O2_ratio		 is 0.0 ...   1.0 as factor
-			// char_I_PSCR_drop      is 0   ...  15 as %
-			// char_I_PSCR_lungratio is 5   ...  20 as %
-			// float_actual_ppO2     is 0.0 ...     in cbar (!)
-
-			float_actual_ppO2 =   (100 * abs_pres * calc_O2_ratio)
-			                    - (1.0 - calc_O2_ratio) * char_I_PSCR_drop * char_I_PSCR_lungratio;
-		}
-		else
-		{
-			//---- OC ---------------------------------------------------------
-			
-			float_actual_ppO2 = abs_pres * calc_O2_ratio * 100; // in cbar (!)
-		}
-	
-		// caution: float_actual_ppO2 is in cbar here!
-		if      ( float_actual_ppO2 < 0.0   ) char_actual_ppO2 =   0;
-        else if ( float_actual_ppO2 > 254.5 ) char_actual_ppO2 = 255;
-        else                                  char_actual_ppO2 = (unsigned char)(float_actual_ppO2 + 0.5);
-		
+
+		// calculate OC ppO2 (ppWater omitted here on purpose)
+		float_actual_ppO2 = abs_pres * sim_O2_ratio;
+
+		// correct ppO2 in case of pSCR mode by drop
+		if( char_O_deco_status & DECO_MODE_PSCR ) float_actual_ppO2 -= sim_pSCR_drop;
+
+		// convert ppO2 from float to char
+		if      ( float_actual_ppO2 < 0.0   ) char_ppO2 =   0;
+		else if ( float_actual_ppO2 > 2.545 ) char_ppO2 = 255;
+		else                                  char_ppO2 = (unsigned char)(100 * float_actual_ppO2 + 0.5);
+
 
 		// simulate extended bottom time (fTTS) / delay before ascent (bailout) if configured
 		if( char_O_deco_status & DECO_ASCENT_DELAYED )
 		{
-			tissue_increment  = char_I_extra_time;		// must be limited to 127, is limited by range of char_I_extra_time
-			calc_CNS_fraction();			
+			tissue_increment  = char_I_extra_time;	// must be limited to 127, is limited by range of char_I_extra_time
+			calc_CNS_increment();					// calculate the CNS increment
+			sim_CNS_fraction += CNS_fraction_inc;	// sum up
 		}
 
-		
+
 		// For simplicity reason (non-linearity of the relation between ppO2 and CNS increments), the
 		// whole ascent is calculated with bottom ppO2. This errs, but it does so to the safe side.
-		
+
 		// calculate ascent time (integer division and generous round-up)
 		tissue_increment = bottom_depth / char_I_ascent_speed + 1;
-		
-		// ** commented out - not needed when char_I_ascent_speed is limited to a
-		// **                 minimum of 2.something, it is indeed limited to 5.
+
+		// ** commented out - not needed when char_I_ascent_speed is limited to a minimum
+		// **                 of 2.something, it is indeed limited to a minimum of 5.
 		//
 		// // limit tissue_increment to 127 minutes
-		// if( tissue_increment > 127 ) tissue_increment = 127;			
+		// if( tissue_increment > 127 ) tissue_increment = 127;
 
 		// simulate the CNS increase
-		calc_CNS_fraction();
-
-
-        //---- Stops ---------------------------------------------------------
+		calc_CNS_increment();						// calculate the CNS increment
+		sim_CNS_fraction += CNS_fraction_inc;		// sum up
+
+
+		//---- Stops ---------------------------------------------------------
 		
-        for(i=0; i<NUM_STOPS; ++i)
-        {
+		for(i=0; i<NUM_STOPS; ++i)
+		{
 			// get the depth of the stop
 			stop_depth = internal_deco_depth[i];
 
@@ -3358,61 +3292,51 @@
 
 			// get the duration of the stop and the gas breathed
 			tissue_increment  = internal_deco_time[i];
-            sim_gas_last_used = internal_deco_gas[i];
-			
-            // do we have a gas switch?
-            if( sim_gas_last_used != last_gas )
-            {
-				// yes - get new calc ratios
-				gas_switch_set();				
+			sim_gas_last_used = internal_deco_gas[i];
+
+			// do we have a gas switch?
+			if( sim_gas_last_used != last_gas )
+			{
+				// yes - get new calculation ratios
+				gas_set_ratios();
 
 				// remember new gas as last gas
 				last_gas = sim_gas_last_used;
 			}
 
-            // calculate absolute pressure at stop depth
+			// calculate absolute pressure at stop depth
 			abs_pres = pres_surface + stop_depth * METER_TO_BAR;
-			
-			// pSCR mode
-			if( char_O_deco_status & DECO_MODE_PSCR )
-			{
-				// abs_pres              is 0.0 ...     in bar
-				// calc_O2_ratio		 is 0.0 ...   1.0 as factor
-				// char_I_PSCR_drop      is 0   ...  15 as %
-				// char_I_PSCR_lungratio is 5   ...  20 as %
-				// float_actual_ppO2     is 0.0 ...     in cbar (!)
-
-				float_actual_ppO2 =   (100 * abs_pres * calc_O2_ratio)
-				                    - (1.0 - calc_O2_ratio) * char_I_PSCR_drop * char_I_PSCR_lungratio;
-			}
-			else // OC mode
-			{
-				float_actual_ppO2 = abs_pres * calc_O2_ratio * 100;	// in cbar (!)
-			}
-
-			// caution: float_actual_ppO2 is in cbar here!
-			if      ( float_actual_ppO2 < 0.0   ) char_actual_ppO2 =   0;
-			else if ( float_actual_ppO2 > 254.5 ) char_actual_ppO2 = 255;
-			else                                  char_actual_ppO2 = (unsigned char)(float_actual_ppO2 + 0.5);
-
-			
+
+			// calculate OC ppO2 (ppWater omitted here on purpose)
+			float_actual_ppO2 = abs_pres * sim_O2_ratio;
+
+			// correct ppO2 in case of pSCR mode by drop
+			if( char_O_deco_status & DECO_MODE_PSCR ) float_actual_ppO2 -= sim_pSCR_drop;
+
+			// convert ppO2 from float to char
+			if      ( float_actual_ppO2 < 0.0   ) char_ppO2 =   0;
+			else if ( float_actual_ppO2 > 2.545 ) char_ppO2 = 255;
+			else                                  char_ppO2 = (unsigned char)(100 * float_actual_ppO2 + 0.5);
+
 			// ** Currently, stop times per stop entry are limited to 99 minutes in update_deco_table(),
 			// ** so the following code block is not needed at times.
 			//
-			// // tissue_increment is limited to 127 when fed to deco_calc_CNS_fraction(),
+			// // tissue_increment is limited to 127 when fed to calc_CNS_increment(),
 			// // so if the stop is longer than 127 minutes (but not longer than 254 minutes!)
 			// // we need to calculate the CNS in two chunks.
 			// if( tissue_increment > 127)
 			// {
-			//		tissue_increment -= 127;	// subtract full 127 minutes and do the "remaining" minutes first
-			//		calc_CNS_fraction();
-			//		tissue_increment  = 127;	// catch up with the previously subtracted full 127 minutes
+			//		tissue_increment -= 127;				// subtract full 127 minutes and do the "remaining" minutes first
+			//		calc_CNS_increment();					// calculate the CNS increment
+			//		sim_CNS_fraction += CNS_fraction_inc;	// sum up
+			//		tissue_increment  = 127;				// catch up with the previously subtracted full 127 minutes
 			// }
 
-            // calculate CNS% for the stop			
-			calc_CNS_fraction();
-        }
-    }
+			// calculate CNS% for the stop
+			calc_CNS_increment();					// calculate the CNS increment
+			sim_CNS_fraction += CNS_fraction_inc;	// sum up
+		}
+	}
 }
 
 
@@ -3421,25 +3345,25 @@
 //
 // calculates volumes and required tank fill pressures for each gas.
 //
-// Input:   bottom_depth			 depth of the bottom segment
-//			char_I_bottom_time		 duration of the bottom segment
-//			char_I_extra_time		 extra bottom time for fTTS / delayed ascent
-//			float_ascent_speed       ascent speed, in meters/minute
-//          sim_gas_first_used 		 the bottom gas (1-5 for configured gases, 0 for the manual gas)
-//          internal_deco_depth[]	 depth of the stops
-//			internal_deco_time[]	 duration of the stops
-//			internal_deco_gas[]      gas breathed at the stops
-//          char_I_bottom_usage 	 gas consumption during bottom part and initial ascent, in liters/minute
-//          char_I_deco_usage 		 gas consumption during stops and following ascents, in liters/minute
-//			char_I_tank_size[]       size of the tanks for gas 1-5, in liters
-//			char_I_tank_pres_fill[]  fill pressure of the tanks
+// Input:	bottom_depth			depth of the bottom segment
+//			char_I_bottom_time		duration of the bottom segment
+//			char_I_extra_time		extra bottom time for fTTS / delayed ascent
+//			float_ascent_speed		ascent speed, in meters/minute
+//			sim_gas_first_used		the bottom gas (1-5 for configured gases, 0 for the manual gas)
+//			internal_deco_depth[]	depth of the stops
+//			internal_deco_time[]	duration of the stops
+//			internal_deco_gas[]		gas breathed at the stops
+//			char_I_bottom_usage		gas consumption during bottom part and initial ascent, in liters/minute
+//			char_I_deco_usage		gas consumption during stops and following ascents, in liters/minute
+//			char_I_tank_size[]		size of the tanks for gas 1-5, in liters
+//			char_I_tank_pres_fill[]	fill pressure of the tanks
 //
-// Output:  int_O_gas_volumes[]      amount of gas needed, in liters
-//			int_O_tank_pres_need[]   in bar, + flags for fast evaluation by dive mode warnings:
-//											   2^15: pres_need >= pres_fill
-//											   2^14: pres_need >= press_fill * GAS_NEEDS_ATTENTION_THRESHOLD
-//											   2^11: pres_need == 0
-//											   2^10: pres_need invalid
+// Output:	int_O_gas_volumes[]		amount of gas needed, in liters
+//			int_O_tank_pres_need[]	in bar, + flags for fast evaluation by dive mode warnings:
+//											  2^15: pres_need >= pres_fill
+//											  2^14: pres_need >= press_fill * GAS_NEEDS_ATTENTION_THRESHOLD
+//											  2^11: pres_need == 0
+//											  2^10: pres_need invalid
 //
 void gas_volumes_helper(void)
 {
@@ -3447,7 +3371,7 @@
 	// We use 1.0 for the surface pressure to have stable results when used through
 	// the deco calculator (simulation mode).
 	volume = (float_depth * METER_TO_BAR + 1.0) * float_time * usage;
-	
+
 	return;
 }
 
@@ -3462,35 +3386,35 @@
 	overlay unsigned char stop_depth_last;
 	overlay unsigned char i;
 
-	
-    //---- initialization ----------------------------------------------------
-	
+
+	//---- initialization ----------------------------------------------------
+
 	// null the volume accumulators
-    for(i=0; i<NUM_GAS; ++i) volumes[i] = 0.0;
+	for(i=0; i<NUM_GAS; ++i) volumes[i] = 0.0;
 
 	// quit for CCR and pSCR mode
 	if( char_O_deco_status & DECO_MODE_LOOP ) goto done;
 
 
-    //---- bottom demand -----------------------------------------------------
-	
+	//---- bottom demand -----------------------------------------------------
+
 	// sim_gas_first_used : gas used during bottom segment (0, 1-5)
 	// bottom_depth: depth of the bottom segment
-	
+
 	assert(0 <= sim_gas_first_used && sim_gas_first_used <= NUM_GAS);
 
 	// get the gas used during bottom segment
 	stop_gas_last = stop_gas = sim_gas_first_used;
-	
+
 	// set the usage (SAC rate) to bottom usage rate for bottom part and initial ascent
 	usage = char_I_bottom_usage;
-		
+
 	// volumes are only calculated for gases 1-5, but not the manually configured one
 	if( stop_gas )
 	{
 		// set the bottom depth
 		float_depth = (float)bottom_depth;
-		
+
 		// calculate either bottom segment or just the fTTS/bailout delayed part
 		if( char_O_main_status & DECO_BOTTOM_CALCULATE )
 		{
@@ -3502,41 +3426,39 @@
 			// duration of delayed ascent
 			float_time = (float)char_I_extra_time;
 		}
-		
+
 		// calculate gas demand
 		gas_volumes_helper();
-		
+
 		// take result
 		volumes[stop_gas-1] = volume;
 	}
-	
-	
+
 	// initialize stop index with first stop
 	i = 0;
 
-	
 	//---- initial ascent demand ---------------------------------------------
-	
+
 	// stop_gas                : gas from bottom segment
-	// bottom_depth            : depth of the bottom segment in meters
+	// bottom_depth            : depth of the bottom segment
 	// internal_deco_depth[i=0]: depth of the first stop, may be 0 if no stop exists
-	
+
 	// get the data of the first stop	
 	stop_depth = internal_deco_depth[i];
 	stop_time  = internal_deco_time[i];
-	
+
 	// volumes are only calculated for gases 1-5, but not the manually configured one
 	if( stop_gas )
 	{
 		// compute distance between bottom and first stop
 		float_depth = (float)bottom_depth - (float)stop_depth;
-		
+
 		// initial ascent exists only if ascent distance is > 0
 		if( float_depth > 0.0 )
 		{
 			// compute ascent time
 			float_time = float_depth / float_ascent_speed;
-		
+
 			// compute average depth between bottom and first stop
 			float_depth = (float)bottom_depth - float_depth * 0.5;
 
@@ -3551,10 +3473,10 @@
 	// switch the usage (SAC rate) to deco usage rate
 	// for stops, intermediate and final ascent
 	usage = char_I_deco_usage;
-	
+
 	// is there a (first) stop? if yes, goto stops processing
 	if( stop_depth ) goto stops;
-	
+
 	// add demand of a 3 minutes safety stop at 5 meters, at least for contingency...
 	float_time  = 3.0;
 	float_depth = 5.0;
@@ -3566,16 +3488,16 @@
 	volumes[stop_gas-1] += volume;
 
 	// proceed to volume conversion and pressure calculations
-	goto done;			
-
-	
+	goto done;
+
+
 	//---- intermediate ascent demand ---------------------------------------
 inter_ascents:
 
 	// store last stop depth and gas
 	stop_depth_last = stop_depth;
 	stop_gas_last   = stop_gas;
-	
+
 	// check if we are at the end of the stops table
 	if( i < NUM_STOPS-1 )
 	{
@@ -3612,7 +3534,7 @@
 
 		// compute ascent time
 		float_time = float_depth / float_ascent_speed;
-		
+
 		// compute average depth between the two stops
 		float_depth = (float)stop_depth_last - float_depth * 0.5;
 
@@ -3626,32 +3548,32 @@
 
 	//---- next stop demand -------------------------------------------------
 stops:
-	
+
 	// convert depth of the stop
 	float_depth = (float)stop_depth;
-	
+
 	// get the next gas
 	stop_gas = internal_deco_gas[i];
-	
+
 	// do we we have a gas change?
 	if( stop_gas_last && (stop_gas != stop_gas_last) )
 	{
 		// yes - spend an additional char_I_gas_change_time on the old gas
 		float_time = (float)char_I_gas_change_time;
-		
+
 		// calculate gas demand
 		gas_volumes_helper();
 
 		// add result
 		volumes[stop_gas_last-1] += volume;
 	}
-	
+
 	// calculate and add demand on new gas for the full stop duration
 	if( stop_gas )
 	{
 		// get the duration of the stop
 		float_time = (float)stop_time;
-				
+
 		// calculate gas demand
 		gas_volumes_helper();
 
@@ -3668,16 +3590,16 @@
 
 	// float_depth: depth of last stop
 	// stop_gas   : gas from last stop (0 or 1-5)
-	
+
 	// volumes are only calculated for gases 1-5, but not the manually configured one	
 	if( stop_gas )
 	{
 		// set ascent time according to an ascent speed of 1 meter per minute
 		float_time = float_depth;
-		
+
 		// set half-way depth
 		float_depth *= 0.5;
-		
+
 		// calculate gas demand
 		gas_volumes_helper();
 
@@ -3686,12 +3608,12 @@
 	}
 
 
-    //---- convert results for the assembler interface -----------------------------
+	//---- convert results for the assembler interface -----------------------------
 done:
 
-    for(i=0; i<NUM_GAS; ++i)
+	for(i=0; i<NUM_GAS; ++i)
 	{
-        if( volumes[i] >= 65534.5 )
+		if( volumes[i] >= 65534.5 )
 		{
 			int_O_gas_volumes[i]	= 65535;
 			int_O_tank_pres_need[i]	= 999 + INT_FLAG_WARNING; // 999 bar + warning flag for > pres_fill
@@ -3699,18 +3621,18 @@
 		else
 		{
 			overlay unsigned short tank_pres_fill = 10.0 * (unsigned short)char_I_tank_pres_fill[i];
-			
+
 			// No distinct rounding done here because volumes are not accurate to the single liter anyhow
-			
+
 			// convert gas volumes to integers
-            int_O_gas_volumes[i]     = (unsigned short)volumes[i];
-		
+			int_O_gas_volumes[i]     = (unsigned short)volumes[i];
+
 			// compute how much pressure in the tank will be needed [in bar]  (integer-division)
 			int_O_tank_pres_need[i]  = (unsigned short)(int_O_gas_volumes[i] / char_I_tank_size[i]);
-			
+
 			// limit to 999 bar because of display constraints
 			if( int_O_tank_pres_need[i] > 999 ) int_O_tank_pres_need[i] = 999;
-			
+
 			// set flags for fast evaluation by divemode check for warnings
 			if     ( int_O_tank_pres_need[i] == 0 )
 			{
@@ -3726,8 +3648,8 @@
 			else if( int_O_tank_pres_need[i] >= tank_pres_fill * GAS_NEEDS_ATTENTION_THRESHOLD )
 			{
 				// set pre-warning flag
-				int_O_tank_pres_need[i] |= INT_FLAG_PREWARNING;	
-			}			
+				int_O_tank_pres_need[i] |= INT_FLAG_ATTENTION;
+			}
 
 			// set invalid flag if there is an overflow in the stops table
 			if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW )
@@ -3739,7 +3661,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void compute_CNS_for_display(void)
+void convert_CNS_for_display(void)
 {
 	if		( CNS_fraction <  0.01  ) int_O_CNS_fraction = 0;
 	else if ( CNS_fraction >= 9.985 ) int_O_CNS_fraction = 999 + INT_FLAG_WARNING;
@@ -3747,69 +3669,72 @@
 	{
 		// convert float to integer
 		int_O_CNS_fraction = (unsigned short)(100 * CNS_fraction + 0.5);
-	
-		// compute warnings
-		if		( int_O_CNS_fraction >= CNS_warning_threshold    )
-		{
-			// reset pre-warning and set main warning flag
-			int_O_CNS_fraction &= ~INT_FLAG_PREWARNING;			
-			int_O_CNS_fraction |=  INT_FLAG_WARNING;
-		}
-		else if	( int_O_CNS_fraction >= CNS_prewarning_threshold )
-		{
-			// reset main warning but set pre-warning flag
-			int_O_CNS_fraction &= ~INT_FLAG_WARNING;
-			int_O_CNS_fraction |=  INT_FLAG_PREWARNING;
-		}
-		else
-		{
-			// clear both warnings
-			int_O_CNS_fraction &= ~(INT_FLAG_WARNING + INT_FLAG_PREWARNING);
-		}
+
+		// set warnings
+		if		( int_O_CNS_fraction >= CNS_WARNING_THRESHOLD   ) int_O_CNS_fraction |= INT_FLAG_WARNING;
+		else if	( int_O_CNS_fraction >= CNS_ATTENTION_THRESHOLD ) int_O_CNS_fraction |= INT_FLAG_ATTENTION;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void convert_sim_CNS_for_display(void)
+{
+	if		( sim_CNS_fraction <  0.01  ) int_sim_CNS_fraction = 0;
+	else if ( sim_CNS_fraction >= 9.985 ) int_sim_CNS_fraction = 999 + INT_FLAG_WARNING;
+	else
+	{
+		// convert float to integer
+		int_sim_CNS_fraction = (unsigned short)(100 * sim_CNS_fraction + 0.5);
+
+		// set warning flag if CNS is >= 100%
+		if      ( int_sim_CNS_fraction >= CNS_WARNING_THRESHOLD    ) int_sim_CNS_fraction |= INT_FLAG_WARNING;
+		else if ( int_sim_CNS_fraction >= CNS_ATTENTION_THRESHOLD  ) int_sim_CNS_fraction |= INT_FLAG_ATTENTION;
+
+		// set invalid flag if there is an overflow in the stops table
+		if( char_O_deco_warnings & DECO_WARNING_STOPTABLE_OVERFLOW ) int_sim_CNS_fraction |= INT_FLAG_INVALID;
 	}
 }
 
 //////////////////////////////////////////////////////////////////////////////
-
-void deco_push_tissues_to_vault(void)
+// push_tissues_to_vault & pull_tissues_from_vault
+//
+// ATTENTION: Do not use from inside the deco engine!
+//            The vault is exclusively reserved to back-up and restore the real
+//            tissues and related data when entering / leaving simulation mode!
+//
+
+void push_tissues_to_vault(void)
 {
-    overlay unsigned char x;
-
-    RESET_C_STACK
-
-	low_depth_norm_vault = low_depth_norm;
-	low_depth_alt_vault  = low_depth_alt;
-    cns_vault_float      = CNS_fraction;
-	cns_vault_int        = int_O_CNS_fraction;
+	overlay unsigned char x;
+
+	cns_vault_float      = CNS_fraction;
 	deco_warnings_vault  = char_O_deco_warnings;
 
-    for (x=0;x<NUM_COMP;x++)
-    {
-        pres_tissue_N2_vault[x] = pres_tissue_N2[x];
-        pres_tissue_He_vault[x] = pres_tissue_He[x];
-    }
+	for (x=0;x<NUM_COMP;x++)
+	{
+		pres_tissue_N2_vault[x] = pres_tissue_N2[x];
+		pres_tissue_He_vault[x] = pres_tissue_He[x];
+	}
 }
 
-void deco_pull_tissues_from_vault(void)
+void pull_tissues_from_vault(void)
 {
-    overlay unsigned char x;
-
-    RESET_C_STACK
-
-	low_depth_norm       = low_depth_norm_vault;
-	low_depth_alt        = low_depth_alt_vault;
-    CNS_fraction         = cns_vault_float;
-    int_O_CNS_fraction   = cns_vault_int;
+	overlay unsigned char x;
+
+	CNS_fraction         = cns_vault_float;
 	char_O_deco_warnings = deco_warnings_vault;
-	
+
+	convert_CNS_for_display();
+
 	locked_GF_step_norm  = GF_delta / low_depth_norm;
 	locked_GF_step_alt   = GF_delta / low_depth_alt;
 	
-    for (x=0; x<NUM_COMP; x++)
-    {
-        pres_tissue_N2[x] = pres_tissue_N2_vault[x];
-        pres_tissue_He[x] = pres_tissue_He_vault[x];
-    }
+	for (x=0; x<NUM_COMP; x++)
+	{
+		pres_tissue_N2[x] = pres_tissue_N2_vault[x];
+		pres_tissue_He[x] = pres_tissue_He_vault[x];
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////