Mercurial > public > mk2
comparison code_part1/OSTC_code_c_part2/p2_deco.c @ 711:f555590f1419
minor cleanups for CNS/NOAA bugfix.
author | JeanDo <jd.gascuel@free.fr> |
---|---|
date | Thu, 09 May 2013 00:26:41 +0200 |
parents | d36f060e8203 |
children | c498d6972087 8466932a2fcf |
comparison
equal
deleted
inserted
replaced
710:d36f060e8203 | 711:f555590f1419 |
---|---|
85 // 2012/02/25: [jDG] Looking for a more stable LOW grad factor reference. | 85 // 2012/02/25: [jDG] Looking for a more stable LOW grad factor reference. |
86 // 2012/09/10: [mH] Fill char_O_deco_time_for_log for logbook write | 86 // 2012/09/10: [mH] Fill char_O_deco_time_for_log for logbook write |
87 // 2012/10/05: [jDG] Better deco_gas_volumes accuracy (average depth, switch between stop). | 87 // 2012/10/05: [jDG] Better deco_gas_volumes accuracy (average depth, switch between stop). |
88 // 2013/03/05: [jDG] Should vault low_depth too. | 88 // 2013/03/05: [jDG] Should vault low_depth too. |
89 // 2013/03/05: [jDG] Wrobell remark: ascent_to_first_stop works better with finer steps (2sec). | 89 // 2013/03/05: [jDG] Wrobell remark: ascent_to_first_stop works better with finer steps (2sec). |
90 // 2013/05/08: [jDG] A. Salm remark: NOAA tables for CNS are in ATA, not bar. | |
90 // | 91 // |
91 // TODO: | 92 // TODO: |
92 // + Allow to abort MD2 calculation (have to restart next time). | 93 // + Allow to abort MD2 calculation (have to restart next time). |
93 // | 94 // |
94 // Literature: | 95 // Literature: |
172 // Simulation context: used to predict ascent. | 173 // Simulation context: used to predict ascent. |
173 unsigned char sim_lead_tissue_no; // Leading compatiment number. | 174 unsigned char sim_lead_tissue_no; // Leading compatiment number. |
174 float sim_lead_tissue_limit; // Buhlmann tolerated pressure. | 175 float sim_lead_tissue_limit; // Buhlmann tolerated pressure. |
175 | 176 |
176 // Real context: what we are doing now. | 177 // Real context: what we are doing now. |
177 static float calc_lead_tissue_limit; // | 178 static float calc_lead_tissue_limit; // |
178 | 179 |
179 static unsigned char internal_deco_time[NUM_STOPS]; | 180 static unsigned char internal_deco_time[NUM_STOPS]; |
180 static unsigned char internal_deco_depth[NUM_STOPS]; | 181 static unsigned char internal_deco_depth[NUM_STOPS]; |
181 | 182 |
182 static float cns_vault; | 183 static float cns_vault; |
208 static float var_He_ht; // Half-time for current N2 tissue. | 209 static float var_He_ht; // Half-time for current N2 tissue. |
209 | 210 |
210 static float pres_diluent; // new in v.101 | 211 static float pres_diluent; // new in v.101 |
211 static float const_ppO2; // new in v.101 | 212 static float const_ppO2; // new in v.101 |
212 | 213 |
213 static unsigned char sim_gas_last_depth; // Depth of last used gas, to detected a gas switch. | 214 static unsigned char sim_gas_last_depth; // Depth of last used gas, to detected a gas switch. |
214 static unsigned char sim_gas_last_used; // Number of last used gas, to detected a gas switch. | 215 static unsigned char sim_gas_last_used; // Number of last used gas, to detected a gas switch. |
215 static unsigned short sim_gas_delay; // Time of gas-switch-stop ends [min on dive]. | 216 static unsigned short sim_gas_delay; // Time of gas-switch-stop ends [min on dive]. |
216 static unsigned short sim_dive_mins; // Simulated dive time. | 217 static unsigned short sim_dive_mins; // Simulated dive time. |
217 static float calc_N2_ratio; // Simulated (switched) nitrogen ratio. | 218 static float calc_N2_ratio; // Simulated (switched) nitrogen ratio. |
218 static float calc_He_ratio; // Simulated (switched) helium ratio. | 219 static float calc_He_ratio; // Simulated (switched) helium ratio. |
219 static float CNS_fraction; // new in v.101 | 220 static float CNS_fraction; // new in v.101 |
343 LFSR 1,C_STACK | 344 LFSR 1,C_STACK |
344 MOVLW 0xCC | 345 MOVLW 0xCC |
345 loop: MOVWF POSTINC1,0 | 346 loop: MOVWF POSTINC1,0 |
346 TSTFSZ FSR1L,0 | 347 TSTFSZ FSR1L,0 |
347 BRA loop | 348 BRA loop |
348 | 349 |
349 LFSR 1,C_STACK | 350 LFSR 1,C_STACK |
350 LFSR 2,C_STACK | 351 LFSR 2,C_STACK |
351 _endasm | 352 _endasm |
352 } | 353 } |
353 # else | 354 # else |
399 #endif | 400 #endif |
400 } | 401 } |
401 | 402 |
402 ////////////////////////////////////////////////////////////////////////////// | 403 ////////////////////////////////////////////////////////////////////////////// |
403 // read buhlmann tables A and B for compatriment ci | 404 // read buhlmann tables A and B for compatriment ci |
404 // | 405 // |
405 static void read_buhlmann_coefficients(void) | 406 static void read_buhlmann_coefficients(void) |
406 { | 407 { |
407 #ifndef CROSS_COMPILE | 408 #ifndef CROSS_COMPILE |
408 // Note: we don't use far rom pointer, because the | 409 // Note: we don't use far rom pointer, because the |
409 // 24 bits is too complex, hence we have to set | 410 // 24 bits is too complex, hence we have to set |
480 } | 481 } |
481 } | 482 } |
482 | 483 |
483 ////////////////////////////////////////////////////////////////////////////// | 484 ////////////////////////////////////////////////////////////////////////////// |
484 // read buhlmann tables for compatriment ci | 485 // read buhlmann tables for compatriment ci |
485 // | 486 // |
486 static void read_buhlmann_ht(void) | 487 static void read_buhlmann_ht(void) |
487 { | 488 { |
488 | 489 |
489 #ifndef CROSS_COMPILE | 490 #ifndef CROSS_COMPILE |
490 // Note: we don't use far rom pointer, because the | 491 // Note: we don't use far rom pointer, because the |
500 assert( ci < NUM_COMP ); | 501 assert( ci < NUM_COMP ); |
501 { | 502 { |
502 overlay rom const float* ptr = &buhlmann_ht[2*ci]; | 503 overlay rom const float* ptr = &buhlmann_ht[2*ci]; |
503 var_N2_ht = *ptr++; | 504 var_N2_ht = *ptr++; |
504 var_He_ht = *ptr++; | 505 var_He_ht = *ptr++; |
505 } | 506 } |
506 | 507 |
507 assert( 4.0 <= var_N2_ht && var_N2_ht <= 635.0 ); | 508 assert( 4.0 <= var_N2_ht && var_N2_ht <= 635.0 ); |
508 assert( 1.5099 <= var_He_ht && var_He_ht <= 240.03 ); | 509 assert( 1.5099 <= var_He_ht && var_He_ht <= 240.03 ); |
509 } | 510 } |
510 | 511 |
538 // Recompute leading gas limit, at current depth: | 539 // Recompute leading gas limit, at current depth: |
539 overlay float depth = (temp_deco - pres_surface) * BAR_TO_METER; | 540 overlay float depth = (temp_deco - pres_surface) * BAR_TO_METER; |
540 | 541 |
541 // At most, ascent 1 minute, at 10m/min == 10.0 m. | 542 // At most, ascent 1 minute, at 10m/min == 10.0 m. |
542 overlay float min_depth = (depth > 10.0) ? (depth - 10.0) : 0.0; | 543 overlay float min_depth = (depth > 10.0) ? (depth - 10.0) : 0.0; |
543 | 544 |
544 // Do we need to stop at current depth ? | 545 // Do we need to stop at current depth ? |
545 overlay unsigned char need_stop = 0; | 546 overlay unsigned char need_stop = 0; |
546 | 547 |
547 assert( depth >= -0.2 ); // Allow for 200mbar of weather change. | 548 assert( depth >= -0.2 ); // Allow for 200mbar of weather change. |
548 | 549 |
549 //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ | 550 //---- ZH-L16 + GRADIENT FACTOR model ------------------------------------ |
550 if( char_I_deco_model != 0 ) | 551 if( char_I_deco_model != 0 ) |
551 { | 552 { |
552 overlay unsigned char first_stop = 0; | 553 overlay unsigned char first_stop = 0; |
553 overlay float p; | 554 overlay float p; |
554 | 555 |
555 sim_limit( GF_low ); | 556 sim_limit( GF_low ); |
556 p = sim_lead_tissue_limit - pres_surface; | 557 p = sim_lead_tissue_limit - pres_surface; |
594 next_stop = 0; | 595 next_stop = 0; |
595 else if( first_stop == 6 ) | 596 else if( first_stop == 6 ) |
596 next_stop = char_I_depth_last_deco; | 597 next_stop = char_I_depth_last_deco; |
597 else | 598 else |
598 next_stop = first_stop - 3; // Index of next (upper) stop. | 599 next_stop = first_stop - 3; // Index of next (upper) stop. |
599 | 600 |
600 // Total preassure at the new stop candidate: | 601 // Total preassure at the new stop candidate: |
601 p = next_stop * METER_TO_BAR | 602 p = next_stop * METER_TO_BAR |
602 + pres_surface; | 603 + pres_surface; |
603 | 604 |
604 // Recompute limit for this new stop: | 605 // Recompute limit for this new stop: |
605 if( !low_depth || next_stop > low_depth ) | 606 if( !low_depth || next_stop > low_depth ) |
606 sim_limit( GF_low ); | 607 sim_limit( GF_low ); |
607 else | 608 else |
614 // Else, validate that stop and loop... | 615 // Else, validate that stop and loop... |
615 first_stop = next_stop; | 616 first_stop = next_stop; |
616 } | 617 } |
617 | 618 |
618 no_deco_stop: | 619 no_deco_stop: |
619 temp_depth_limit = min_depth; | 620 temp_depth_limit = min_depth; |
620 goto done; | 621 goto done; |
621 | 622 |
622 deco_stop_found: | 623 deco_stop_found: |
623 // next stop is the last validated depth found, aka first_stop | 624 // next stop is the last validated depth found, aka first_stop |
624 need_stop = 1; // Hit. | 625 need_stop = 1; // Hit. |
625 temp_depth_limit = first_stop; // Stop depth, in meter. | 626 temp_depth_limit = first_stop; // Stop depth, in meter. |
626 | 627 |
627 done: | 628 done: |
628 ; | 629 ; |
629 } | 630 } |
630 else //---- ZH-L16 model ------------------------------------------------- | 631 else //---- ZH-L16 model ------------------------------------------------- |
631 { | 632 { |
632 overlay float pres_gradient; | 633 overlay float pres_gradient; |
633 | 634 |
634 // Original model | 635 // Original model |
635 // optimized in v.101 | 636 // optimized in v.101 |
636 // char_I_depth_last_deco included in v.101 | 637 // char_I_depth_last_deco included in v.101 |
637 | 638 |
638 // Compute sim_lead_tissue_limit too, but just once. | 639 // Compute sim_lead_tissue_limit too, but just once. |
639 sim_limit(1.0); | 640 sim_limit(1.0); |
640 | 641 |
641 pres_gradient = sim_lead_tissue_limit - pres_surface; | 642 pres_gradient = sim_lead_tissue_limit - pres_surface; |
642 if (pres_gradient >= 0) | 643 if (pres_gradient >= 0) |
643 { | 644 { |
644 pres_gradient *= BAR_TO_METER/3; // Bar --> stop number; | 645 pres_gradient *= BAR_TO_METER/3; // Bar --> stop number; |
645 temp_depth_limit = 3 * (short) (pres_gradient + 0.99); // --> metre : depth for deco | 646 temp_depth_limit = 3 * (short) (pres_gradient + 0.99); // --> metre : depth for deco |
646 need_stop = 1; // Hit. | 647 need_stop = 1; // Hit. |
647 | 648 |
648 // Implement last stop at 4m/5m/6m... | 649 // Implement last stop at 4m/5m/6m... |
649 if( temp_depth_limit == 3 ) | 650 if( temp_depth_limit == 3 ) |
650 temp_depth_limit = char_I_depth_last_deco; | 651 temp_depth_limit = char_I_depth_last_deco; |
651 } | 652 } |
652 else | 653 else |
653 temp_depth_limit = 0; | 654 temp_depth_limit = 0; |
654 } | 655 } |
655 | 656 |
656 //---- Check gas change -------------------------------------------------- | 657 //---- Check gas change -------------------------------------------------- |
657 need_stop |= gas_switch_deepest(); // Update temp_depth_limit if there is a change, | 658 need_stop |= gas_switch_deepest(); // Update temp_depth_limit if there is a change, |
658 | 659 |
659 return need_stop; | 660 return need_stop; |
666 // while computing the next set. | 667 // while computing the next set. |
667 // | 668 // |
668 static void copy_deco_table(void) | 669 static void copy_deco_table(void) |
669 { | 670 { |
670 // Copy depth of the first (deepest) stop, because when reversing | 671 // Copy depth of the first (deepest) stop, because when reversing |
671 // order, it will be hard to find... | 672 // order, it will be hard to find... |
672 char_O_first_deco_depth = internal_deco_depth[0] & 0x7F; | 673 char_O_first_deco_depth = internal_deco_depth[0] & 0x7F; |
673 char_O_first_deco_time = internal_deco_time [0]; | 674 char_O_first_deco_time = internal_deco_time [0]; |
674 | 675 |
675 if( read_custom_function(54) & 1 ) //---- Should we reverse table ? ------ | 676 if( read_custom_function(54) & 1 ) //---- Should we reverse table ? ------ |
676 { | 677 { |
742 static void temp_tissue_safety(void) | 743 static void temp_tissue_safety(void) |
743 { | 744 { |
744 assert( 0.0 < float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 ); | 745 assert( 0.0 < float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 ); |
745 assert( 1.0 <= float_saturation_multiplier && float_saturation_multiplier <= 2.0 ); | 746 assert( 1.0 <= float_saturation_multiplier && float_saturation_multiplier <= 2.0 ); |
746 | 747 |
747 if( char_I_deco_model == 0 ) | 748 if( char_I_deco_model == 0 ) |
748 { | 749 { |
749 if( temp_tissue < 0.0 ) | 750 if( temp_tissue < 0.0 ) |
750 temp_tissue *= float_desaturation_multiplier; | 751 temp_tissue *= float_desaturation_multiplier; |
751 else | 752 else |
752 temp_tissue *= float_saturation_multiplier; | 753 temp_tissue *= float_saturation_multiplier; |
753 } | 754 } |
754 } | 755 } |
755 | 756 |
756 ////////////////////////////////////////////////////////////////////////////// | 757 ////////////////////////////////////////////////////////////////////////////// |
757 ////////////////////////////////////////////////////////////////////////////// | 758 ////////////////////////////////////////////////////////////////////////////// |
758 // ** THE JUMP-IN CODE ** | 759 // ** THE JUMP-IN CODE ** |
793 // | 794 // |
794 void deco_calc_tissue(void) | 795 void deco_calc_tissue(void) |
795 { | 796 { |
796 RESET_C_STACK | 797 RESET_C_STACK |
797 calc_hauptroutine_update_tissues(); | 798 calc_hauptroutine_update_tissues(); |
798 } | 799 } |
799 | 800 |
800 ////////////////////////////////////////////////////////////////////////////// | 801 ////////////////////////////////////////////////////////////////////////////// |
801 | 802 |
802 void deco_calc_wo_deco_step_1_min(void) | 803 void deco_calc_wo_deco_step_1_min(void) |
803 { | 804 { |
814 calc_dive_interval(); | 815 calc_dive_interval(); |
815 } | 816 } |
816 | 817 |
817 ////////////////////////////////////////////////////////////////////////////// | 818 ////////////////////////////////////////////////////////////////////////////// |
818 // Find current gas in the list (if any). | 819 // Find current gas in the list (if any). |
819 // | 820 // |
820 // Input: char_I_current_gas = 1..6 | 821 // Input: char_I_current_gas = 1..6 |
821 // | 822 // |
822 // Output: sim_gas_last_depth = 0..5, temp_depth_limit. | 823 // Output: sim_gas_last_depth = 0..5, temp_depth_limit. |
823 // | 824 // |
824 static void gas_switch_find_current(void) | 825 static void gas_switch_find_current(void) |
838 sim_gas_last_used = 0; // Gas 6 = manual set | 839 sim_gas_last_used = 0; // Gas 6 = manual set |
839 } | 840 } |
840 | 841 |
841 ////////////////////////////////////////////////////////////////////////////// | 842 ////////////////////////////////////////////////////////////////////////////// |
842 // Find deepest available gas. | 843 // Find deepest available gas. |
843 // | 844 // |
844 // Input: temp_depth_limit, | 845 // Input: temp_depth_limit, |
845 // deco_gas_change[] | 846 // deco_gas_change[] |
846 // sim_gas_delay, sim_gas_depth_used, sim_dive_mins. | 847 // sim_gas_delay, sim_gas_depth_used, sim_dive_mins. |
847 // | 848 // |
848 // RETURNS TRUE if a stop is needed for gas switch. | 849 // RETURNS TRUE if a stop is needed for gas switch. |
911 return 0; | 912 return 0; |
912 } | 913 } |
913 | 914 |
914 ////////////////////////////////////////////////////////////////////////////// | 915 ////////////////////////////////////////////////////////////////////////////// |
915 // Calculate gas switches | 916 // Calculate gas switches |
916 // | 917 // |
917 // | 918 // |
918 // Input: N2_ratio, He_ratio. | 919 // Input: N2_ratio, He_ratio. |
919 // sim_gas_last_used | 920 // sim_gas_last_used |
920 // | 921 // |
921 // Output: calc_N2_ratio, calc_He_ratio | 922 // Output: calc_N2_ratio, calc_He_ratio |
925 assert( sim_gas_last_used <= NUM_GAS ); | 926 assert( sim_gas_last_used <= NUM_GAS ); |
926 | 927 |
927 if( sim_gas_last_used == 0 ) // Gas6 = manualy set gas. | 928 if( sim_gas_last_used == 0 ) // Gas6 = manualy set gas. |
928 { | 929 { |
929 calc_N2_ratio = N2_ratio; | 930 calc_N2_ratio = N2_ratio; |
930 calc_He_ratio = He_ratio; | 931 calc_He_ratio = He_ratio; |
931 } | 932 } |
932 else | 933 else |
933 { | 934 { |
934 calc_N2_ratio = char_I_deco_N2_ratio[sim_gas_last_used-1] * 0.01; | 935 calc_N2_ratio = char_I_deco_N2_ratio[sim_gas_last_used-1] * 0.01; |
935 calc_He_ratio = char_I_deco_He_ratio[sim_gas_last_used-1] * 0.01; | 936 calc_He_ratio = char_I_deco_He_ratio[sim_gas_last_used-1] * 0.01; |
936 } | 937 } |
937 | 938 |
938 assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 ); | 939 assert( 0.0 <= calc_N2_ratio && calc_N2_ratio <= 0.95 ); |
939 assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 ); | 940 assert( 0.0 <= calc_He_ratio && calc_He_ratio <= 0.95 ); |
940 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 ); | 941 assert( (calc_N2_ratio + calc_He_ratio) <= 1.00 ); |
959 if( deco_diluent > pres_surface ) | 960 if( deco_diluent > pres_surface ) |
960 deco_diluent += float_deco_distance; | 961 deco_diluent += float_deco_distance; |
961 | 962 |
962 //---- CCR mode : deco gas switch ? -------------------------------------- | 963 //---- CCR mode : deco gas switch ? -------------------------------------- |
963 if( char_I_const_ppO2 != 0 ) | 964 if( char_I_const_ppO2 != 0 ) |
964 { | 965 { |
965 // In CCR mode, use calc_XX_ratio instead of XX_ratio. | 966 // In CCR mode, use calc_XX_ratio instead of XX_ratio. |
966 // Note: PPO2 and ratios are known outside the lumbs, so there is no | 967 // Note: PPO2 and ratios are known outside the lumbs, so there is no |
967 // ppWater in the equations below: | 968 // ppWater in the equations below: |
968 deco_diluent -= const_ppO2; | 969 deco_diluent -= const_ppO2; |
969 deco_diluent /= calc_N2_ratio + calc_He_ratio; | 970 deco_diluent /= calc_N2_ratio + calc_He_ratio; |
970 | 971 |
971 if (deco_diluent > temp_deco) | 972 if (deco_diluent > temp_deco) |
972 deco_diluent = temp_deco; | 973 deco_diluent = temp_deco; |
973 } | 974 } |
974 | 975 |
975 if( deco_diluent > ppWater ) | 976 if( deco_diluent > ppWater ) |
976 { | 977 { |
977 ppN2 = calc_N2_ratio * (deco_diluent - ppWater); | 978 ppN2 = calc_N2_ratio * (deco_diluent - ppWater); |
978 ppHe = calc_He_ratio * (deco_diluent - ppWater); | 979 ppHe = calc_He_ratio * (deco_diluent - ppWater); |
995 // Note: fixed N2_ratio for standard air. | 996 // Note: fixed N2_ratio for standard air. |
996 // | 997 // |
997 static void clear_tissue(void) | 998 static void clear_tissue(void) |
998 { | 999 { |
999 overlay float p; | 1000 overlay float p; |
1000 flag_in_divemode = 0; | 1001 flag_in_divemode = 0; |
1001 | 1002 |
1002 // Kludge: the 0.0002 of 0.7902 are missing with standard air. | 1003 // Kludge: the 0.0002 of 0.7902 are missing with standard air. |
1003 N2_ratio = 0.7902; | 1004 N2_ratio = 0.7902; |
1004 pres_respiration = int_I_pres_respiration * 0.001; | 1005 pres_respiration = int_I_pres_respiration * 0.001; |
1005 | 1006 |
1006 p = N2_ratio * (pres_respiration - ppWater); | 1007 p = N2_ratio * (pres_respiration - ppWater); |
1007 for(ci=0; ci<NUM_COMP; ci++) | 1008 for(ci=0; ci<NUM_COMP; ci++) |
1008 { | 1009 { |
1009 // cycle through the 16 Bühlmann N2 tissues | 1010 // cycle through the 16 Bühlmann N2 tissues |
1010 pres_tissue_N2[ci] = p; | 1011 pres_tissue_N2[ci] = p; |
1044 // 6 = ascent to first stop (same as 2), except continue to 7 | 1045 // 6 = ascent to first stop (same as 2), except continue to 7 |
1045 // 7 = same as 1, except loop to 7. | 1046 // 7 = same as 1, except loop to 7. |
1046 // | 1047 // |
1047 static void calc_hauptroutine(void) | 1048 static void calc_hauptroutine(void) |
1048 { | 1049 { |
1049 static unsigned char backup_gas_used = 0; | 1050 static unsigned char backup_gas_used = 0; |
1050 static unsigned char backup_gas_depth = 0; | 1051 static unsigned char backup_gas_depth = 0; |
1051 static unsigned char backup_gas_delay = 0; | 1052 static unsigned char backup_gas_delay = 0; |
1052 | 1053 |
1053 calc_hauptroutine_data_input(); | 1054 calc_hauptroutine_data_input(); |
1054 | 1055 |
1055 calc_hauptroutine_update_tissues(); | 1056 calc_hauptroutine_update_tissues(); |
1056 calc_gradient_factor(); | 1057 calc_gradient_factor(); |
1057 | 1058 |
1058 // toggle between calculation for nullzeit (bottom time), | 1059 // toggle between calculation for nullzeit (bottom time), |
1059 // deco stops | 1060 // deco stops |
1060 // and more deco stops (continue) | 1061 // and more deco stops (continue) |
1061 switch( char_O_deco_status ) | 1062 switch( char_O_deco_status ) |
1062 { | 1063 { |
1063 case 3: //---- At surface: start a new dive ------------------------------ | 1064 case 3: //---- At surface: start a new dive ------------------------------ |
1064 clear_deco_table(); | 1065 clear_deco_table(); |
1065 copy_deco_table(); | 1066 copy_deco_table(); |
1066 int_O_ascenttime = 0; // Reset DTR. | 1067 int_O_ascenttime = 0; // Reset DTR. |
1067 int_O_extra_ascenttime = 0; | 1068 int_O_extra_ascenttime = 0; |
1068 char_O_nullzeit = 0; // Reset bottom time. | 1069 char_O_nullzeit = 0; // Reset bottom time. |
1069 char_O_deco_status = 0; // Calc bottom-time/nullzeit next iteration. | 1070 char_O_deco_status = 0; // Calc bottom-time/nullzeit next iteration. |
1070 | 1071 |
1071 // Values that should be reset just once for the full real dive. | 1072 // Values that should be reset just once for the full real dive. |
1072 // This is used to record the lowest stop for the whole dive, | 1073 // This is used to record the lowest stop for the whole dive, |
1073 // Including ACCROSS all simulated ascent. | 1074 // Including ACCROSS all simulated ascent. |
1084 case 0: //---- bottom time ----------------------------------------------- | 1085 case 0: //---- bottom time ----------------------------------------------- |
1085 default: | 1086 default: |
1086 gas_switch_find_current(); // Lookup for current gas & time. | 1087 gas_switch_find_current(); // Lookup for current gas & time. |
1087 gas_switch_set(); // setup calc_ratio's | 1088 gas_switch_set(); // setup calc_ratio's |
1088 | 1089 |
1089 calc_nullzeit(); | 1090 calc_nullzeit(); |
1090 if( char_O_nullzeit > 0 ) // Some NDL time left ? | 1091 if( char_O_nullzeit > 0 ) // Some NDL time left ? |
1091 { | 1092 { |
1092 char_O_deco_status = 0; // YES: recalc ndl next time. | 1093 char_O_deco_status = 0; // YES: recalc ndl next time. |
1093 clear_deco_table(); // Also clear stops ! | 1094 clear_deco_table(); // Also clear stops ! |
1094 copy_deco_table(); | 1095 copy_deco_table(); |
1095 char_O_deco_last_stop = 0; // And last stop (OSTC menu anim) | 1096 char_O_deco_last_stop = 0; // And last stop (OSTC menu anim) |
1096 } | 1097 } |
1097 else | 1098 else |
1098 char_O_deco_status = 2; // NO: calc ascent next time. | 1099 char_O_deco_status = 2; // NO: calc ascent next time. |
1099 break; | 1100 break; |
1100 | 1101 |
1101 case 2: //---- Simulate ascent to first stop ----------------------------- | 1102 case 2: //---- Simulate ascent to first stop ----------------------------- |
1102 case 6: // @+5min variation | 1103 case 6: // @+5min variation |
1103 // Check proposed gas at begin of ascent simulation | 1104 // Check proposed gas at begin of ascent simulation |
1104 sim_dive_mins = int_I_divemins; // Init current time. | 1105 sim_dive_mins = int_I_divemins; // Init current time. |
1105 | 1106 |
1106 gas_switch_find_current(); // Lookup for current gas & time. | 1107 gas_switch_find_current(); // Lookup for current gas & time. |
1107 gas_switch_set(); // setup calc_ratio's | 1108 gas_switch_set(); // setup calc_ratio's |
1108 | 1109 |
1109 backup_gas_used = sim_gas_last_used; // And save for later simu steps. | 1110 backup_gas_used = sim_gas_last_used; // And save for later simu steps. |
1110 backup_gas_depth = sim_gas_last_depth; // And save for later simu steps. | 1111 backup_gas_depth = sim_gas_last_depth; // And save for later simu steps. |
1111 backup_gas_delay = sim_gas_delay; | 1112 backup_gas_delay = sim_gas_delay; |
1112 | 1113 |
1113 sim_ascent_to_first_stop(); | 1114 sim_ascent_to_first_stop(); |
1114 | 1115 |
1115 // Calc stops next time (deco or gas switch). | 1116 // Calc stops next time (deco or gas switch). |
1116 char_O_deco_status = 1 | ( char_O_deco_status & 4 ); | 1117 char_O_deco_status = 1 | ( char_O_deco_status & 4 ); |
1117 break; | 1118 break; |
1118 | 1119 |
1119 case 1: //---- Simulate stops -------------------------------------------- | 1120 case 1: //---- Simulate stops -------------------------------------------- |
1120 case 5: // @+5 variation. | 1121 case 5: // @+5 variation. |
1121 calc_hauptroutine_calc_deco(); | 1122 calc_hauptroutine_calc_deco(); |
1122 | 1123 |
1123 // If simulation is finished, restore the GF low reference, so that | 1124 // If simulation is finished, restore the GF low reference, so that |
1124 // next ascent simulation is done from the current depth: | 1125 // next ascent simulation is done from the current depth: |
1125 if( (char_O_deco_status & 3) == 0 ) | 1126 if( (char_O_deco_status & 3) == 0 ) |
1126 { | 1127 { |
1127 sim_gas_last_used = backup_gas_used; | 1128 sim_gas_last_used = backup_gas_used; |
1128 sim_gas_last_depth = backup_gas_depth; | 1129 sim_gas_last_depth = backup_gas_depth; |
1129 sim_gas_delay = backup_gas_delay; | 1130 sim_gas_delay = backup_gas_delay; |
1130 } | 1131 } |
1131 break; | 1132 break; |
1132 } | 1133 } |
1133 | 1134 |
1134 } | 1135 } |
1135 | 1136 |
1136 ////////////////////////////////////////////////////////////////////////////// | 1137 ////////////////////////////////////////////////////////////////////////////// |
1137 // calc_hauptroutine_data_input | 1138 // calc_hauptroutine_data_input |
1141 // | 1142 // |
1142 void calc_hauptroutine_data_input(void) | 1143 void calc_hauptroutine_data_input(void) |
1143 { | 1144 { |
1144 overlay short int_temp; | 1145 overlay short int_temp; |
1145 overlay unsigned char g; | 1146 overlay unsigned char g; |
1146 | 1147 |
1147 pres_respiration = int_I_pres_respiration * 0.001; | 1148 pres_respiration = int_I_pres_respiration * 0.001; |
1148 pres_surface = int_I_pres_surface * 0.001; | 1149 pres_surface = int_I_pres_surface * 0.001; |
1149 N2_ratio = char_I_N2_ratio * 0.01; | 1150 N2_ratio = char_I_N2_ratio * 0.01; |
1150 He_ratio = char_I_He_ratio * 0.01; | 1151 He_ratio = char_I_He_ratio * 0.01; |
1151 float_deco_distance = char_I_deco_distance * 0.01; // Get offset is in mbar. | 1152 float_deco_distance = char_I_deco_distance * 0.01; // Get offset is in mbar. |
1152 | 1153 |
1153 // ____________________________________________________ | 1154 // ____________________________________________________ |
1154 // | 1155 // |
1155 // _____________ G A S _ C H A N G E S ________________ | 1156 // _____________ G A S _ C H A N G E S ________________ |
1156 // ____________________________________________________ | 1157 // ____________________________________________________ |
1157 | 1158 |
1158 // Keep a margin of 150mbar = 1.50m | 1159 // Keep a margin of 150mbar = 1.50m |
1159 int_temp = (int_I_pres_respiration - int_I_pres_surface) | 1160 int_temp = (int_I_pres_respiration - int_I_pres_surface) |
1160 + MBAR_REACH_GASCHANGE_AUTO_CHANGE_OFF; | 1161 + MBAR_REACH_GASCHANGE_AUTO_CHANGE_OFF; |
1161 | 1162 |
1162 // Gas are selectable if we did not pass the change depth by more than 1.50m: | 1163 // Gas are selectable if we did not pass the change depth by more than 1.50m: |
1163 for(g=0; g < NUM_GAS; ++g) | 1164 for(g=0; g < NUM_GAS; ++g) |
1164 { | 1165 { |
1165 deco_gas_change[g] = 0; | 1166 deco_gas_change[g] = 0; |
1166 if(char_I_deco_gas_change[g]) | 1167 if(char_I_deco_gas_change[g]) |
1167 if( int_temp > 100 *(short)char_I_deco_gas_change[g] ) | 1168 if( int_temp > 100 *(short)char_I_deco_gas_change[g] ) |
1168 deco_gas_change[g] = char_I_deco_gas_change[g]; | 1169 deco_gas_change[g] = char_I_deco_gas_change[g]; |
1169 } | 1170 } |
1170 | 1171 |
1171 const_ppO2 = char_I_const_ppO2 * 0.01; | 1172 const_ppO2 = char_I_const_ppO2 * 0.01; |
1172 float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01; | 1173 float_desaturation_multiplier = char_I_desaturation_multiplier * 0.01; |
1173 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; | 1174 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; |
1184 assert( 0.00 <= N2_ratio && N2_ratio <= 1.00 ); | 1185 assert( 0.00 <= N2_ratio && N2_ratio <= 1.00 ); |
1185 assert( 0.00 <= He_ratio && He_ratio <= 1.00 ); | 1186 assert( 0.00 <= He_ratio && He_ratio <= 1.00 ); |
1186 assert( (N2_ratio + He_ratio) <= 0.95 ); | 1187 assert( (N2_ratio + He_ratio) <= 0.95 ); |
1187 assert( 0.800 < pres_respiration && pres_respiration < 14.0 ); | 1188 assert( 0.800 < pres_respiration && pres_respiration < 14.0 ); |
1188 | 1189 |
1189 pres_diluent = pres_respiration; | 1190 pres_diluent = pres_respiration; |
1190 if( char_I_const_ppO2 != 0 ) // new in v.101 | 1191 if( char_I_const_ppO2 != 0 ) // new in v.101 |
1191 { | 1192 { |
1192 overlay float flush_ppO2 = pres_respiration * (1.0 - N2_ratio - He_ratio); | 1193 overlay float flush_ppO2 = pres_respiration * (1.0 - N2_ratio - He_ratio); |
1193 | 1194 |
1194 pres_diluent -= const_ppO2; // new in v.101 | 1195 pres_diluent -= const_ppO2; // new in v.101 |
1195 pres_diluent /= N2_ratio + He_ratio; // new in v.101 | 1196 pres_diluent /= N2_ratio + He_ratio; // new in v.101 |
1196 if( pres_diluent < 0.0 ) | 1197 if( pres_diluent < 0.0 ) |
1197 pres_diluent = 0.0; | 1198 pres_diluent = 0.0; |
1198 if( pres_diluent > pres_respiration ) // new in v.101 | 1199 if( pres_diluent > pres_respiration ) // new in v.101 |
1199 pres_diluent = pres_respiration; // new in v.101 | 1200 pres_diluent = pres_respiration; // new in v.101 |
1200 | 1201 |
1201 char_O_diluent = (unsigned char)(pres_diluent/pres_respiration*100.0 + 0.5); | 1202 char_O_diluent = (unsigned char)(pres_diluent/pres_respiration*100.0 + 0.5); |
1202 | 1203 |
1203 if( flush_ppO2 > 2.545) flush_ppO2 = 2.55; | 1204 if( flush_ppO2 > 2.545) flush_ppO2 = 2.55; |
1204 if( flush_ppO2 < 0.0 ) flush_ppO2 = 0.0; | 1205 if( flush_ppO2 < 0.0 ) flush_ppO2 = 0.0; |
1205 char_O_flush_ppO2 = (unsigned char)(flush_ppO2*100.0 + 0.5); | 1206 char_O_flush_ppO2 = (unsigned char)(flush_ppO2*100.0 + 0.5); |
1206 } | 1207 } |
1207 | 1208 |
1208 if( pres_diluent > ppWater ) // new in v.101 | 1209 if( pres_diluent > ppWater ) // new in v.101 |
1209 { | 1210 { |
1210 overlay float EAD, END; | 1211 overlay float EAD, END; |
1211 | 1212 |
1212 ppN2 = N2_ratio * (pres_diluent - ppWater); // changed in v.101 | 1213 ppN2 = N2_ratio * (pres_diluent - ppWater); // changed in v.101 |
1213 ppHe = He_ratio * (pres_diluent - ppWater); // changed in v.101 | 1214 ppHe = He_ratio * (pres_diluent - ppWater); // changed in v.101 |
1214 | 1215 |
1215 // EAD : Equivalent Air Dive. Equivalent depth for the same N2 level | 1216 // EAD : Equivalent Air Dive. Equivalent depth for the same N2 level |
1216 // with plain air. | 1217 // with plain air. |
1217 // ppN2 = 79% * (P_EAD - ppWater) | 1218 // ppN2 = 79% * (P_EAD - ppWater) |
1218 // EAD = (P_EAD - Psurface) * 10 | 1219 // EAD = (P_EAD - Psurface) * 10 |
1219 // ie: EAD = (ppN2 / 0.7902 + ppWater -Psurface) * 10 | 1220 // ie: EAD = (ppN2 / 0.7902 + ppWater -Psurface) * 10 |
1220 EAD = (ppN2 / 0.7902 + ppWater - pres_surface) * BAR_TO_METER; | 1221 EAD = (ppN2 / 0.7902 + ppWater - pres_surface) * BAR_TO_METER; |
1221 if( EAD < 0.0 || EAD > 245.5 ) EAD = 0.0; | 1222 if( EAD < 0.0 || EAD > 245.5 ) EAD = 0.0; |
1222 char_O_EAD = (unsigned char)(EAD + 0.5); | 1223 char_O_EAD = (unsigned char)(EAD + 0.5); |
1223 | 1224 |
1224 // END : Equivalent Narcotic Dive. | 1225 // END : Equivalent Narcotic Dive. |
1225 // Here we count O2 as narcotic too. Hence everything but helium (has a narcosis factor of | 1226 // Here we count O2 as narcotic too. Hence everything but helium (has a narcosis factor of |
1226 // 0.23 btw). Hence the formula becomes: | 1227 // 0.23 btw). Hence the formula becomes: |
1227 // END * BarPerMeter * (1.0 - 0.0) - ppWater + Psurface == Pambient - ppHe - ppWater | 1228 // END * BarPerMeter * (1.0 - 0.0) - ppWater + Psurface == Pambient - ppHe - ppWater |
1228 // ie: END = (Pambient - ppHe - Psurface) * BAR_TO_METER | 1229 // ie: END = (Pambient - ppHe - Psurface) * BAR_TO_METER |
1229 // | 1230 // |
1230 // Source cited: | 1231 // Source cited: |
1231 // The Physiology and Medicine of Diving by Peter Bennett and David Elliott, | 1232 // The Physiology and Medicine of Diving by Peter Bennett and David Elliott, |
1232 // 4th edition, 1993, W.B.Saunders Company Ltd, London. | 1233 // 4th edition, 1993, W.B.Saunders Company Ltd, London. |
1233 END = (pres_respiration - ppHe - pres_surface) * BAR_TO_METER; | 1234 END = (pres_respiration - ppHe - pres_surface) * BAR_TO_METER; |
1234 if( END < 0.0 || END > 245.5 ) END = 0.0; | 1235 if( END < 0.0 || END > 245.5 ) END = 0.0; |
1235 char_O_END = (unsigned char)(END + 0.5); | 1236 char_O_END = (unsigned char)(END + 0.5); |
1236 } | 1237 } |
1237 else // new in v.101 | 1238 else // new in v.101 |
1238 { | 1239 { |
1239 ppN2 = 0.0; // new in v.101 | 1240 ppN2 = 0.0; // new in v.101 |
1240 ppHe = 0.0; // new in v.101 | 1241 ppHe = 0.0; // new in v.101 |
1241 char_O_EAD = char_O_END = 0; | 1242 char_O_EAD = char_O_END = 0; |
1242 } | 1243 } |
1243 | 1244 |
1244 if(!char_I_step_is_1min) | 1245 if(!char_I_step_is_1min) |
1245 calc_tissue(0); | 1246 calc_tissue(0); |
1246 else | 1247 else |
1247 calc_tissue(1); | 1248 calc_tissue(1); |
1248 | 1249 |
1249 // Calc limit for surface, ie. GF_high. | 1250 // Calc limit for surface, ie. GF_high. |
1250 calc_limit(); | 1251 calc_limit(); |
1251 | 1252 |
1252 int_O_gtissue_limit = (short)(calc_lead_tissue_limit * 1000); | 1253 int_O_gtissue_limit = (short)(calc_lead_tissue_limit * 1000); |
1253 int_O_gtissue_press = (short)((pres_tissue_N2[char_O_gtissue_no] + pres_tissue_He[char_O_gtissue_no]) * 1000); | 1254 int_O_gtissue_press = (short)((pres_tissue_N2[char_O_gtissue_no] + pres_tissue_He[char_O_gtissue_no]) * 1000); |
1254 } | 1255 } |
1255 | 1256 |
1256 | 1257 |
1257 ////////////////////////////////////////////////////////////////////////////// | 1258 ////////////////////////////////////////////////////////////////////////////// |
1258 // Compute stops. | 1259 // Compute stops. |
1259 // | 1260 // |
1260 // Note: because this can be very long, break on 16 iterations, and set state | 1261 // Note: because this can be very long, break on 16 iterations, and set state |
1261 // to 0 when finished, or to 1 when needing to continue. | 1262 // to 0 when finished, or to 1 when needing to continue. |
1262 // Note: because each iteration might be very long too (~ 66 ms in 1.84beta), | 1263 // Note: because each iteration might be very long too (~ 66 ms in 1.84beta), |
1263 // break the loop when total time > 512msec. | 1264 // break the loop when total time > 512msec. |
1264 // | 1265 // |
1265 void calc_hauptroutine_calc_deco(void) | 1266 void calc_hauptroutine_calc_deco(void) |
1266 { | 1267 { |
1267 overlay unsigned char loop; | 1268 overlay unsigned char loop; |
1268 | 1269 |
1269 for(loop = 0; loop < 16; ++loop) | 1270 for(loop = 0; loop < 16; ++loop) |
1270 { | 1271 { |
1271 // Limit loops to 512ms, using the RTC timer 3: | 1272 // Limit loops to 512ms, using the RTC timer 3: |
1272 if( tmr3() & (512*32) ) | 1273 if( tmr3() & (512*32) ) |
1273 break; | 1274 break; |
1274 | 1275 |
1275 // Do not ascent while doing a gas switch ? | 1276 // Do not ascent while doing a gas switch ? |
1276 if( sim_gas_delay <= sim_dive_mins ) | 1277 if( sim_gas_delay <= sim_dive_mins ) |
1277 { | 1278 { |
1278 if( calc_nextdecodepth() ) | 1279 if( calc_nextdecodepth() ) |
1279 { | 1280 { |
1280 if( temp_depth_limit == 0 ) | 1281 if( temp_depth_limit == 0 ) |
1281 goto Surface; | 1282 goto Surface; |
1282 | 1283 |
1283 //---- We hit a stop at temp_depth_limit --------------------- | 1284 //---- We hit a stop at temp_depth_limit --------------------- |
1284 temp_deco = temp_depth_limit * METER_TO_BAR // Convert to relative bar, | 1285 temp_deco = temp_depth_limit * METER_TO_BAR // Convert to relative bar, |
1285 + pres_surface; // To absolute. | 1286 + pres_surface; // To absolute. |
1286 if( !update_deco_table() ) // Adds a one minute stops. | 1287 if( !update_deco_table() ) // Adds a one minute stops. |
1287 goto Surface; // Deco table full: abort... | 1288 goto Surface; // Deco table full: abort... |
1288 } | 1289 } |
1289 else | 1290 else |
1290 { | 1291 { |
1294 //---- Finish computations once surface is reached ----------- | 1295 //---- Finish computations once surface is reached ----------- |
1295 if( temp_deco <= pres_surface ) | 1296 if( temp_deco <= pres_surface ) |
1296 { | 1297 { |
1297 Surface: | 1298 Surface: |
1298 if( char_O_deco_status == 1 ) // Don't in @+5min variant. | 1299 if( char_O_deco_status == 1 ) // Don't in @+5min variant. |
1299 copy_deco_table(); | 1300 copy_deco_table(); |
1300 | 1301 |
1301 calc_ascenttime(); | 1302 calc_ascenttime(); |
1302 char_O_deco_status = 0; // calc nullzeit next time. | 1303 char_O_deco_status = 0; // calc nullzeit next time. |
1303 char_O_deco_last_stop = 0; // Surface reached (to animate menu) | 1304 char_O_deco_last_stop = 0; // Surface reached (to animate menu) |
1304 return; | 1305 return; |
1305 } | 1306 } |
1306 } | 1307 } |
1307 } | 1308 } |
1308 else | 1309 else |
1309 { | 1310 { |
1314 } | 1315 } |
1315 | 1316 |
1316 //---- Then update tissue -------------------------------------------- | 1317 //---- Then update tissue -------------------------------------------- |
1317 sim_dive_mins++; // Advance simulated time by 1 minute. | 1318 sim_dive_mins++; // Advance simulated time by 1 minute. |
1318 gas_switch_set(); // Apply any simulated gas change, once validated. | 1319 gas_switch_set(); // Apply any simulated gas change, once validated. |
1319 sim_alveolar_presures(); // Updates ppN2 and ppHe. | 1320 sim_alveolar_presures(); // Updates ppN2 and ppHe. |
1320 sim_tissue(1); // Simulate compartiments for 1 minute. | 1321 sim_tissue(1); // Simulate compartiments for 1 minute. |
1321 } | 1322 } |
1322 | 1323 |
1323 // Surface not reached, need more stops... for menu animation. | 1324 // Surface not reached, need more stops... for menu animation. |
1324 char_O_deco_last_stop = temp_depth_limit; // Reached depth. | 1325 char_O_deco_last_stop = temp_depth_limit; // Reached depth. |
1325 } | 1326 } |
1326 | 1327 |
1327 ////////////////////////////////////////////////////////////////////////////// | 1328 ////////////////////////////////////////////////////////////////////////////// |
1328 // Simulation ascention to first deco stop. | 1329 // Simulation ascention to first deco stop. |
1341 overlay unsigned char fast = 1; // 1min or 2sec steps. | 1342 overlay unsigned char fast = 1; // 1min or 2sec steps. |
1342 | 1343 |
1343 update_startvalues(); | 1344 update_startvalues(); |
1344 clear_deco_table(); | 1345 clear_deco_table(); |
1345 | 1346 |
1346 temp_deco = pres_respiration; // Starts from current real depth. | 1347 temp_deco = pres_respiration; // Starts from current real depth. |
1347 | 1348 |
1348 // Are we doing the special @+5min variation ? | 1349 // Are we doing the special @+5min variation ? |
1349 if(char_O_deco_status & 4) | 1350 if(char_O_deco_status & 4) |
1350 sim_extra_time(); | 1351 sim_extra_time(); |
1351 | 1352 |
1352 // Do we have a gas switch going on ? | 1353 // Do we have a gas switch going on ? |
1353 if( sim_gas_delay > sim_dive_mins ) | 1354 if( sim_gas_delay > sim_dive_mins ) |
1354 return; | 1355 return; |
1355 | 1356 |
1356 //---- Loop until first stop, gas switch, or surface is reached ---------- | 1357 //---- Loop until first stop, gas switch, or surface is reached ---------- |
1357 for(;;) | 1358 for(;;) |
1358 { | 1359 { |
1359 overlay float old_deco = temp_deco; // Pamb backup (bars) | 1360 overlay float old_deco = temp_deco; // Pamb backup (bars) |
1360 | 1361 |
1361 // Try ascending 1 full minute (fast) or 2sec (!fast): | 1362 // Try ascending 1 full minute (fast) or 2sec (!fast): |
1362 if( fast ) | 1363 if( fast ) |
1363 temp_deco -= 10*METER_TO_BAR; // 1 min, at 10m/min. ~ 1bar. | 1364 temp_deco -= 10*METER_TO_BAR; // 1 min, at 10m/min. ~ 1bar. |
1405 | 1406 |
1406 if( fast ) | 1407 if( fast ) |
1407 sim_dive_mins++; // Advance simulated time by 1 minute. | 1408 sim_dive_mins++; // Advance simulated time by 1 minute. |
1408 sim_alveolar_presures(); // temp_deco --> ppN2/ppHe | 1409 sim_alveolar_presures(); // temp_deco --> ppN2/ppHe |
1409 sim_tissue(fast); // and update tissues for 1 min. | 1410 sim_tissue(fast); // and update tissues for 1 min. |
1410 } | 1411 } |
1411 } | 1412 } |
1412 | 1413 |
1413 ////////////////////////////////////////////////////////////////////////////// | 1414 ////////////////////////////////////////////////////////////////////////////// |
1414 // Simulation extra time at the current depth. | 1415 // Simulation extra time at the current depth. |
1415 // | 1416 // |
1417 void sim_extra_time(void) | 1418 void sim_extra_time(void) |
1418 { | 1419 { |
1419 overlay unsigned char extra = read_custom_function(58); | 1420 overlay unsigned char extra = read_custom_function(58); |
1420 do { | 1421 do { |
1421 sim_dive_mins++; // Advance simulated time by 1 minute. | 1422 sim_dive_mins++; // Advance simulated time by 1 minute. |
1422 sim_tissue(1); // and update tissues for 1 min. | 1423 sim_tissue(1); // and update tissues for 1 min. |
1423 } while( --extra != 0 ); | 1424 } while( --extra != 0 ); |
1424 } | 1425 } |
1425 | 1426 |
1426 ////////////////////////////////////////////////////////////////////////////// | 1427 ////////////////////////////////////////////////////////////////////////////// |
1427 // calc_tissue | 1428 // calc_tissue |
1524 overlay unsigned char ndl; | 1525 overlay unsigned char ndl; |
1525 overlay unsigned char period = 10; | 1526 overlay unsigned char period = 10; |
1526 | 1527 |
1527 read_buhlmann_coefficients(); | 1528 read_buhlmann_coefficients(); |
1528 read_buhlmann_times(2); // Starts with a 10min period. | 1529 read_buhlmann_times(2); // Starts with a 10min period. |
1529 | 1530 |
1530 //---- Simulate for that tissue -------------------------------------- | 1531 //---- Simulate for that tissue -------------------------------------- |
1531 // NOTE: No need to simulate for longuer than the already found NDL. | 1532 // NOTE: No need to simulate for longuer than the already found NDL. |
1532 for(ndl=0; ndl<char_O_nullzeit;) | 1533 for(ndl=0; ndl<char_O_nullzeit;) |
1533 { | 1534 { |
1534 //---- Compute updated mix M-value at surface | 1535 //---- Compute updated mix M-value at surface |
1597 { | 1598 { |
1598 overlay unsigned char x; | 1599 overlay unsigned char x; |
1599 overlay unsigned short sum; | 1600 overlay unsigned short sum; |
1600 | 1601 |
1601 // + 0.7 to count 1 minute ascent time from 3 metre to surface | 1602 // + 0.7 to count 1 minute ascent time from 3 metre to surface |
1602 overlay float ascent = pres_respiration - pres_surface + 0.7; | 1603 overlay float ascent = pres_respiration - pres_surface + 0.7; |
1603 if (ascent < 0.0) | 1604 if (ascent < 0.0) |
1604 ascent = 0.0; | 1605 ascent = 0.0; |
1605 sum = (unsigned short)(ascent + 0.99); | 1606 sum = (unsigned short)(ascent + 0.99); |
1606 | 1607 |
1607 for(x=0; x<NUM_STOPS && internal_deco_depth[x]; x++) | 1608 for(x=0; x<NUM_STOPS && internal_deco_depth[x]; x++) |
1621 void update_startvalues(void) | 1622 void update_startvalues(void) |
1622 { | 1623 { |
1623 overlay unsigned char x; | 1624 overlay unsigned char x; |
1624 | 1625 |
1625 // Start ascent simulation with current tissue partial pressures. | 1626 // Start ascent simulation with current tissue partial pressures. |
1626 for(x=0; x<NUM_COMP; x++) | 1627 for(x=0; x<NUM_COMP; x++) |
1627 { | 1628 { |
1628 sim_pres_tissue_N2[x] = pres_tissue_N2[x]; | 1629 sim_pres_tissue_N2[x] = pres_tissue_N2[x]; |
1629 sim_pres_tissue_He[x] = pres_tissue_He[x]; | 1630 sim_pres_tissue_He[x] = pres_tissue_He[x]; |
1630 } | 1631 } |
1631 | 1632 |
1632 // No leading tissue (yet) for this ascent simulation. | 1633 // No leading tissue (yet) for this ascent simulation. |
1633 sim_lead_tissue_limit = 0.0; | 1634 sim_lead_tissue_limit = 0.0; |
1634 sim_lead_tissue_no = 255; | 1635 sim_lead_tissue_no = 255; |
1635 } | 1636 } |
1653 | 1654 |
1654 // N2 | 1655 // N2 |
1655 temp_tissue = (ppN2 - sim_pres_tissue_N2[ci]) * var_N2_e; | 1656 temp_tissue = (ppN2 - sim_pres_tissue_N2[ci]) * var_N2_e; |
1656 temp_tissue_safety(); | 1657 temp_tissue_safety(); |
1657 sim_pres_tissue_N2[ci] += temp_tissue; | 1658 sim_pres_tissue_N2[ci] += temp_tissue; |
1658 | 1659 |
1659 // He | 1660 // He |
1660 temp_tissue = (ppHe - sim_pres_tissue_He[ci]) * var_He_e; | 1661 temp_tissue = (ppHe - sim_pres_tissue_He[ci]) * var_He_e; |
1661 temp_tissue_safety(); | 1662 temp_tissue_safety(); |
1662 sim_pres_tissue_He[ci] += temp_tissue; | 1663 sim_pres_tissue_He[ci] += temp_tissue; |
1663 } | 1664 } |
1692 // Note: the correction factor depends both on GF and b, | 1693 // Note: the correction factor depends both on GF and b, |
1693 // Actual values are in the 1.5 .. 1.0 range (for a GF=30%), | 1694 // Actual values are in the 1.5 .. 1.0 range (for a GF=30%), |
1694 // so that can change who is the leading gas... | 1695 // so that can change who is the leading gas... |
1695 // Note: Also depends of the GF_current... | 1696 // Note: Also depends of the GF_current... |
1696 if( char_I_deco_model != 0 ) | 1697 if( char_I_deco_model != 0 ) |
1697 p = ( p - var_N2_a * GF_current) | 1698 p = ( p - var_N2_a * GF_current) |
1698 / (GF_current / var_N2_b + 1.0 - GF_current); | 1699 / (GF_current / var_N2_b + 1.0 - GF_current); |
1699 else | 1700 else |
1700 p = (p - var_N2_a) * var_N2_b; | 1701 p = (p - var_N2_a) * var_N2_b; |
1701 | 1702 |
1702 if( p > sim_lead_tissue_limit ) | 1703 if( p > sim_lead_tissue_limit ) |
1749 assert( !internal_deco_depth[x] || temp_depth_limit <= (internal_deco_depth[x]& 0x7F) ); | 1750 assert( !internal_deco_depth[x] || temp_depth_limit <= (internal_deco_depth[x]& 0x7F) ); |
1750 | 1751 |
1751 if( (internal_deco_depth[x] & 0x7F) == temp_depth_limit ) | 1752 if( (internal_deco_depth[x] & 0x7F) == temp_depth_limit ) |
1752 { | 1753 { |
1753 // Do not overflow (max 255') | 1754 // Do not overflow (max 255') |
1754 if( internal_deco_time[x] < 255 ) | 1755 if( internal_deco_time[x] < 255 ) |
1755 { | 1756 { |
1756 internal_deco_time[x]++; | 1757 internal_deco_time[x]++; |
1757 return 1; | 1758 return 1; |
1758 } | 1759 } |
1759 // But store extra in the next stop... | 1760 // But store extra in the next stop... |
1789 overlay float He = pres_tissue_He[char_O_gtissue_no]; | 1790 overlay float He = pres_tissue_He[char_O_gtissue_no]; |
1790 | 1791 |
1791 assert( char_O_gtissue_no < NUM_COMP ); | 1792 assert( char_O_gtissue_no < NUM_COMP ); |
1792 assert( 0.800 <= pres_respiration && pres_respiration < 14.0 ); | 1793 assert( 0.800 <= pres_respiration && pres_respiration < 14.0 ); |
1793 | 1794 |
1794 // tissue > respiration (currently off-gasing) | 1795 // tissue > respiration (currently off-gasing) |
1795 // GF = 0% when respiration == tissue, ie. bubbles are at equilibrium. | 1796 // GF = 0% when respiration == tissue, ie. bubbles are at equilibrium. |
1796 // GF = 100% when respiration == limit. | 1797 // GF = 100% when respiration == limit. |
1797 temp_tissue = N2 + He; | 1798 temp_tissue = N2 + He; |
1798 if( temp_tissue <= pres_respiration ) | 1799 if( temp_tissue <= pres_respiration ) |
1799 gf = 0.0; | 1800 gf = 0.0; |
1800 else | 1801 else |
1801 { | 1802 { |
1802 overlay float limit = calc_lead_tissue_limit; | 1803 overlay float limit = calc_lead_tissue_limit; |
1803 // NOTE: in GF model, calc_lead_tissue_limit include already the | 1804 // NOTE: in GF model, calc_lead_tissue_limit include already the |
1804 // correction due to gradient factor. To compute the actual | 1805 // correction due to gradient factor. To compute the actual |
1811 var_N2_a = (var_N2_a * N2 + var_He_a * He) / temp_tissue; | 1812 var_N2_a = (var_N2_a * N2 + var_He_a * He) / temp_tissue; |
1812 var_N2_b = (var_N2_b * N2 + var_He_b * He) / temp_tissue; | 1813 var_N2_b = (var_N2_b * N2 + var_He_b * He) / temp_tissue; |
1813 limit = (temp_tissue - var_N2_a) * var_N2_b; | 1814 limit = (temp_tissue - var_N2_a) * var_N2_b; |
1814 } | 1815 } |
1815 | 1816 |
1816 gf = (temp_tissue - pres_respiration) | 1817 gf = (temp_tissue - pres_respiration) |
1817 / (temp_tissue - limit) | 1818 / (temp_tissue - limit) |
1818 * 100.0; | 1819 * 100.0; |
1819 if( gf > 254.5 ) gf = 255.0; | 1820 if( gf > 254.5 ) gf = 255.0; |
1820 if( gf < 0.0 ) gf = 0.0; | 1821 if( gf < 0.0 ) gf = 0.0; |
1821 } | 1822 } |
1822 char_O_gradient_factor = (unsigned char)(gf+0.5f); | 1823 char_O_gradient_factor = (unsigned char)(gf+0.5f); |
1823 | 1824 |
1824 if( char_I_deco_model != 0 ) // calculate relative gradient factor | 1825 if( char_I_deco_model != 0 ) // calculate relative gradient factor |
1825 { | 1826 { |
1826 overlay float rgf; | 1827 overlay float rgf; |
1827 | 1828 |
1828 if( low_depth < 3 ) | 1829 if( low_depth < 3 ) |
1829 rgf = GF_high; | 1830 rgf = GF_high; |
1830 else | 1831 else |
1831 { | 1832 { |
1832 overlay float temp1 = low_depth * METER_TO_BAR; | 1833 overlay float temp1 = low_depth * METER_TO_BAR; |
1833 overlay float temp2 = pres_respiration - pres_surface; | 1834 overlay float temp2 = pres_respiration - pres_surface; |
1834 | 1835 |
1835 if (temp2 <= 0) | 1836 if (temp2 <= 0) |
1836 rgf = GF_high; | 1837 rgf = GF_high; |
1837 else if (temp2 >= temp1) | 1838 else if (temp2 >= temp1) |
1838 rgf = GF_low; | 1839 rgf = GF_low; |
1839 else | 1840 else |
1840 rgf = GF_low + (temp1 - temp2)/temp1*GF_delta; | 1841 rgf = GF_low + (temp1 - temp2)/temp1*GF_delta; |
1841 } | 1842 } |
1842 | 1843 |
1843 rgf = gf / rgf; // gf is already in percent | 1844 rgf = gf / rgf; // gf is already in percent |
1844 if( rgf < 0.0 ) rgf = 0.0; | 1845 if( rgf < 0.0 ) rgf = 0.0; |
1845 if( rgf > 254.5 ) rgf = 255.0; | 1846 if( rgf > 254.5 ) rgf = 255.0; |
1846 char_O_relative_gradient_GF = (unsigned char)(rgf+0.5f); | 1847 char_O_relative_gradient_GF = (unsigned char)(rgf+0.5f); |
1847 } // calc relative gradient factor | 1848 } // calc relative gradient factor |
1848 else | 1849 else |
1849 { | 1850 { |
1850 char_O_relative_gradient_GF = char_O_gradient_factor; | 1851 char_O_relative_gradient_GF = char_O_gradient_factor; |
1851 } | 1852 } |
1852 } | 1853 } |
1853 | 1854 |
1854 ////////////////////////////////////////////////////////////////////////////// | 1855 ////////////////////////////////////////////////////////////////////////////// |
1855 // deco_calc_desaturation_time | 1856 // deco_calc_desaturation_time |
1856 // | 1857 // |
1891 temp2 = ppN2 - pres_tissue_N2[ci]; | 1892 temp2 = ppN2 - pres_tissue_N2[ci]; |
1892 if (temp2 >= 0.0) | 1893 if (temp2 >= 0.0) |
1893 temp1 = 0.0; | 1894 temp1 = 0.0; |
1894 else | 1895 else |
1895 temp1 = temp1 / temp2; | 1896 temp1 = temp1 / temp2; |
1896 | 1897 |
1897 if( 0.0 < temp1 && temp1 < 1.0 ) | 1898 if( 0.0 < temp1 && temp1 < 1.0 ) |
1898 { | 1899 { |
1899 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. | 1900 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. |
1900 // minus because log is negative. | 1901 // minus because log is negative. |
1901 temp1 = log(1.0 - temp1) / -0.6931; // temp1 is the multiples of half times necessary. | 1902 temp1 = log(1.0 - temp1) / -0.6931; // temp1 is the multiples of half times necessary. |
1914 temp3 = 0.0; | 1915 temp3 = 0.0; |
1915 else | 1916 else |
1916 temp3 = - temp3 / pres_tissue_He[ci]; | 1917 temp3 = - temp3 / pres_tissue_He[ci]; |
1917 | 1918 |
1918 if( 0.0 < temp3 && temp3 < 1.0 ) | 1919 if( 0.0 < temp3 && temp3 < 1.0 ) |
1919 { | 1920 { |
1920 temp3 = log(1.0 - temp3) / -0.6931; // temp1 is the multiples of half times necessary. | 1921 temp3 = log(1.0 - temp3) / -0.6931; // temp1 is the multiples of half times necessary. |
1921 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. | 1922 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. |
1922 // minus because log is negative | 1923 // minus because log is negative |
1923 temp4 = var_He_ht * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier | 1924 temp4 = var_He_ht * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier |
1924 } | 1925 } |
1925 else | 1926 else |
1926 { | 1927 { |
1927 temp3 = 0.0; | 1928 temp3 = 0.0; |
1928 temp4 = 0.0; | 1929 temp4 = 0.0; |
1929 } | 1930 } |
1930 | 1931 |
1931 // saturation_time (for flight) | 1932 // saturation_time (for flight) |
1932 if (temp4 > temp2) | 1933 if (temp4 > temp2) |
1933 desat_time = (unsigned short)temp4; | 1934 desat_time = (unsigned short)temp4; |
1934 else | 1935 else |
1935 desat_time = (unsigned short)temp2; | 1936 desat_time = (unsigned short)temp2; |
1936 | 1937 |
1937 if(desat_time > int_O_desaturation_time) | 1938 if(desat_time > int_O_desaturation_time) |
1938 int_O_desaturation_time = desat_time; | 1939 int_O_desaturation_time = desat_time; |
1939 | 1940 |
1940 // N2 saturation in multiples of halftime for display purposes | 1941 // N2 saturation in multiples of halftime for display purposes |
1941 temp2 = temp1 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8 | 1942 temp2 = temp1 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8 |
1975 pres_respiration = pres_surface = int_I_pres_surface * 0.001; | 1976 pres_respiration = pres_surface = int_I_pres_surface * 0.001; |
1976 ppN2 = N2_ratio * (pres_respiration - ppWater); | 1977 ppN2 = N2_ratio * (pres_respiration - ppWater); |
1977 ppHe = 0.0; | 1978 ppHe = 0.0; |
1978 float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); | 1979 float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); |
1979 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; | 1980 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; |
1980 | 1981 |
1981 calc_tissue(1); // update the pressure in the tissues N2/He in accordance with the new ambient pressure | 1982 calc_tissue(1); // update the pressure in the tissues N2/He in accordance with the new ambient pressure |
1982 | 1983 |
1983 clear_deco_table(); | 1984 clear_deco_table(); |
1984 char_O_deco_status = 3; // surface new in v.102 : stays in surface state. | 1985 char_O_deco_status = 3; // surface new in v.102 : stays in surface state. |
1985 char_O_nullzeit = 0; | 1986 char_O_nullzeit = 0; |
1986 int_O_ascenttime = 0; | 1987 int_O_ascenttime = 0; |
1987 int_O_extra_ascenttime = 0; | 1988 int_O_extra_ascenttime = 0; |
2024 calc_tissue(2); // period = 10min. | 2025 calc_tissue(2); // period = 10min. |
2025 CNS_fraction = 0.92587471 * CNS_fraction; // Half-time = 90min: (1/2)^(1/9) | 2026 CNS_fraction = 0.92587471 * CNS_fraction; // Half-time = 90min: (1/2)^(1/9) |
2026 } | 2027 } |
2027 assert( 0.0 <= CNS_fraction && CNS_fraction <= 2.56 ); | 2028 assert( 0.0 <= CNS_fraction && CNS_fraction <= 2.56 ); |
2028 char_O_CNS_fraction = (unsigned char)(CNS_fraction * 100.0 + 0.5); | 2029 char_O_CNS_fraction = (unsigned char)(CNS_fraction * 100.0 + 0.5); |
2029 | 2030 |
2030 //---- Restore model ----------------------------------------------------- | 2031 //---- Restore model ----------------------------------------------------- |
2031 char_I_deco_model = backup_model; | 2032 char_I_deco_model = backup_model; |
2032 } | 2033 } |
2033 | 2034 |
2034 ////////////////////////////////////////////////////////////////////////////// | 2035 ////////////////////////////////////////////////////////////////////////////// |
2045 overlay unsigned char md_buffer[16]; | 2046 overlay unsigned char md_buffer[16]; |
2046 overlay unsigned char md_temp; | 2047 overlay unsigned char md_temp; |
2047 overlay unsigned short md_pointer; | 2048 overlay unsigned short md_pointer; |
2048 | 2049 |
2049 RESET_C_STACK | 2050 RESET_C_STACK |
2050 | 2051 |
2051 // init | 2052 // init |
2052 for(md_i=0;md_i<16;md_i++) | 2053 for(md_i=0;md_i<16;md_i++) |
2053 { | 2054 { |
2054 md_state[md_i] = 0; | 2055 md_state[md_i] = 0; |
2055 char_O_hash[md_i] = 0; | 2056 char_O_hash[md_i] = 0; |
2099 | 2100 |
2100 md_buffer[md_i] = md_temp; | 2101 md_buffer[md_i] = md_temp; |
2101 md_state[md_i+16] = md_temp; | 2102 md_state[md_i+16] = md_temp; |
2102 md_state[md_i+32] = (unsigned char)(md_temp ^ md_state[md_i]); | 2103 md_state[md_i+32] = (unsigned char)(md_temp ^ md_state[md_i]); |
2103 } // for md_i 16 | 2104 } // for md_i 16 |
2104 | 2105 |
2105 for (md_i=0;md_i<18;md_i++) | 2106 for (md_i=0;md_i<18;md_i++) |
2106 { | 2107 { |
2107 for (md_j=0;md_j<48;md_j++) | 2108 for (md_j=0;md_j<48;md_j++) |
2108 { | 2109 { |
2109 md_state[md_j] ^= md_pi_subst[md_t]; | 2110 md_state[md_j] ^= md_pi_subst[md_t]; |
2110 md_t = md_state[md_j]; | 2111 md_t = md_state[md_j]; |
2111 } // for md_j 48 | 2112 } // for md_j 48 |
2112 md_t = (unsigned char)(md_t+1); | 2113 md_t = (unsigned char)(md_t+1); |
2113 } // for md_i 18 | 2114 } // for md_i 18 |
2114 md_t = char_O_hash[15]; | 2115 md_t = char_O_hash[15]; |
2115 | 2116 |
2116 for (md_i=0;md_i<16;md_i++) | 2117 for (md_i=0;md_i<16;md_i++) |
2117 { | 2118 { |
2118 char_O_hash[md_i] ^= md_pi_subst[(md_buffer[md_i] ^ md_t)]; | 2119 char_O_hash[md_i] ^= md_pi_subst[(md_buffer[md_i] ^ md_t)]; |
2119 md_t = char_O_hash[md_i]; | 2120 md_t = char_O_hash[md_i]; |
2120 } // for md_i 16 | 2121 } // for md_i 16 |
2143 // CNS_fraction : velue before period. | 2144 // CNS_fraction : velue before period. |
2144 // Output: CNS_fraction, char_O_CNS_fraction | 2145 // Output: CNS_fraction, char_O_CNS_fraction |
2145 // | 2146 // |
2146 void deco_calc_CNS_fraction(void) | 2147 void deco_calc_CNS_fraction(void) |
2147 { | 2148 { |
2148 overlay float time_factor = 1.0f; | 2149 overlay float time_factor = 1.0f; |
2149 RESET_C_STACK | 2150 RESET_C_STACK |
2150 | 2151 |
2151 assert( 0.0 <= CNS_fraction && CNS_fraction <= 2.56 ); | 2152 assert( 0.0 <= CNS_fraction && CNS_fraction <= 2.56 ); |
2152 assert( char_I_actual_ppO2 > 15 ); | 2153 assert( char_I_actual_ppO2 > 15 ); |
2153 | 2154 |
2159 // Don't increase CNS below 0.5 bar, but keep it steady. | 2160 // Don't increase CNS below 0.5 bar, but keep it steady. |
2160 if (char_I_actual_ppO2 < 50) | 2161 if (char_I_actual_ppO2 < 50) |
2161 ; // no changes | 2162 ; // no changes |
2162 //------------------------------------------------------------------------ | 2163 //------------------------------------------------------------------------ |
2163 // Below (and including) 1.60 bar | 2164 // Below (and including) 1.60 bar |
2164 else if (char_I_actual_ppO2 < 60) | 2165 else if (char_I_actual_ppO2 < 61) |
2165 CNS_fraction += time_factor/(-533.07 * char_I_actual_ppO2 + 54000.0); | 2166 CNS_fraction += time_factor/(-533.07 * char_I_actual_ppO2 + 54000.0); |
2166 else if (char_I_actual_ppO2 < 70) | 2167 else if (char_I_actual_ppO2 < 71) |
2167 CNS_fraction += time_factor/(-444.22 * char_I_actual_ppO2 + 48600.0); | 2168 CNS_fraction += time_factor/(-444.22 * char_I_actual_ppO2 + 48600.0); |
2168 else if (char_I_actual_ppO2 < 80) | 2169 else if (char_I_actual_ppO2 < 81) |
2169 CNS_fraction += time_factor/(-355.38 * char_I_actual_ppO2 + 42300.0); | 2170 CNS_fraction += time_factor/(-355.38 * char_I_actual_ppO2 + 42300.0); |
2170 else if (char_I_actual_ppO2 < 90) | 2171 else if (char_I_actual_ppO2 < 91) |
2171 CNS_fraction += time_factor/(-266.53 * char_I_actual_ppO2 + 35100.0); | 2172 CNS_fraction += time_factor/(-266.53 * char_I_actual_ppO2 + 35100.0); |
2172 else if (char_I_actual_ppO2 < 110) | 2173 else if (char_I_actual_ppO2 < 111) |
2173 CNS_fraction += time_factor/(-177.69 * char_I_actual_ppO2 + 27000.0); | 2174 CNS_fraction += time_factor/(-177.69 * char_I_actual_ppO2 + 27000.0); |
2174 else if (char_I_actual_ppO2 < 150) | 2175 else if (char_I_actual_ppO2 < 152) |
2175 CNS_fraction += time_factor/( -88.84 * char_I_actual_ppO2 + 17100.0); | 2176 CNS_fraction += time_factor/( -88.84 * char_I_actual_ppO2 + 17100.0); |
2176 else if (char_I_actual_ppO2 < 165) | 2177 else if (char_I_actual_ppO2 < 167) |
2177 CNS_fraction += time_factor/(-222.11 * char_I_actual_ppO2 + 37350.0); | 2178 CNS_fraction += time_factor/(-222.11 * char_I_actual_ppO2 + 37350.0); |
2178 //------------------------------------------------------------------------ | 2179 //------------------------------------------------------------------------ |
2179 // Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity: | 2180 // Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity: |
2180 // J Appl Physiol 92: 248–256, 2002, doi:10.1152/japplphysiol.00434.2001 | 2181 // J Appl Physiol 92: 248–256, 2002, doi:10.1152/japplphysiol.00434.2001 |
2181 // Formula (A1) based on value for 1.55 and c=20 | 2182 // Formula (A1) based on value for 1.55 and c=20 |
2182 // example calculation: Sqrt((1.7/1.55)^20)*0.000404 | 2183 // example calculation: Sqrt((1.7/1.55)^20)*0.000404 |
2183 else if (char_I_actual_ppO2 < 170) | 2184 else if (char_I_actual_ppO2 < 172) |
2184 CNS_fraction += time_factor*0.00102; | 2185 CNS_fraction += time_factor*0.00102; |
2185 else if (char_I_actual_ppO2 < 175) | 2186 else if (char_I_actual_ppO2 < 177) |
2186 CNS_fraction += time_factor*0.00136; | 2187 CNS_fraction += time_factor*0.00136; |
2187 else if (char_I_actual_ppO2 < 180) | 2188 else if (char_I_actual_ppO2 < 182) |
2188 CNS_fraction += time_factor*0.00180; | 2189 CNS_fraction += time_factor*0.00180; |
2189 else if (char_I_actual_ppO2 < 185) | 2190 else if (char_I_actual_ppO2 < 187) |
2190 CNS_fraction += time_factor*0.00237; | 2191 CNS_fraction += time_factor*0.00237; |
2191 else if (char_I_actual_ppO2 < 190) | 2192 else if (char_I_actual_ppO2 < 192) |
2192 CNS_fraction += time_factor*0.00310; | 2193 CNS_fraction += time_factor*0.00310; |
2193 else if (char_I_actual_ppO2 < 195) | 2194 else if (char_I_actual_ppO2 < 198) |
2194 CNS_fraction += time_factor*0.00401; | 2195 CNS_fraction += time_factor*0.00401; |
2195 else if (char_I_actual_ppO2 < 200) | 2196 else if (char_I_actual_ppO2 < 203) |
2196 CNS_fraction += time_factor*0.00517; | 2197 CNS_fraction += time_factor*0.00517; |
2197 else if (char_I_actual_ppO2 < 230) | 2198 else if (char_I_actual_ppO2 < 233) |
2198 CNS_fraction += time_factor*0.0209; | 2199 CNS_fraction += time_factor*0.0209; |
2199 else | 2200 else |
2200 CNS_fraction += time_factor*0.0482; // value for 2.5 | 2201 CNS_fraction += time_factor*0.0482; // value for 2.5 |
2201 | 2202 |
2202 if( CNS_fraction > 2.5 ) | 2203 if( CNS_fraction > 2.5 ) |
2210 ////////////////////////////////////////////////////////////////////////////// | 2211 ////////////////////////////////////////////////////////////////////////////// |
2211 // deco_calc_CNS_planning | 2212 // deco_calc_CNS_planning |
2212 // | 2213 // |
2213 // Compute CNS during predicted ascent. | 2214 // Compute CNS during predicted ascent. |
2214 // | 2215 // |
2215 // Note: Needs a call to deco_push_tissues_to_vault(), | 2216 // Note: Needs a call to deco_push_tissues_to_vault(), |
2216 // deco_pull_tissues_from_vault() to avoid trashing everything... | 2217 // deco_pull_tissues_from_vault() to avoid trashing everything... |
2217 // | 2218 // |
2218 // Input: CNS_fraction, char_O_deco_time[], char_O_deco_depth[] | 2219 // Input: CNS_fraction, char_O_deco_time[], char_O_deco_depth[] |
2219 // Output: CNS_fraction, char_O_CNS_fraction | 2220 // Output: CNS_fraction, char_O_CNS_fraction |
2220 // | 2221 // |
2235 backup_dive_mins = sim_dive_mins; | 2236 backup_dive_mins = sim_dive_mins; |
2236 backup_actual_ppO2 = char_I_actual_ppO2; | 2237 backup_actual_ppO2 = char_I_actual_ppO2; |
2237 | 2238 |
2238 // Uses 1min CNS period: | 2239 // Uses 1min CNS period: |
2239 char_I_step_is_1min = 1; | 2240 char_I_step_is_1min = 1; |
2240 | 2241 |
2241 //---- Retrieve bottom Gas used, and set variables. | 2242 //---- Retrieve bottom Gas used, and set variables. |
2242 sim_gas_last_used = char_I_first_gas; | 2243 sim_gas_last_used = char_I_first_gas; |
2243 sim_gas_last_depth = 0; // Surface gas marker. | 2244 sim_gas_last_depth = 0; // Surface gas marker. |
2244 gas_switch_set(); // Sets initial calc_N2/He_ratio | 2245 gas_switch_set(); // Sets initial calc_N2/He_ratio |
2245 | 2246 |
2291 { | 2292 { |
2292 time = char_O_deco_time[(NUM_STOPS-1)-i]; | 2293 time = char_O_deco_time[(NUM_STOPS-1)-i]; |
2293 temp_depth_limit = char_O_deco_depth[(NUM_STOPS-1)-i]; | 2294 temp_depth_limit = char_O_deco_depth[(NUM_STOPS-1)-i]; |
2294 } | 2295 } |
2295 if( time == 0 ) continue; | 2296 if( time == 0 ) continue; |
2296 | 2297 |
2297 //---- Gas Switch ? ---------------------------------------------- | 2298 //---- Gas Switch ? ---------------------------------------------- |
2298 switch_gas = temp_depth_limit & 0x80; // Switch flag. | 2299 switch_gas = temp_depth_limit & 0x80; // Switch flag. |
2299 temp_depth_limit &= 0x7F; // True stop depth. | 2300 temp_depth_limit &= 0x7F; // True stop depth. |
2300 | 2301 |
2301 if( switch_gas ) | 2302 if( switch_gas ) |
2325 sim_gas_last_depth = backup_gas_last_depth; | 2326 sim_gas_last_depth = backup_gas_last_depth; |
2326 sim_gas_last_used = backup_gas_last_used; | 2327 sim_gas_last_used = backup_gas_last_used; |
2327 sim_gas_delay = backup_gas_delay; | 2328 sim_gas_delay = backup_gas_delay; |
2328 sim_dive_mins = backup_dive_mins; | 2329 sim_dive_mins = backup_dive_mins; |
2329 char_I_actual_ppO2 = backup_actual_ppO2; | 2330 char_I_actual_ppO2 = backup_actual_ppO2; |
2330 } | 2331 } |
2331 | 2332 |
2332 ////////////////////////////////////////////////////////////////////////////// | 2333 ////////////////////////////////////////////////////////////////////////////// |
2333 // deco_calc_CNS_decrease_15min | 2334 // deco_calc_CNS_decrease_15min |
2334 // | 2335 // |
2335 // new in v.101 | 2336 // new in v.101 |
2513 void deco_push_tissues_to_vault(void) | 2514 void deco_push_tissues_to_vault(void) |
2514 { | 2515 { |
2515 overlay unsigned char x; | 2516 overlay unsigned char x; |
2516 RESET_C_STACK | 2517 RESET_C_STACK |
2517 | 2518 |
2518 cns_vault = CNS_fraction; | 2519 cns_vault = CNS_fraction; |
2519 low_depth_vault = low_depth; | 2520 low_depth_vault = low_depth; |
2520 | 2521 |
2521 for (x=0;x<NUM_COMP;x++) | 2522 for (x=0;x<NUM_COMP;x++) |
2522 { | 2523 { |
2523 pres_tissue_N2_vault[x] = pres_tissue_N2[x]; | 2524 pres_tissue_N2_vault[x] = pres_tissue_N2[x]; |
2524 pres_tissue_He_vault[x] = pres_tissue_He[x]; | 2525 pres_tissue_He_vault[x] = pres_tissue_He[x]; |
2525 } | 2526 } |
2526 } | 2527 } |
2527 | 2528 |
2528 void deco_pull_tissues_from_vault(void) | 2529 void deco_pull_tissues_from_vault(void) |
2529 { | 2530 { |
2530 overlay unsigned char x; | 2531 overlay unsigned char x; |
2531 RESET_C_STACK | 2532 RESET_C_STACK |
2532 | 2533 |
2533 for (x=0; x<NUM_COMP; x++) | 2534 for (x=0; x<NUM_COMP; x++) |
2534 { | 2535 { |
2535 pres_tissue_N2[x] = pres_tissue_N2_vault[x]; | 2536 pres_tissue_N2[x] = pres_tissue_N2_vault[x]; |
2536 pres_tissue_He[x] = pres_tissue_He_vault[x]; | 2537 pres_tissue_He[x] = pres_tissue_He_vault[x]; |
2537 } | 2538 } |
2538 | 2539 |
2539 // Restore both CNS variable, too. | 2540 // Restore both CNS variable, too. |
2540 CNS_fraction = cns_vault; | 2541 CNS_fraction = cns_vault; |
2541 char_O_CNS_fraction = (unsigned char)(CNS_fraction * 100.0 + 0.5); | 2542 char_O_CNS_fraction = (unsigned char)(CNS_fraction * 100.0 + 0.5); |
2542 | 2543 |
2543 // GF history too: | 2544 // GF history too: |