diff Discovery/Src/vpm.c @ 981:c6c781a2e85b default

Merge into default
author heinrichsweikamp
date Tue, 11 Feb 2025 18:12:00 +0100
parents 79b522fbabe6
children 22d5b477c903
line wrap: on
line diff
--- a/Discovery/Src/vpm.c	Tue Aug 13 13:24:54 2024 +0200
+++ b/Discovery/Src/vpm.c	Tue Feb 11 18:12:00 2025 +0100
@@ -132,6 +132,9 @@
 
 static const _Bool vpm_b = true;
 
+static SvpmTableState vpmTableState = VPM_TABLE_INIT;
+static SDecoinfo vpmTable;
+
 extern const float float_buehlmann_N2_factor_expositon_20_seconds[];
 extern const float float_buehlmann_He_factor_expositon_20_seconds[];
 extern const float float_buehlmann_N2_factor_expositon_one_minute[];
@@ -165,7 +168,7 @@
 
 static float r_int(float *x)
 {
-    return( (*x>0) ? floorf(*x) : -floorf(- *x) );
+    return( (*x>0.0) ? floorf(*x) : -floorf(- *x) );
 }
 
 /** private functions
@@ -191,6 +194,8 @@
 static void  vpm_init_1(void);
 static void vpm_calc_deco_ceiling(void);
 
+uint8_t vpm_get_decozone(void);
+
 static void vpm_init_1(void)
 {
      units_equal_msw = true;
@@ -219,6 +224,50 @@
     return gCNS_VPM;
 }
 
+
+void vpm_maintainTable(SLifeData* pLifeData,SDecoinfo* pDecoInfo)
+{
+	static uint32_t lastDiveSecond = 0;
+	uint8_t actual_deco_stop = 0;
+	int8_t index = 0;
+	uint8_t decreaseStopTime = 1;
+
+	if(lastDiveSecond < pLifeData->dive_time_seconds)
+	{
+		lastDiveSecond = pLifeData->dive_time_seconds;
+		actual_deco_stop = decom_get_actual_deco_stop((SDiveState*)stateUsed);
+
+		pDecoInfo->output_time_to_surface_seconds = 0;
+		for(index = DECOINFO_STRUCT_MAX_STOPS -1 ;index >= 0; index--)
+		{
+			if(pDecoInfo->output_stop_length_seconds[index] > 0)
+			{
+				if(decreaseStopTime)
+				{
+					if((pLifeData->depth_meter > (float)(actual_deco_stop - 1.5))
+						&& (pLifeData->depth_meter < (float)actual_deco_stop + 1.5))
+					{
+						pDecoInfo->output_stop_length_seconds[index]--;
+						decreaseStopTime = 0;
+					}
+					else if (pLifeData->depth_meter < (float)(actual_deco_stop - 1.5)) /* missed deco stop */
+					{
+						vpmTableState = VPM_TABLE_MISSED;
+						pDecoInfo->output_stop_length_seconds[index] = 0;
+						decreaseStopTime = 0;
+					}
+				}
+				pDecoInfo->output_time_to_surface_seconds += pDecoInfo->output_stop_length_seconds[index];
+			}
+		}
+		pDecoInfo->output_time_to_surface_seconds += pLifeData->depth_meter / 10.0 * 60.0;
+	}
+	else if(lastDiveSecond > pLifeData->dive_time_seconds)
+	{
+		lastDiveSecond = pLifeData->dive_time_seconds;
+	}
+}
+
 int  vpm_calc(SLifeData* pINPUT,
               SDiveSettings* pSettings,
               SVpm* pVPM,
@@ -226,10 +275,17 @@
               pDECOINFO,
               int calc_what)
 {
+	static uint8_t vpmTableActive = 0;
+
     vpm_init_1();
     //decom_CreateGasChangeList(pSettings, pINPUT);
     vpm_calc_what = calc_what;
     /**clear decoInfo*/
+
+    if((vpmTableActive) && (vpm_calc_what == DECOSTOPS))
+    {
+    	memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo));	/* save changes done by e.g. the simulator */
+    }
     pDECOINFO->output_time_to_surface_seconds = 0;
     pDECOINFO->output_ndl_seconds = 0;
     pDECOINFO->output_ceiling_meter = 0;
@@ -280,7 +336,33 @@
 
     //Only Decostops not futute stops
     if(vpm_calc_what == DECOSTOPS)
