Mercurial > public > mk2
comparison code_part1/OSTC_code_c_part2/p2_deco.c @ 212:275befc5f39d
Debug GF model (bug #11 & #12).
+ ASSERT stops should be computed in order (bug#11).
+ BUGFIX: Mark GF_low reference at actual first stop, not predicted one.
+ BUGFIX: sim_to_first_stop() stops BEFORE first stop, not after (bug#11).
+ BUGFIX: check that calc_nextdecodepth() don't ascent faster than 10m/mn (bug#11).
+ BUGFIX: calc_nextdecodepth() should check gas switch, too (bug#11).
+ let gas switch detection in depth/meter (not ambientPresure/mbar).
+ BUGFIX OCR mode: bad diluent value in sim_alveolar_pressure() (bug#11).
+ BUGFIX: add deco distance (offset) only to compartiment integration, not to B?hlmann or GF criterion.
+ BUGFIX: add margin one meter above gas switch depth (bug#12)
+ BUGFIX: When ascenting too fast, cancel gas switch delay and history (bug#11).
author | JeanDo |
---|---|
date | Mon, 21 Feb 2011 22:36:48 +0100 |
parents | 2d9af08ed0ac |
children | c7e32ff65636 |
comparison
equal
deleted
inserted
replaced
211:d0903d4ab588 | 212:275befc5f39d |
---|---|
125 static void calc_hauptroutine_data_input(void); | 125 static void calc_hauptroutine_data_input(void); |
126 static void calc_hauptroutine_update_tissues(void); | 126 static void calc_hauptroutine_update_tissues(void); |
127 static void calc_hauptroutine_calc_deco(void); | 127 static void calc_hauptroutine_calc_deco(void); |
128 static void sim_ascent_to_first_stop(void); | 128 static void sim_ascent_to_first_stop(void); |
129 | 129 |
130 static void check_gas_switch(void); | |
130 static void calc_nextdecodepth(void); | 131 static void calc_nextdecodepth(void); |
131 | 132 |
132 //---- Bank 4 parameters ----------------------------------------------------- | 133 //---- Bank 4 parameters ----------------------------------------------------- |
133 #pragma udata bank4=0x400 | 134 #pragma udata bank4=0x400 |
134 | 135 |
172 static float var_He_b; // Bühlmann b, for current He tissue. | 173 static float var_He_b; // Bühlmann b, for current He tissue. |
173 static float var_N2_e; // Exposition, for current N2 tissue. | 174 static float var_N2_e; // Exposition, for current N2 tissue. |
174 static float var_He_e; // Exposition, for current He tissue. | 175 static float var_He_e; // Exposition, for current He tissue. |
175 | 176 |
176 static float pres_diluent; // new in v.101 | 177 static float pres_diluent; // new in v.101 |
177 static float deco_diluent; // new in v.101 | |
178 static float const_ppO2; // new in v.101 | 178 static float const_ppO2; // new in v.101 |
179 static float deco_ppO2_change; // new in v.101 | 179 static float deco_ppO2_change; // new in v.101 |
180 static float deco_ppO2; // new in v.101 | 180 static float deco_ppO2; // new in v.101 |
181 | 181 |
182 static unsigned char sim_gas_last_used; // Last used gas, to detected a gas switch. | 182 static unsigned char sim_gas_last_used; // Last used gas, to detected a gas switch. |
188 static float float_saturation_multiplier; // new in v.101 | 188 static float float_saturation_multiplier; // new in v.101 |
189 static float float_desaturation_multiplier; // new in v.101 | 189 static float float_desaturation_multiplier; // new in v.101 |
190 static float float_deco_distance; // new in v.101 | 190 static float float_deco_distance; // new in v.101 |
191 static char flag_in_divemode; // new in v.108 | 191 static char flag_in_divemode; // new in v.108 |
192 | 192 |
193 static float deco_gas_change1; // new in v.101 | 193 static unsigned char deco_gas_change1; // new in v.101 |
194 static float deco_gas_change2; // new in v.109 | 194 static unsigned char deco_gas_change2; // new in v.109 |
195 static float deco_gas_change3; // new in v.109 | 195 static unsigned char deco_gas_change3; // new in v.109 |
196 static float deco_gas_change4; // new in v.109 | 196 static unsigned char deco_gas_change4; // new in v.109 |
197 static float deco_gas_change5; // new in v.109 | 197 static unsigned char deco_gas_change5; // new in v.109 |
198 | 198 |
199 static float deco_N2_ratio1; // new in v.101 | 199 static float deco_N2_ratio1; // new in v.101 |
200 static float deco_He_ratio1; // new in v.101 | 200 static float deco_He_ratio1; // new in v.101 |
201 | 201 |
202 | 202 |
225 static char md_state[48]; // DONT MOVE !! // has to be at the beginning of bank 9 for the asm code!!! | 225 static char md_state[48]; // DONT MOVE !! // has to be at the beginning of bank 9 for the asm code!!! |
226 | 226 |
227 // internal, dbg: | 227 // internal, dbg: |
228 static unsigned char DBG_char_I_deco_model; // new in v.108. | 228 static unsigned char DBG_char_I_deco_model; // new in v.108. |
229 static unsigned char DBG_char_I_depth_last_deco; // new in v.108 | 229 static unsigned char DBG_char_I_depth_last_deco; // new in v.108 |
230 static unsigned char DBG_deco_gas_change; // new in v.108 | |
230 static float DBG_pres_surface; // new in v.108 | 231 static float DBG_pres_surface; // new in v.108 |
231 static float DBG_GF_low; // new in v.108 | 232 static float DBG_GF_low; // new in v.108 |
232 static float DBG_GF_high; // new in v.108 | 233 static float DBG_GF_high; // new in v.108 |
233 static float DBG_const_ppO2; // new in v.108 | 234 static float DBG_const_ppO2; // new in v.108 |
234 static float DBG_deco_ppO2_change; // new in v.108 | 235 static float DBG_deco_ppO2_change; // new in v.108 |
235 static float DBG_deco_ppO2; // new in v.108 | 236 static float DBG_deco_ppO2; // new in v.108 |
236 static float DBG_deco_N2_ratio; // new in v.108 | 237 static float DBG_deco_N2_ratio; // new in v.108 |
237 static float DBG_deco_He_ratio; // new in v.108 | 238 static float DBG_deco_He_ratio; // new in v.108 |
238 static float DBG_deco_gas_change; // new in v.108 | |
239 static float DBG_float_saturation_multiplier; // new in v.108 | 239 static float DBG_float_saturation_multiplier; // new in v.108 |
240 static float DBG_float_desaturation_multiplier; // new in v.108 | 240 static float DBG_float_desaturation_multiplier; // new in v.108 |
241 static float DBG_float_deco_distance; // new in v.108 | 241 static float DBG_float_deco_distance; // new in v.108 |
242 static float DBG_deco_N2_ratio; // new in v.108 | 242 static float DBG_deco_N2_ratio; // new in v.108 |
243 static float DBG_deco_He_ratio; // new in v.108 | 243 static float DBG_deco_He_ratio; // new in v.108 |
596 // char_I_depth_last_deco | 596 // char_I_depth_last_deco |
597 // float_deco_distance | 597 // float_deco_distance |
598 // | 598 // |
599 // OUTPUT | 599 // OUTPUT |
600 // locked_GF_step | 600 // locked_GF_step |
601 // temp_deco | |
602 // temp_depth_limt | 601 // temp_depth_limt |
603 // low_depth | 602 // low_depth |
604 // | 603 // |
605 static void calc_nextdecodepth(void) | 604 static void calc_nextdecodepth(void) |
606 { | 605 { |
607 //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ | 606 //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ |
608 if (char_I_deco_model == 1) | 607 if (char_I_deco_model == 1) |
609 { | 608 { |
610 // Recompute leading gas limit, at current depth: | 609 // Recompute leading gas limit, at current depth: |
611 overlay float depth = (temp_deco - pres_surface) / 0.09995; | 610 overlay float depth = (temp_deco - pres_surface) / 0.09995; |
612 assert( depth >= 0.0 ); | 611 assert( depth >= 0.0 ); |
622 { | 621 { |
623 // Deepest stop, in meter. | 622 // Deepest stop, in meter. |
624 overlay unsigned char first_stop = 3 * (short)(0.99 + (sim_lead_tissue_limit - pres_surface) / 0.29985); | 623 overlay unsigned char first_stop = 3 * (short)(0.99 + (sim_lead_tissue_limit - pres_surface) / 0.29985); |
625 assert( first_stop < 128 ); | 624 assert( first_stop < 128 ); |
626 | 625 |
627 // Apply correction for the first stop. | 626 // Apply correction for the shallowest stop. |
628 if( first_stop == 3 ) // new in v104 | 627 if( first_stop == 3 ) // new in v104 |
629 first_stop = char_I_depth_last_deco; // Use last 3m..6m instead. | 628 first_stop = char_I_depth_last_deco; // Use last 3m..6m instead. |
629 | |
630 // Check all stops until one is higher than tolerated presure | |
631 while(first_stop > 0) | |
632 { | |
633 overlay unsigned char next_stop; // Next index (0..30) | |
634 overlay float pres_stop; // Next depth (0m..90m) | |
635 | |
636 if( first_stop <= char_I_depth_last_deco ) // new in v104 | |
637 next_stop = 0; | |
638 else | |
639 next_stop = first_stop - 3; // Index of next (upper) stop. | |
640 if( first_stop == 3 ) | |
641 first_stop = char_I_depth_last_deco; | |
642 | |
643 pres_stop = next_stop * 0.09995 // Meters to bar | |
644 + pres_surface; | |
645 | |
646 // Keep GF_low until a first stop depth is found: | |
647 if( next_stop >= low_depth ) | |
648 sim_limit( GF_low ); | |
649 else | |
650 // current GF is GF_high - alpha (GF_high - GF_low) | |
651 // With alpha = currentDepth / maxDepth, hence in [0..1] | |
652 sim_limit( GF_high - next_stop * locked_GF_step ); | |
653 | |
654 // upper limit (lowest pressure tolerated): | |
655 if( sim_lead_tissue_limit >= pres_stop ) // check if ascent to next deco stop is ok | |
656 break; | |
657 | |
658 // Else, validate that stop and loop... | |
659 first_stop = next_stop; | |
660 } | |
630 | 661 |
631 // Is it a new deepest first stop ? If yes this is the reference for | 662 // Is it a new deepest first stop ? If yes this is the reference for |
632 // the varying gradient factor. So reset that: | 663 // the varying gradient factor. So reset that: |
633 if( first_stop > low_depth ) | 664 if( first_stop > low_depth ) |
634 { | 665 { |
635 // Store the deepest stop depth, as reference for GF_low. | 666 // Store the deepest stop depth, as reference for GF_low. |
636 low_depth = first_stop; | 667 low_depth = first_stop; |
637 locked_GF_step = GF_delta / low_depth; | 668 locked_GF_step = GF_delta / low_depth; |
638 } | 669 } |
639 | 670 |
640 // Check all stops until one is higher than tolerated presure | 671 // next stop is the last validated depth found, aka first_stop |
641 while(first_stop > 0) | |
642 { | |
643 overlay unsigned char next_stop; // Next index (0..30) | |
644 overlay float pres_stop; // Next depth (0m..90m) | |
645 | |
646 if( first_stop <= char_I_depth_last_deco ) // new in v104 | |
647 next_stop = 0; | |
648 else | |
649 next_stop = first_stop - 3; // Index of next (upper) stop. | |
650 if( first_stop == 3 ) | |
651 first_stop = char_I_depth_last_deco; | |
652 | |
653 pres_stop = next_stop * 0.09995 // Meters to bar | |
654 + pres_surface; | |
655 | |
656 // current GF is GF_high - alpha (GF_high - GF_low) | |
657 // With alpha = currentDepth / maxDepth, hence in [0..1] | |
658 sim_limit( GF_high - next_stop * locked_GF_step ); | |
659 | |
660 // upper limit (lowest pressure tolerated): | |
661 if( sim_lead_tissue_limit >= pres_stop ) // check if ascent to next deco stop is ok | |
662 break; | |
663 | |
664 // Else, validate that stop and loop... | |
665 first_stop = next_stop; | |
666 } | |
667 | |
668 // first_stop is the last validated depth found: | |
669 temp_depth_limit = first_stop; // Stop depth, in meter. | 672 temp_depth_limit = first_stop; // Stop depth, in meter. |
670 temp_deco = first_stop * 0.09995 // Convert to bars, too. | |
671 + pres_surface; | |
672 if (first_stop > 0) | |
673 temp_deco += float_deco_distance; // Add security distance (bars too) | |
674 } | 673 } |
675 else | 674 else |
676 { | |
677 temp_deco = pres_surface; // surface ambient presure | |
678 temp_depth_limit = 0; // stop depth, in meter. | 675 temp_depth_limit = 0; // stop depth, in meter. |
679 } | |
680 } | 676 } |
681 else //---- ZH-L16 model ------------------------------------------------- | 677 else //---- ZH-L16 model ------------------------------------------------- |
682 { | 678 { |
683 overlay float pres_gradient; | 679 overlay float pres_gradient; |
684 | 680 |
692 pres_gradient = sim_lead_tissue_limit - pres_surface; | 688 pres_gradient = sim_lead_tissue_limit - pres_surface; |
693 if (pres_gradient >= 0) | 689 if (pres_gradient >= 0) |
694 { | 690 { |
695 pres_gradient /= 0.29985; // Bar --> stop number; | 691 pres_gradient /= 0.29985; // Bar --> stop number; |
696 temp_depth_limit = 3 * (short) (pres_gradient + 0.99); // --> meter : depth for deco | 692 temp_depth_limit = 3 * (short) (pres_gradient + 0.99); // --> meter : depth for deco |
697 if (temp_depth_limit == 0) // At surface ? | 693 if (temp_depth_limit != 0) // At surface ? |
698 temp_deco = pres_surface; | |
699 else | |
700 { | 694 { |
701 if (temp_depth_limit < char_I_depth_last_deco) // Implement last stop at 4m/5m/6m... | 695 if (temp_depth_limit < char_I_depth_last_deco) // Implement last stop at 4m/5m/6m... |
702 temp_depth_limit = char_I_depth_last_deco; | 696 temp_depth_limit = char_I_depth_last_deco; |
703 temp_deco = (temp_depth_limit * 0.09995) // depth for deco [bar] = depth | |
704 + float_deco_distance // + security margin | |
705 + pres_surface; // + surface ambient presure | |
706 } | 697 } |
707 } | 698 } |
708 else | 699 else |
709 { | |
710 temp_deco = pres_surface; // surface ambient presure | |
711 temp_depth_limit = 0; // stop depth, in meter. | 700 temp_depth_limit = 0; // stop depth, in meter. |
712 } | |
713 } | 701 } |
702 | |
703 //---- Check gas change -------------------------------------------------- | |
704 check_gas_switch(); // Update temp_depth_limit if there is a change, | |
705 // Calculate N2_ratio and He_ratio too. | |
714 } | 706 } |
715 | 707 |
716 ////////////////////////////////////////////////////////////////////////////// | 708 ////////////////////////////////////////////////////////////////////////////// |
717 // copy_deco_table | 709 // copy_deco_table |
718 // | 710 // |
870 | 862 |
871 ////////////////////////////////////////////////////////////////////////////// | 863 ////////////////////////////////////////////////////////////////////////////// |
872 // Calculate gas switches | 864 // Calculate gas switches |
873 // | 865 // |
874 // | 866 // |
875 void check_gas_switch(void) | 867 // Input: N2_ratio, He_ratio. |
868 // deco_gas_change* | |
869 // sim_gas_delay, sim_gas_last_used, sim_dive_mins. | |
870 // | |
871 // Output: calc_N2_ratio, calc_He_ratio | |
872 // temp_depth_limit, sim_gas_delay, sim_gas_last_used IFF the is a switch. | |
873 // | |
874 static void check_gas_switch(void) | |
876 { | 875 { |
877 overlay unsigned char temp_gas_switch = 0; | 876 overlay unsigned char temp_gas_switch = 0; |
878 overlay float switch_deco; | 877 overlay unsigned char switch_deco = 0; |
879 | 878 |
880 calc_N2_ratio = N2_ratio; | 879 calc_N2_ratio = N2_ratio; |
881 calc_He_ratio = He_ratio; | 880 calc_He_ratio = He_ratio; |
882 | 881 |
883 if (char_I_const_ppO2 == 0) | 882 if (char_I_const_ppO2 == 0) |
884 { | 883 { |
885 deco_diluent = temp_deco; | |
886 | |
887 // Keep selecting the best gas during the ascent simulation. | 884 // Keep selecting the best gas during the ascent simulation. |
888 if( deco_gas_change1 && (temp_deco < deco_gas_change1)) | 885 // Add a one meter margin in depth comparaison. |
886 if( deco_gas_change1 && ((temp_depth_limit-1) <= deco_gas_change1)) | |
889 { | 887 { |
890 calc_N2_ratio = deco_N2_ratio1; | 888 calc_N2_ratio = deco_N2_ratio1; |
891 calc_He_ratio = deco_He_ratio1; | 889 calc_He_ratio = deco_He_ratio1; |
892 temp_gas_switch = 1; | 890 temp_gas_switch = 1; |
893 switch_deco = deco_gas_change1; | 891 switch_deco = deco_gas_change1; |
894 } | 892 } |
895 if(deco_gas_change2 && (temp_deco < deco_gas_change2)) | 893 if(deco_gas_change2 && ((temp_depth_limit-1) <= deco_gas_change2)) |
896 { | 894 { |
897 calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01; | 895 calc_N2_ratio = char_I_deco_N2_ratio2 * 0.01; |
898 calc_He_ratio = char_I_deco_He_ratio2 * 0.01; | 896 calc_He_ratio = char_I_deco_He_ratio2 * 0.01; |
899 temp_gas_switch = 2; | 897 temp_gas_switch = 2; |
900 switch_deco = deco_gas_change2; | 898 switch_deco = deco_gas_change2; |
901 } | 899 } |
902 if(deco_gas_change3 && (temp_deco < deco_gas_change3)) | 900 if(deco_gas_change3 && ((temp_depth_limit-1) <= deco_gas_change3)) |
903 { | 901 { |
904 calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01; | 902 calc_N2_ratio = char_I_deco_N2_ratio3 * 0.01; |
905 calc_He_ratio = char_I_deco_He_ratio3 * 0.01; | 903 calc_He_ratio = char_I_deco_He_ratio3 * 0.01; |
906 temp_gas_switch = 3; | 904 temp_gas_switch = 3; |
907 switch_deco = deco_gas_change3; | 905 switch_deco = deco_gas_change3; |
908 } | 906 } |
909 if(deco_gas_change4 && (temp_deco < deco_gas_change4)) | 907 if(deco_gas_change4 && ((temp_depth_limit-1) <= deco_gas_change4)) |
910 { | 908 { |
911 calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01; | 909 calc_N2_ratio = char_I_deco_N2_ratio4 * 0.01; |
912 calc_He_ratio = char_I_deco_He_ratio4 * 0.01; | 910 calc_He_ratio = char_I_deco_He_ratio4 * 0.01; |
913 temp_gas_switch = 4; | 911 temp_gas_switch = 4; |
914 switch_deco = deco_gas_change4; | 912 switch_deco = deco_gas_change4; |
915 } | 913 } |
916 if(deco_gas_change5 && (temp_deco < deco_gas_change5)) | 914 if(deco_gas_change5 && ((temp_depth_limit-1) <= deco_gas_change5)) |
917 { | 915 { |
918 calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01; | 916 calc_N2_ratio = char_I_deco_N2_ratio5 * 0.01; |
919 calc_He_ratio = char_I_deco_He_ratio5 * 0.01; | 917 calc_He_ratio = char_I_deco_He_ratio5 * 0.01; |
920 temp_gas_switch = 5; | 918 temp_gas_switch = 5; |
921 switch_deco = deco_gas_change5; | 919 switch_deco = deco_gas_change5; |
923 } | 921 } |
924 | 922 |
925 // If there is a better gas available | 923 // If there is a better gas available |
926 if( temp_gas_switch ) | 924 if( temp_gas_switch ) |
927 { | 925 { |
928 // Should detect gas switch only when gas do changes... | 926 // Should restart gas-switch delay only when gas do changes... |
929 // sim_gas_last_used: used to detect just once in each ascent simu. | 927 // sim_gas_last_used: used to detect just once in each ascent simu. |
930 // N2_ratio : used to detect when already breathing that gas. | 928 // N2_ratio : used to detect when already breathing that gas. |
931 if( sim_gas_last_used < temp_gas_switch | 929 if( sim_gas_last_used < temp_gas_switch |
932 && sim_gas_delay <= sim_dive_mins | 930 && sim_gas_delay <= sim_dive_mins |
933 && (calc_N2_ratio != N2_ratio || calc_He_ratio != He_ratio)) | 931 && (calc_N2_ratio != N2_ratio || calc_He_ratio != He_ratio)) |
937 | 935 |
938 // Apply depth correction ONLY if CF#55 is not null: | 936 // Apply depth correction ONLY if CF#55 is not null: |
939 if( sim_gas_delay > 0 ) | 937 if( sim_gas_delay > 0 ) |
940 { | 938 { |
941 sim_gas_delay += sim_dive_mins; | 939 sim_gas_delay += sim_dive_mins; |
942 temp_deco = switch_deco - float_deco_distance; | 940 temp_depth_limit = switch_deco; |
943 temp_depth_limit = (temp_deco - pres_surface) / 0.09985; | |
944 } | 941 } |
945 } | 942 } |
946 } | 943 } |
947 else | 944 else |
948 sim_gas_delay = 0; | 945 sim_gas_delay = 0; |
952 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 ); | 949 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 ); |
953 } | 950 } |
954 | 951 |
955 ////////////////////////////////////////////////////////////////////////////// | 952 ////////////////////////////////////////////////////////////////////////////// |
956 // | 953 // |
957 static void alveolar_presures(void) | 954 // Input: calc_N2_ratio, calc_He_ratio : simulated gas mix. |
958 { | 955 // temp_deco : simulated respiration pressure + security offset (deco_distance) |
956 // Water-vapor pressure inside lumbs (ppWVapour). | |
957 // | |
958 // Output: ppO2, ppHe. | |
959 // | |
960 static void sim_alveolar_presures(void) | |
961 { | |
962 overlay float deco_diluent = temp_deco; // new in v.101 | |
963 | |
964 //---- CCR mode : deco gas switch ? -------------------------------------- | |
959 if (char_I_const_ppO2 != 0) | 965 if (char_I_const_ppO2 != 0) |
960 { | 966 { |
961 if (temp_deco > deco_ppO2_change) | 967 // In CCR mode, calc_XX_ratio == XX_ratio. |
962 { | 968 if( temp_deco > deco_ppO2_change ) |
963 deco_diluent = ((temp_deco - const_ppO2)/(N2_ratio + He_ratio)); | 969 deco_diluent = ((temp_deco - const_ppO2)/(calc_N2_ratio + calc_He_ratio)); |
964 } | |
965 else | 970 else |
966 { | 971 deco_diluent = ((temp_deco - deco_ppO2)/(calc_N2_ratio + calc_He_ratio)); |
967 deco_diluent = ((temp_deco - deco_ppO2)/(N2_ratio + He_ratio)); | 972 |
968 } | 973 if (deco_diluent > temp_deco) |
974 deco_diluent = temp_deco; | |
969 } | 975 } |
970 | 976 |
971 if (deco_diluent > temp_deco) | 977 // Take deco offset into account, but not at surface. |
972 deco_diluent = temp_deco; | 978 if( deco_diluent > pres_surface ) |
973 if (deco_diluent > ppWVapour) | 979 deco_diluent += float_deco_distance; |
980 | |
981 if( deco_diluent > ppWVapour ) | |
974 { | 982 { |
975 ppO2 = calc_N2_ratio * (deco_diluent - ppWVapour); | 983 ppO2 = calc_N2_ratio * (deco_diluent - ppWVapour); |
976 ppHe = calc_He_ratio * (deco_diluent - ppWVapour); | 984 ppHe = calc_He_ratio * (deco_diluent - ppWVapour); |
977 } | 985 } |
978 else | 986 else |
1001 int_O_DBG_post_bitfield = 0; | 1009 int_O_DBG_post_bitfield = 0; |
1002 char_O_NDL_at_20mtr = 255; | 1010 char_O_NDL_at_20mtr = 255; |
1003 | 1011 |
1004 // Kludge: the 0.0002 of 0.7902 are missing with standard air. | 1012 // Kludge: the 0.0002 of 0.7902 are missing with standard air. |
1005 N2_ratio = 0.7902; | 1013 N2_ratio = 0.7902; |
1006 pres_respiration = (float)int_I_pres_respiration / 1000.0; | 1014 pres_respiration = int_I_pres_respiration * 0.001; |
1007 | 1015 |
1008 for(ci=0; ci<16; ci++) | 1016 for(ci=0; ci<16; ci++) |
1009 { | 1017 { |
1010 // cycle through the 16 Bühlmann tissues | 1018 // cycle through the 16 Bühlmann tissues |
1011 overlay float p = N2_ratio * (pres_respiration - ppWVapour); | 1019 overlay float p = N2_ratio * (pres_respiration - ppWVapour); |
1100 // dive data. | 1108 // dive data. |
1101 backup_GF_step = locked_GF_step; | 1109 backup_GF_step = locked_GF_step; |
1102 backup_low_depth = low_depth; | 1110 backup_low_depth = low_depth; |
1103 | 1111 |
1104 // Check proposed gas at begin of ascent simulation | 1112 // Check proposed gas at begin of ascent simulation |
1105 temp_deco = pres_respiration; // Starts from current real depth. | |
1106 sim_dive_mins = int_I_divemins; // and time. | 1113 sim_dive_mins = int_I_divemins; // and time. |
1114 temp_depth_limit = (int)(0.95 + (pres_respiration - pres_surface) / 0.09985) ; // Starts from current real depth. | |
1107 check_gas_switch(); | 1115 check_gas_switch(); |
1108 | 1116 |
1109 backup_gas_used = sim_gas_last_used;// And save for later simu steps. | 1117 backup_gas_used = sim_gas_last_used;// And save for later simu steps. |
1110 backup_gas_delay = sim_gas_delay; | 1118 backup_gas_delay = sim_gas_delay; |
1111 | 1119 |
1155 // ____________________________________________________ | 1163 // ____________________________________________________ |
1156 // | 1164 // |
1157 // _____________ G A S _ C H A N G E S ________________ | 1165 // _____________ G A S _ C H A N G E S ________________ |
1158 // ____________________________________________________ | 1166 // ____________________________________________________ |
1159 | 1167 |
1160 // Keep a marhin of 150mbar = 1.50m | 1168 // Keep a margin of 150mbar = 1.50m |
1161 int_temp = (int_I_pres_respiration - int_I_pres_surface) + MBAR_REACH_GASCHANGE_AUTO_CHANGE_OFF; | 1169 int_temp = (int_I_pres_respiration - int_I_pres_surface) |
1170 + MBAR_REACH_GASCHANGE_AUTO_CHANGE_OFF; | |
1162 | 1171 |
1163 deco_gas_change1 = 0.0; | 1172 deco_gas_change1 = 0; |
1164 deco_gas_change2 = 0.0; | 1173 deco_gas_change2 = 0; |
1165 deco_gas_change3 = 0.0; | 1174 deco_gas_change3 = 0; |
1166 deco_gas_change4 = 0.0; | 1175 deco_gas_change4 = 0; |
1167 deco_gas_change5 = 0.0; | 1176 deco_gas_change5 = 0; |
1168 | 1177 |
1169 // Gas are selectable if we did not pass the change depth by more than 1.50m: | 1178 // Gas are selectable if we did not pass the change depth by more than 1.50m: |
1170 if(char_I_deco_gas_change1) | 1179 if(char_I_deco_gas_change1) |
1171 { | 1180 { |
1172 if( int_temp > 100 *(short)char_I_deco_gas_change1 ) | 1181 if( int_temp > 100 *(short)char_I_deco_gas_change1 ) |
1173 deco_gas_change1 = char_I_deco_gas_change1 / 9.995 | 1182 deco_gas_change1 = char_I_deco_gas_change1; |
1174 + pres_surface | |
1175 + float_deco_distance; | |
1176 } | 1183 } |
1177 if(char_I_deco_gas_change2) | 1184 if(char_I_deco_gas_change2) |
1178 { | 1185 { |
1179 if( int_temp > 100 *(short)char_I_deco_gas_change2 ) | 1186 if( int_temp > 100 *(short)char_I_deco_gas_change2 ) |
1180 deco_gas_change2 = char_I_deco_gas_change2 / 9.995 | 1187 deco_gas_change2 = char_I_deco_gas_change2; |
1181 + pres_surface | |
1182 + float_deco_distance; | |
1183 } | 1188 } |
1184 if(char_I_deco_gas_change3) | 1189 if(char_I_deco_gas_change3) |
1185 { | 1190 { |
1186 if( int_temp > 100 *(short)char_I_deco_gas_change3 ) | 1191 if( int_temp > 100 *(short)char_I_deco_gas_change3 ) |
1187 deco_gas_change3 = char_I_deco_gas_change3 / 9.995 | 1192 deco_gas_change3 = char_I_deco_gas_change3; |
1188 + pres_surface | |
1189 + float_deco_distance; | |
1190 } | 1193 } |
1191 if(char_I_deco_gas_change4) | 1194 if(char_I_deco_gas_change4) |
1192 { | 1195 { |
1193 if( int_temp > 100 *(short)char_I_deco_gas_change4 ) | 1196 if( int_temp > 100 *(short)char_I_deco_gas_change4 ) |
1194 deco_gas_change4 = char_I_deco_gas_change4 / 9.995 | 1197 deco_gas_change4 = char_I_deco_gas_change4; |
1195 + pres_surface | |
1196 + float_deco_distance; | |
1197 } | 1198 } |
1198 if(char_I_deco_gas_change5) | 1199 if(char_I_deco_gas_change5) |
1199 { | 1200 { |
1200 if( int_temp > 100 *(short)char_I_deco_gas_change5 ) | 1201 if( int_temp > 100 *(short)char_I_deco_gas_change5 ) |
1201 deco_gas_change5 = char_I_deco_gas_change5 / 9.995 | 1202 deco_gas_change5 = char_I_deco_gas_change5; |
1202 + pres_surface | |
1203 + float_deco_distance; | |
1204 } | 1203 } |
1205 | 1204 |
1206 const_ppO2 = char_I_const_ppO2 * 0.01; | 1205 const_ppO2 = char_I_const_ppO2 * 0.01; |
1207 deco_ppO2_change = char_I_deco_ppO2_change / 99.95 | 1206 deco_ppO2_change = char_I_deco_ppO2_change / 99.95 |
1208 + pres_surface | 1207 + pres_surface |
1275 { | 1274 { |
1276 overlay unsigned char loop; | 1275 overlay unsigned char loop; |
1277 | 1276 |
1278 for(loop = 0; loop < 16; ++loop) | 1277 for(loop = 0; loop < 16; ++loop) |
1279 { | 1278 { |
1279 overlay float new_presure; | |
1280 overlay unsigned char backup_gas_last_used; | |
1281 | |
1280 // Do not ascent while doing a gas switch. | 1282 // Do not ascent while doing a gas switch. |
1281 if( sim_gas_delay <= sim_dive_mins ) | 1283 if( sim_gas_delay <= sim_dive_mins ) |
1282 { | 1284 { |
1285 backup_gas_last_used = sim_gas_last_used; | |
1283 calc_nextdecodepth(); | 1286 calc_nextdecodepth(); |
1284 | 1287 |
1285 //---- Finish computations once surface is reached --------------- | 1288 //---- Finish computations once surface is reached --------------- |
1286 if( temp_depth_limit == 0 ) | 1289 if( temp_depth_limit == 0 ) |
1287 { | 1290 { |
1288 copy_deco_table(); | 1291 copy_deco_table(); |
1289 calc_ascenttime(); | 1292 calc_ascenttime(); |
1290 char_O_deco_status = 0; // calc nullzeit next time. | 1293 char_O_deco_status = 0; // calc nullzeit next time. |
1291 return; | 1294 return; |
1292 } | 1295 } |
1293 | 1296 } |
1294 //---- Else, continue simulating the stops ----------------------- | 1297 |
1295 check_gas_switch(); // Calculate N2_ratio and He_ratio. | 1298 //---- Can we ascent to that stop at once, or is it just ascenting ? |
1299 new_presure = temp_depth_limit * 0.09985 // Convert to relative bar, | |
1300 + pres_surface; // To absolute, | |
1301 | |
1302 if( (temp_deco - new_presure) > 1.0 ) // More than 10m/mn ? | |
1303 { | |
1304 temp_deco -= 1.0; // Just keep ascending. | |
1305 sim_gas_delay = 0; // Reset gas delay, | |
1306 sim_gas_last_used = backup_gas_last_used; // and usage history. | |
1307 } | |
1308 else | |
1309 { | |
1310 temp_deco = new_presure; | |
1311 update_deco_table(); // This is a one minute stops. | |
1296 } | 1312 } |
1297 | 1313 |
1298 //---- Then update tissue and decoplan ------------------------------- | 1314 //---- Then update tissue and decoplan ------------------------------- |
1299 sim_dive_mins++; // Advance simulated time by 1 minute. | 1315 sim_dive_mins++; // Advance simulated time by 1 minute. |
1300 alveolar_presures(); // Updates ppN2 and ppHe. | 1316 sim_alveolar_presures(); // Updates ppN2 and ppHe. |
1301 sim_tissue(1); // Simulate compartiments for 1 minute. | 1317 sim_tissue(1); // Simulate compartiments for 1 minute. |
1302 update_deco_table(); // Add one minute stops. | |
1303 } | 1318 } |
1304 | 1319 |
1305 // Surface not reached, need more stops... | 1320 // Surface not reached, need more stops... |
1306 char_O_deco_status = 1; // calc more stops next time. | 1321 char_O_deco_status = 1; // calc more stops next time. |
1307 } | 1322 } |
1318 update_startvalues(); | 1333 update_startvalues(); |
1319 clear_deco_table(); | 1334 clear_deco_table(); |
1320 | 1335 |
1321 temp_deco = pres_respiration; // Starts from current real depth. | 1336 temp_deco = pres_respiration; // Starts from current real depth. |
1322 | 1337 |
1338 // Do we have a gas switch going on ? | |
1339 if( sim_gas_delay > sim_dive_mins ) | |
1340 return; | |
1341 | |
1323 // Loop until first stop, gas switch, or surface is reached. | 1342 // Loop until first stop, gas switch, or surface is reached. |
1324 for(;;) | 1343 for(;;) |
1325 { | 1344 { |
1326 // Do we have a gas switch going on ? | |
1327 if( sim_gas_delay > sim_dive_mins ) | |
1328 break; | |
1329 | |
1330 // No: try ascending 1 full minute. | 1345 // No: try ascending 1 full minute. |
1331 temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min. | 1346 temp_deco -= 1.0; // Ascent 1 min, at 10m/min. == 1bar/min. |
1347 | |
1348 // Compute sim_lead_tissue_limit at GF_low (deepest stop). | |
1349 sim_limit(GF_low); | |
1350 | |
1351 // Did we reach deepest remaining stop ? | |
1352 if( temp_deco <= sim_lead_tissue_limit ) | |
1353 { | |
1354 temp_deco += 1.0; // Restore last correct depth. | |
1355 break; // Return stop found ! | |
1356 } | |
1332 | 1357 |
1333 // Did we reach surface ? | 1358 // Did we reach surface ? |
1334 if( temp_deco <= pres_surface ) | 1359 if( temp_deco <= pres_surface ) |
1335 { | 1360 { |
1336 temp_deco = pres_surface; // Yes: finished ! | 1361 temp_deco = pres_surface; // Yes: finished ! |
1337 break; | 1362 break; |
1338 } | 1363 } |
1339 | 1364 |
1340 // Compute sim_lead_tissue_limit at GF_low (deepest stop). | 1365 // Check gas change 5 meter below new depth. |
1341 sim_limit(GF_low); | 1366 temp_depth_limit = (temp_deco + 0.5 - pres_surface) / 0.09985; |
1342 | 1367 check_gas_switch(); |
1343 // Did we reach deepest remaining stop ? | 1368 if( sim_gas_delay > sim_dive_mins ) |
1344 if( temp_deco <= sim_lead_tissue_limit ) | 1369 break; |
1345 { | |
1346 temp_deco = sim_lead_tissue_limit; | |
1347 break; // Return stop found ! | |
1348 } | |
1349 | |
1350 temp_deco += 0.5; // Check gas change 5 meter below new depth. | |
1351 check_gas_switch(); | |
1352 temp_deco -= 0.5; // Back to new depth. | |
1353 | 1370 |
1354 sim_dive_mins++; // Advance simulated time by 1 minute. | 1371 sim_dive_mins++; // Advance simulated time by 1 minute. |
1355 alveolar_presures(); // Calculate ppO2/ppHe at new depth. | 1372 sim_alveolar_presures(); // Still uses temp_deco. |
1356 sim_tissue(1); // and update tissues for 1 min. | 1373 sim_tissue(1); // and update tissues for 1 min. |
1357 } | 1374 } |
1358 | |
1359 // Always updates depth in meter, too: | |
1360 temp_depth_limit = (temp_deco - pres_surface) / 0.09985; | |
1361 } | 1375 } |
1362 | 1376 |
1363 ////////////////////////////////////////////////////////////////////////////// | 1377 ////////////////////////////////////////////////////////////////////////////// |
1364 // calc_tissue | 1378 // calc_tissue |
1365 // | 1379 // |
1571 // Function separated from sim_tissue() to allow recomputing limit on | 1585 // Function separated from sim_tissue() to allow recomputing limit on |
1572 // different depth, because it depends on current gradient factor. | 1586 // different depth, because it depends on current gradient factor. |
1573 // | 1587 // |
1574 static void sim_limit(PARAMETER float GF_current) | 1588 static void sim_limit(PARAMETER float GF_current) |
1575 { | 1589 { |
1590 assert( 0.0 < GF_current && GF_current <= 1.0f); | |
1591 | |
1576 sim_lead_tissue_limit = 0.0; | 1592 sim_lead_tissue_limit = 0.0; |
1577 sim_lead_tissue_no = 255; | 1593 sim_lead_tissue_no = 0; // If no one is critic, keep first tissue. |
1578 | 1594 |
1579 for(ci=0; ci<16; ci++) | 1595 for(ci=0; ci<16; ci++) |
1580 { | 1596 { |
1581 overlay float p = sim_pres_tissue[ci] + (sim_pres_tissue+16)[ci]; | 1597 overlay float p = sim_pres_tissue[ci] + (sim_pres_tissue+16)[ci]; |
1582 | 1598 |
1643 overlay unsigned char x; | 1659 overlay unsigned char x; |
1644 assert( temp_depth_limit < 128 ); // Can't be negativ (overflown). | 1660 assert( temp_depth_limit < 128 ); // Can't be negativ (overflown). |
1645 | 1661 |
1646 for(x=0; x<32; ++x) | 1662 for(x=0; x<32; ++x) |
1647 { | 1663 { |
1664 // Make sure deco-stops are recorded in order: | |
1665 assert( !internal_deco_depth[x] || temp_depth_limit <= internal_deco_depth[x] ); | |
1666 | |
1648 if( internal_deco_depth[x] == temp_depth_limit ) | 1667 if( internal_deco_depth[x] == temp_depth_limit ) |
1649 { | 1668 { |
1650 // Do not overflow (max 255') | 1669 // Do not overflow (max 255') |
1651 if( internal_deco_time[x] < 255 ) | 1670 if( internal_deco_time[x] < 255 ) |
1652 { | 1671 { |
1846 flag_in_divemode = 0; | 1865 flag_in_divemode = 0; |
1847 set_dbg_end_of_dive(); | 1866 set_dbg_end_of_dive(); |
1848 } | 1867 } |
1849 | 1868 |
1850 N2_ratio = 0.7902; // FIXED, sum lt. buehlmann | 1869 N2_ratio = 0.7902; // FIXED, sum lt. buehlmann |
1851 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system | 1870 pres_respiration = int_I_pres_respiration * 0.001; // assembler code uses different digit system |
1852 pres_surface = (float)int_I_pres_surface / 1000.0; // the b"uhlmann formula using pres_surface does not use the N2_ratio | 1871 pres_surface = int_I_pres_surface * 0.001; // the b"uhlmann formula using pres_surface does not use the N2_ratio |
1853 ppO2 = N2_ratio * (pres_respiration - ppWVapour); // ppWVapour is the extra pressure in the body | 1872 ppO2 = N2_ratio * (pres_respiration - ppWVapour); // ppWVapour is the extra pressure in the body |
1854 ppHe = 0.0; | 1873 ppHe = 0.0; |
1855 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142) | 1874 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142) |
1856 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; | 1875 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; |
1857 | 1876 |