+    {
         vpm_calc_status = tmp_calc_status;
+        if(pSettings->vpm_tableMode)		/* store the most conservative deco plan and stick to it. */
+        {
+			if((int16_t)(pDECOINFO->output_time_to_surface_seconds - vpmTable.output_time_to_surface_seconds) > 60)
+			{
+				memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo));
+				vpmTableActive = 1;
+				if(pVpm->deco_zone_reached) /* table should not change after deco zone was entered */
+				{
+					if(vpmTableState != VPM_TABLE_MISSED)
+					{
+						vpmTableState = VPM_TABLE_WARNING;
+					}
+				}
+			}
+			else
+			{
+				if(vpmTable.output_time_to_surface_seconds > 0)
+				{
+					vpm_maintainTable(pINPUT, &vpmTable);
+					vpmTable.output_ceiling_meter = pDECOINFO->output_ceiling_meter;
+					memcpy(pDECOINFO, &vpmTable, sizeof(SDecoinfo));
+				}
+			}
+        }
+    }
     return vpm_calc_status;
 }
 
@@ -460,10 +542,18 @@
 
     for (i = 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++)
     {
-        if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero  >= depth_change[0] + 1)
+        if((pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero  >= depth_change[0] + 1)
+#ifdef ENABLE_DECOCALC_OPTION
+        		&& (pDiveSettings->gas[pDiveSettings->decogaslist[i].GasIdInSettings].note.ub.decocalc)
+#endif
+        	)
             continue;
 
-        if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero <= 0)
+        if((pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero <= 0)
+#ifdef ENABLE_DECOCALC_OPTION
+        	|| (pDiveSettings->gas[pDiveSettings->decogaslist[i].GasIdInSettings].note.ub.decocalc == 0)
+#endif
+        )
             break;
 
         j++;
@@ -636,8 +726,8 @@
         {
             for (i = 0; i < 16; i++)
             {
-                tissue_He_saturation[i] = helium_pressure[i] / 10;
-                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10;
+                tissue_He_saturation[i] = helium_pressure[i] / 10.0;
+                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10.0;
             }
 
             if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_stop_depth / 10.0f) + pInput->pressure_surface_bar))
@@ -645,7 +735,7 @@
 
                 vpm_violates_buehlmann = true;
                 do {
-                    deco_stop_depth += 3;
+                    deco_stop_depth += 3.0;
                 } while (!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_stop_depth / 10.0f) + pInput->pressure_surface_bar));
             }
         }
@@ -923,13 +1013,12 @@
         {
             for (i = 0; i < 16; i++)
             {
-                tissue_He_saturation[i] = helium_pressure[i] / 10;
-                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10;
+                tissue_He_saturation[i] = helium_pressure[i] / 10.0;
+                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10.0;
             }
 
             if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar))
             {
-
                 vpm_violates_buehlmann = true;
                 do {
                     deco_ceiling_depth += 0.1f;
@@ -961,13 +1050,12 @@
         {
             for (i = 0; i < 16; i++)
             {
-                tissue_He_saturation[i] = helium_pressure[i] / 10;
-                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10;
+                tissue_He_saturation[i] = helium_pressure[i] / 10.0;
+                tissue_N2_saturation[i] = nitrogen_pressure[i] / 10.0;
             }
 
             if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar))
             {
-
                 vpm_violates_buehlmann = true;
                 do {
                     deco_ceiling_depth += 0.1f;
@@ -981,12 +1069,12 @@
     }
     else
     {
-         pDecoInfo->output_ceiling_meter = 0;
+         pDecoInfo->output_ceiling_meter = 0.0;
     }
 
     // fix hw 160627
-    if(pDecoInfo->output_ceiling_meter < 0)
-        pDecoInfo->output_ceiling_meter = 0;
+    if(pDecoInfo->output_ceiling_meter < 0.0)
+        pDecoInfo->output_ceiling_meter = 0.0;
 
     /*** End CALC ceiling    ***************************************************/
 }
@@ -1005,6 +1093,10 @@
     static int dp_max;
     static float surfacetime;
     _Bool first_stop = false;
+    float roundingValue = 0.0;
+
+    uint16_t stop_time_seconds;
+
     max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth);
     if(begin)
     {
@@ -1103,16 +1195,22 @@
             }
             else
             {
-                    dp = 1 + (int)((deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10)) / step_size);
+            	roundingValue = (deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10.0)) / step_size;
+            	dp = 1 + r_nint(&roundingValue);
             }
-            dp_max = (int)fmaxf(dp_max,dp);
+
+            //dp_max = (int)fmaxf(dp_max,dp);
+            if(dp > dp_max)
+            {
+            	dp_max = dp;
+            }
             if(dp < DECOINFO_STRUCT_MAX_STOPS)
             {
-                int stop_time_seconds = fminf((999 * 60), (int)(stop_time *60));
+                stop_time_seconds = (uint16_t)(fminf((999.9 * 60.0), (stop_time *60.0)));
                 //
 
                 //if(vpm_calc_what == DECOSTOPS)
-                    pDecoInfo->output_stop_length_seconds[dp] = (unsigned short)stop_time_seconds;
+                    pDecoInfo->output_stop_length_seconds[dp] = stop_time_seconds;
                 //else
                     //decostop_bailout[dp] = (unsigned short)stop_time_seconds;
             }
@@ -1156,7 +1254,7 @@
                 //decostop_bailout[dp] = 0;
         }
     }
-    pDecoInfo->output_time_to_surface_seconds = (int)(surfacetime * 60);
+    pDecoInfo->output_time_to_surface_seconds = (int)(surfacetime * 60.0);
     pDecoInfo->output_ndl_seconds = 0;
 
     vpm_calc_deco_ceiling();
@@ -1407,8 +1505,8 @@
         /*     the vacuum of outer space! */
         /* =============================================================================== */
 
-        if (tolerated_ambient_pressure < 0) {
-            tolerated_ambient_pressure = 0;
+        if (tolerated_ambient_pressure < 0.0) {
+            tolerated_ambient_pressure = 0.0;
         }
         compartment_deco_ceiling[i - 1] =
         tolerated_ambient_pressure - barometric_pressure;
@@ -1736,8 +1834,8 @@
     ending_ambient_pressure = starting_ambient_pressure/2;
 
     time_test = (ending_ambient_pressure - starting_ambient_pressure) / *rate;
-    decom_get_inert_gases(starting_ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_begin, &fraction_helium_begin );
-    decom_get_inert_gases(ending_ambient_pressure   / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_end, &fraction_helium_end );
+    decom_get_inert_gases(starting_ambient_pressure / 10.0, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_begin, &fraction_helium_begin );
+    decom_get_inert_gases(ending_ambient_pressure   / 10.0, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_end, &fraction_helium_end );
     initial_inspired_he_pressure =	(starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_helium_begin;
     initial_inspired_n2_pressure =	(starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_nitrogen_begin;
     helium_rate = ((ending_ambient_pressure  - WATER_VAPOR_PRESSURE)* fraction_helium_end - initial_inspired_he_pressure)/time_test;
@@ -1768,7 +1866,7 @@
     /*     and high bound function values. */
     /* =============================================================================== */
 
-    low_bound = 0.;
+    low_bound = 0.0;
     high_bound = starting_ambient_pressure / *rate * -1.0f;
     for (i = 1; i <= 16; ++i)
     {
@@ -2020,17 +2118,17 @@
     }
     else
     {
-        deco_ceiling_depth = next_stop + 1;
+        deco_ceiling_depth = next_stop + 1.0;
     }
         if(deco_ceiling_depth > next_stop)
         {
             while (deco_ceiling_depth > next_stop)
             {
 
-                segment_time  +=  60;
-                if(segment_time >= 999 )
+                segment_time  +=  60.0;
+                if(segment_time >= 999.0 )
                 {
-                    segment_time = 999 ;
+                    segment_time = 999.0 ;
                     run_time += segment_time;
                     return;
                 }
@@ -2048,7 +2146,7 @@
             }
             if(deco_ceiling_depth < next_stop)
             {
-                segment_time  -=  60;
+                segment_time  -=  60.0;
                 gCNS_VPM = initial_CNS;
                 for (i = 0; i < 16; i++)
                 {
@@ -2088,11 +2186,11 @@
             while (buehlmann_wait || (deco_ceiling_depth > next_stop))
             {
                 //time_counter = temp_segment_time;
-                segment_time  +=  1;
+                segment_time  +=  1.0;
 
-                if(segment_time >= 999 )
+                if(segment_time >= 999.0 )
                 {
-                    segment_time = 999 ;
+                    segment_time = 999.0 ;
                     run_time += segment_time;
                     return;
                 }
@@ -2300,8 +2398,8 @@
 
         for(i = 0; i < 16;i++)
         {
-            future_helium_pressure[i] =  pInput->tissue_helium_bar[i] * 10;//tissue_He_saturation[st_dive][i] * 10;
-            future_nitrogen_pressure[i] = pInput->tissue_nitrogen_bar[i] * 10;
+            future_helium_pressure[i] =  pInput->tissue_helium_bar[i] * 10.0;//tissue_He_saturation[st_dive][i] * 10;
+            future_nitrogen_pressure[i] = pInput->tissue_nitrogen_bar[i] * 10.0;
         }
         temp_segment_time = 0;
 
@@ -2409,3 +2507,18 @@
     else
         return CALC_BEGIN;
 }
+
+void vpm_table_init()
+{
+	vpmTable.output_time_to_surface_seconds = 0;
+	vpmTableState = VPM_TABLE_INIT;
+}
+uint8_t vpm_get_decozone(void)
+{
+	return((uint8_t)pVpm->depth_start_of_deco_zone_save);
+}
+SvpmTableState vpm_get_TableState(void)
+{
+	return vpmTableState;
+}
+