Mercurial > public > ostc4
annotate Common/Src/decom.c @ 771:29d9b5bc7946
Revised automatic setpoint change. The proposed approach is essentially the approach used by most controllers of eCCR ('upshift' on descent, 'downshift' on ascent), so that the OSTC4 when used as a backup computer for eCCR will make the changes at the same time as the eCCR itself.
author | heinrichsweikamp |
---|---|
date | Fri, 21 Apr 2023 09:48:23 +0200 |
parents | 9bc817e9e221 |
children | 012f94ec2fe0 |
rev | line source |
---|---|
38 | 1 /////////////////////////////////////////////////////////////////////////////// |
2 /// -*- coding: UTF-8 -*- | |
3 /// | |
4 /// \file Common/Src/decom.c | |
5 /// \brief This code is used to calculate desat, calculated by RTE and send to Firmware | |
6 /// \author heinrichs weikamp gmbh | |
7 /// \date 22-Feb-2016 | |
8 /// | |
9 /// $Id$ | |
10 /////////////////////////////////////////////////////////////////////////////// | |
11 /// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh | |
12 /// | |
13 /// This program is free software: you can redistribute it and/or modify | |
14 /// it under the terms of the GNU General Public License as published by | |
15 /// the Free Software Foundation, either version 3 of the License, or | |
16 /// (at your option) any later version. | |
17 /// | |
18 /// This program is distributed in the hope that it will be useful, | |
19 /// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 /// GNU General Public License for more details. | |
22 /// | |
23 /// You should have received a copy of the GNU General Public License | |
24 /// along with this program. If not, see <http://www.gnu.org/licenses/>. | |
25 ////////////////////////////////////////////////////////////////////////////// | |
26 /** | |
27 @verbatim | |
28 ============================================================================== | |
29 ##### Changes ##### | |
30 ============================================================================== | |
31 V1.0.2 1602220x decom_oxygen_calculate_cns() changed to hwOS version | |
32 | |
33 @endverbatim | |
34 ****************************************************************************** | |
35 */ | |
36 | |
37 #include "decom.h" | |
38 | |
39 #include <math.h> | |
40 #include "settings.h" | |
41 #include "calc_crush.h" | |
42 | |
43 # define FRACTION_N2_AIR 0.7902 | |
44 | |
45 const float helium_time_constant[16] = { | |
46 3.68695308808482E-001, | |
47 2.29518933960247E-001, | |
48 1.46853216220327E-001, | |
49 9.91626867753856E-002, | |
50 6.78890480470074E-002, | |
51 4.78692804254106E-002, | |
52 3.37626488338989E-002, | |
53 2.38113081607676E-002, | |
54 1.68239606932026E-002, | |
55 1.25592893741610E-002, | |
56 9.80544886914621E-003, | |
57 7.67264977374303E-003, | |
58 6.01220557342307E-003, | |
59 4.70185307665137E-003, | |
60 3.68225234041620E-003, | |
61 2.88775228329769E-003}; | |
62 | |
63 const float nitrogen_time_constant[16] = { | |
64 1.38629436111989E-001, | |
65 8.66433975699932E-002, | |
66 5.54517744447956E-002, | |
67 3.74674151654024E-002, | |
68 2.56721177985165E-002, | |
69 1.80978376125312E-002, | |
70 1.27651414467762E-002, | |
71 9.00191143584345E-003, | |
72 6.35914844550409E-003, | |
73 4.74758342849278E-003, | |
74 3.70666941475907E-003, | |
75 2.90019740820061E-003, | |
76 2.27261370675392E-003, | |
77 1.77730046297422E-003, | |
78 1.39186180835330E-003, | |
79 1.09157036308653E-003}; | |
80 | |
81 | |
82 const float buehlmann_N2_a[] = { | |
83 1.1696f, | |
84 1.0000f, | |
85 0.8618f, | |
86 0.7562f, | |
87 0.6200f, | |
88 0.5043f, | |
89 0.4410f, | |
90 0.4000f, | |
91 0.3750f, | |
92 0.3500f, | |
93 0.3295f, | |
94 0.3065f, | |
95 0.2835f, | |
96 0.2610f, | |
97 0.2480f, | |
98 0.2327f}; | |
99 | |
100 const float buehlmann_N2_b[] = { | |
101 0.5578f, | |
102 0.6514f, | |
103 0.7222f, | |
104 0.7825f, | |
105 0.8126f, | |
106 0.8434f, | |
107 0.8693f, | |
108 0.8910f, | |
109 0.9092f, | |
110 0.9222f, | |
111 0.9319f, | |
112 0.9403f, | |
113 0.9477f, | |
114 0.9544f, | |
115 0.9602f, | |
116 0.9653f}; | |
117 | |
118 const float buehlmann_He_a[] = { | |
119 1.6189f, | |
120 1.3830f, | |
121 1.1919f, | |
122 1.0458f, | |
123 0.9220f, | |
124 0.8205f, | |
125 0.7305f, | |
126 0.6502f, | |
127 0.5950f, | |
128 0.5545f, | |
129 0.5333f, | |
130 0.5189f, | |
131 0.5181f, | |
132 0.5176f, | |
133 0.5172f, | |
134 0.5119f}; | |
135 | |
136 const float buehlmann_He_b[] = { | |
137 0.4770f, | |
138 0.5747f, | |
139 0.6527f, | |
140 0.7223f, | |
141 0.7582f, | |
142 0.7957f, | |
143 0.8279f, | |
144 0.8553f, | |
145 0.8757f, | |
146 0.8903f, | |
147 0.8997f, | |
148 0.9073f, | |
149 0.9122f, | |
150 0.9171f, | |
151 0.9217f, | |
152 0.9267f}; | |
153 | |
154 const float buehlmann_N2_t_halflife[] = { | |
155 5.0f, | |
156 8.0f, | |
157 12.5f, | |
158 18.5f, | |
159 27.0f, | |
160 38.3f, | |
161 54.3f, | |
162 77.0f, | |
163 109.0f, | |
164 146.0f, | |
165 187.0f, | |
166 239.0f, | |
167 305.0f, | |
168 390.0f, | |
169 498.0f, | |
170 635.0f}; | |
171 | |
172 const float buehlmann_He_t_halflife[] = { | |
173 1.88f, | |
174 3.02f, | |
175 4.72f, | |
176 6.99f, | |
177 10.21f, | |
178 14.48f, | |
179 20.53f, | |
180 29.11f, | |
181 41.20f, | |
182 55.19f, | |
183 70.69f, | |
184 90.34f, | |
185 115.29f, | |
186 147.42f, | |
187 188.24f, | |
188 240.03f}; | |
189 | |
190 const float float_buehlmann_N2_factor_expositon_one_second[] = { 2.30782347297664E-003f, 1.44301447809736E-003f, 9.23769302935806E-004f, 6.24261986779007E-004f, 4.27777107246730E-004f, 3.01585140931371E-004f, 2.12729727268379E-004f, 1.50020603047807E-004f, 1.05980191127841E-004f, 7.91232600646508E-005f, 6.17759153688224E-005f, 4.83354552742732E-005f, 3.78761777920511E-005f, 2.96212356654113E-005f, 2.31974277413727E-005f, 1.81926738960225E-005f}; | |
191 const float float_buehlmann_N2_factor_expositon_003_second[] = { 6.90750456296407E-003f, 4.32279956671600E-003f, 2.76874864793053E-003f, 1.87161709452954E-003f, 1.28278242026003E-003f, 9.04482589432765E-004f, 6.38053429621421E-004f, 4.49994293975742E-004f, 3.17906879170993E-004f, 2.37350999218289E-004f, 1.85316297551252E-004f, 1.44999356986975E-004f, 1.13624229615916E-004f, 8.88610747694640E-005f, 6.95906688746861E-005f, 5.45770287740943E-005f}; | |
192 const float float_buehlmann_N2_factor_expositon_008_second[] = { 1.83141447532454E-002f, 1.14859796471039E-002f, 7.36630472495203E-003f, 4.98319782231915E-003f, 3.41709742823104E-003f, 2.41013596224415E-003f, 1.70057124687550E-003f, 1.19953484034729E-003f, 8.47527105247492E-004f, 6.32810814525819E-004f, 4.94100480767923E-004f, 3.86618231662861E-004f, 3.02969256443353E-004f, 2.36945319086024E-004f, 1.85564355251966E-004f, 1.45532124251058E-004f}; | |
193 const float float_buehlmann_N2_factor_expositon_10_seconds[] = { 2.28400315657541E-002f, 1.43368013598124E-002f, 9.19938673477072E-003f, 6.22511239287027E-003f, 4.69545762670800E-003f, 3.01176178733265E-003f, 2.12526200031782E-003f, 1.49919365737827E-003f, 1.05929662305226E-03f, 7.909509380171760E-004f, 6.17587450108648E-004f, 4.83249432061905E-004f, 3.78697227222391E-004f, 2.61728759809380E-004f, 2.31950063482533E-004f, 1.81911845881011E-004f}; | |
194 const float float_buehlmann_N2_factor_expositon_18_seconds[] = { 4.07358806747357E-002f, 2.56581087982929E-002f, 1.64979259737517E-002f, 1.11772892486697E-002f, 7.67205373705648E-003f, 5.41463899418337E-003f, 3.82221908774349E-003f, 2.69693016270112E-003f, 1.90592594569927E-003f, 1.42326123023573E-003f, 1.11138278062062E-003f, 8.69680830683950E-004f, 6.81551750048359E-004f, 5.33048018290350E-004f, 4.17471377070378E-004f, 3.27417496114757E-004f}; | |
195 const float float_buehlmann_N2_factor_expositon_20_seconds[] = { 4.51583960895835E-002f, 2.84680588463941E-002f, 1.83141447532454E-002f, 1.24114727614367E-002f, 8.52086250432193E-003f, 6.01445286560154E-003f, 4.24600726206570E-003f, 2.99613973313428E-003f, 2.11747113676897E-003f, 1.58127627264804E-003f, 1.23479348595879E-003f, 9.66265334110261E-004f, 7.57251042854845E-004f, 5.92258033589421E-004f, 4.63846326133055E-004f, 3.63790599842373E-004f}; | |
196 const float float_buehlmann_N2_factor_expositon_one_minute[] = { 1.29449436703876E-001f, 8.29959567953288E-002f, 5.39423532744041E-002f, 3.67741962370398E-002f, 2.53453908775689E-002f, 1.79350552316596E-002f, 1.26840126026602E-002f, 8.96151553540825E-003f, 6.33897185233323E-003f, 4.73633146787078E-003f, 3.69980819572546E-003f, 2.89599589841472E-003f, 2.27003327536857E-003f, 1.77572199977927E-003f, 1.39089361795441E-003f, 1.09097481687104E-003f}; | |
197 const float float_buehlmann_N2_factor_expositon_100_second[] = { 2.06299474015900E-001f, 1.34463438993857E-001f, 8.82775114417832E-002f, 6.05359181023788E-002f, 4.18844218114071E-002f, 2.97126970072147E-002f, 2.10505144045823E-002f, 1.48911986890571E-002f, 1.05426136839346E-002f, 7.88141652426455E-003f, 6.15873909572406E-003f, 4.82199900095137E-003f, 3.78052526350936E-003f, 2.95778454900952E-003f, 2.31708109427220E-003f, 1.81763004457269E-003f}; | |
198 const float float_buehlmann_N2_factor_expositon_five_minutes[]= { 5.00000000000000E-001f, 3.51580222674495E-001f, 2.42141716744801E-001f, 1.70835801932547E-001f, 1.20463829104624E-001f, 8.65157896183918E-002f, 6.18314987350977E-002f, 4.40116547625051E-002f, 3.12955727186929E-002f, 2.34583889613009E-002f, 1.83626606868127E-002f, 1.43963540993090E-002f, 1.12987527093947E-002f, 8.84713405486026E-003f, 6.93514912851934E-003f, 5.44298480182925E-003f}; | |
199 const float float_buehlmann_N2_factor_expositon_800_second[] = { 8.42509868763141E-001f, 6.85019737526282E-001f, 5.22579198044792E-001f, 3.93205767018569E-001f, 2.89861248917861E-001f, 2.14397627137602E-001f, 1.56505490290652E-001f, 1.13102166881646E-001f, 8.12935637814599E-002f, 6.13392112527207E-002f, 4.82208523469105E-002f, 3.79311861210304E-002f, 2.98470272862601E-002f, 2.34187624071612E-002f, 1.83870151711824E-002f, 1.44488700649190E-002f}; | |
200 const float float_buehlmann_N2_factor_expositon_one_hour[]= { 9.99755859375000E-001f, 9.94475728271980E-001f, 9.64103176406343E-001f, 8.94394508891055E-001f, 7.85689004286732E-001f, 6.62392147498621E-001f, 5.35088626789486E-001f, 4.17318576947576E-001f, 3.17197008420226E-001f, 2.47876700002107E-001f, 1.99405069752929E-001f, 1.59713055172538E-001f, 1.27468761759271E-001f, 1.01149026804458E-001f, 8.01196838116008E-002f, 6.33955413542552E-002f}; | |
201 | |
202 const float float_buehlmann_He_factor_expositon_one_second[] = { 6.12608039419837E-003f, 3.81800836683133E-003f, 2.44456078654209E-003f, 1.65134647076792E-003f, 1.13084424730725E-003f, 7.97503165599123E-004f, 5.62552521860549E-004f, 3.96776399429366E-004f, 2.80360036664540E-004f, 2.09299583354805E-004f, 1.63410794820518E-004f, 1.27869320250551E-004f, 1.00198406028040E-004f, 7.83611475491108E-005f, 6.13689891868496E-005f, 4.81280465299827E-005f}; | |
203 const float float_buehlmann_He_factor_expositon_003_second[] = { 1.82658845044263E-002f, 1.14103491926518E-002f, 7.31576933570466E-003f, 4.94586307993539E-003f, 3.38869776192019E-003f, 2.39060197012086E-003f, 1.68670834759044E-003f, 1.18985696621965E-003f, 8.40844326779777E-004f, 6.27767340286467E-004f, 4.90152279561396E-004f, 3.83558911153159E-004f, 3.00565099928485E-004f, 2.35065021719993E-004f, 1.84095669333084E-004f, 1.44377190774980E-004f}; // 3 He | |
204 const float float_buehlmann_He_factor_expositon_008_second[] = { 4.79706116082057E-002f, 3.01390075707096E-002f, 1.93899772993034E-002f, 1.31346689569831E-002f, 9.01102820363486E-003f, 6.36224538449637E-003f, 4.49156910795023E-003f, 3.16980660943422E-003f, 2.24068067793926E-003f, 1.67317060331207E-003f, 1.30653891641375E-003f, 1.02249686330114E-003f, 8.01306192375617E-004f, 6.26717274191169E-004f, 4.90846474157092E-004f, 3.84959521834594E-004f}; // 8 He | |
205 const float float_buehlmann_He_factor_expositon_10_seconds[] = { 5.95993001714799E-002f, 3.75307444923134E-002f, 2.41784389107607E-002f, 1.63912909924208E-002f, 1.25106927410620E-002f, 7.94647192918641E-003f, 5.61130562069978E-003f, 3.96068706690245E-003f, 2.80006593100546E-003f, 2.09102564918129E-003f, 1.63290683272987E-003f, 1.27795767799976E-003f, 1.00153239354972E-003f, 7.33352120986130E-004f, 6.13520442722559E-004f, 4.81176244777948E-004f}; | |
206 const float float_buehlmann_He_factor_expositon_18_seconds[] = { 1.04710896899039E-001f, 6.65386126706349E-002f, 4.30995968284519E-002f, 2.93106657684409E-002f, 2.01607137751910E-002f, 1.42581599093282E-002f, 1.00776711616688E-002f, 7.11793906429403E-003f, 5.03447255531631E-003f, 3.76069760984632E-003f, 2.93731229281968E-003f, 2.29914783358365E-003f, 1.80203605181650E-003f, 1.40956155658090E-003f, 1.10406577253352E-003f, 8.65950533235460E-004f}; | |
207 const float float_buehlmann_He_factor_expositon_20_seconds[] = { 1.15646523762030E-001f, 7.36529322024796E-002f, 4.77722809133601E-002f, 3.25139075644434E-002f, 2.23755519884017E-002f, 1.58297974422514E-002f, 1.11911244906306E-002f, 7.90568709176287E-003f, 5.59229149279306E-003f, 4.17767891009702E-003f, 3.26314728073529E-003f, 2.55428218017273E-003f, 2.00206171996409E-003f, 1.56605681014277E-003f, 1.22666447811148E-003f, 9.62120958977297E-004f}; | |
208 const float float_buehlmann_He_factor_expositon_one_minute[] = { 3.08363886219441E-001f, 2.05084082411030E-001f, 1.36579295730211E-001f, 9.44046323514587E-002f, 6.56358626478964E-002f, 4.67416115355790E-002f, 3.31990512604121E-002f, 2.35300557146709E-002f, 1.66832281977395E-002f, 1.24807506400979E-002f, 9.75753219809561E-003f, 7.64329013320042E-003f, 5.99416843126677E-003f, 4.69081666943783E-003f, 3.67548116287808E-003f, 2.88358673732592E-003f}; | |
209 const float float_buehlmann_He_factor_expositon_100_second[] = { 4.59084487437744E-001f, 3.17867635141657E-001f, 2.17103957783539E-001f, 1.52336166567559E-001f, 1.06981885584572E-001f, 7.66825160768219E-002f, 5.47171474343117E-002f, 3.89083581201959E-002f, 2.76504642556165E-002f, 2.07145921483078E-002f, 1.62096019995457E-002f, 1.27063337640768E-002f, 9.97030625587825E-003f, 7.80579708939710E-003f, 6.11829377951190E-003f, 4.80135692933603E-003f}; // 100 He | |
210 const float float_buehlmann_He_factor_expositon_five_minutes[]= { 8.41733751018722E-001f, 6.82600697933713E-001f, 5.20142493735619E-001f, 3.90924736715930E-001f, 2.87834706153524E-001f, 2.12857832580192E-001f, 1.55333364924147E-001f, 1.12242395185686E-001f, 8.06788883581406E-002f, 6.08653819753062E-002f, 4.78448115000141E-002f, 3.76366999883051E-002f, 2.96136888654287E-002f, 2.32350754744602E-002f, 1.82428098114835E-002f, 1.43350223887367E-002f}; // thre | |
211 const float float_buehlmann_He_factor_expositon_800_second[] = { 9.92671155759686E-001f, 9.53124140216102E-001f, 8.58865632718416E-001f, 7.33443528431762E-001f, 5.95533881446524E-001f, 4.71787742036413E-001f, 3.62479376011699E-001f, 2.72021750877104E-001f, 2.00940186773410E-001f, 1.54187175639359E-001f, 1.22553521140786E-001f, 9.72431193565182E-002f, 7.70338702477497E-002f, 6.07666995543268E-002f, 4.79109397391700E-002f, 3.77715319879068E-002f}; // 800 He | |
212 const float float_buehlmann_He_factor_expositon_one_hour[]= { 9.99999999753021E-001f, 9.99998954626205E-001f, 9.99850944669188E-001f, 9.97393537149572E-001f, 9.82979603888650E-001f, 9.43423231328217E-001f, 8.68106292901111E-001f, 7.60374619482322E-001f, 6.35576141220644E-001f, 5.29310840978539E-001f, 4.44744511849213E-001f, 3.68942936079581E-001f, 3.02834419265355E-001f, 2.45810174422126E-001f, 1.98231319020275E-001f, 1.59085372294989E-001f}; | |
213 | |
214 void decom_get_inert_gases(const float ambient_pressure_bar,const SGas* pGas, float* fraction_nitrogen, float* fraction_helium ) | |
215 { | |
216 float fraction_all_inertgases; | |
217 float ppo2_fraction_setpoint; | |
218 float diluent_divisor; | |
219 | |
220 *fraction_nitrogen = ((float)pGas->nitrogen_percentage) / 100.0f; | |
221 *fraction_helium = ((float)pGas->helium_percentage) / 100.0f; | |
222 | |
662 | 223 if(pGas->AppliedDiveMode == DIVEMODE_CCR) |
224 { | |
225 // continue with CCR | |
226 fraction_all_inertgases = *fraction_nitrogen + *fraction_helium; | |
38 | 227 |
662 | 228 ppo2_fraction_setpoint = (float)pGas->setPoint_cbar/ (100 * ambient_pressure_bar); |
229 | |
230 diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases; | |
231 if(diluent_divisor < 0) | |
232 diluent_divisor = 0; | |
38 | 233 |
662 | 234 *fraction_nitrogen *= diluent_divisor; |
235 *fraction_helium *= diluent_divisor; | |
236 } | |
237 if(pGas->AppliedDiveMode == DIVEMODE_PSCR) | |
238 { | |
239 fraction_all_inertgases = *fraction_nitrogen + *fraction_helium; | |
240 ppo2_fraction_setpoint = decom_calc_SimppO2(ambient_pressure_bar, pGas) / ambient_pressure_bar; | |
241 diluent_divisor = (1.0f - ppo2_fraction_setpoint) / fraction_all_inertgases; | |
242 if(diluent_divisor < 0) | |
243 diluent_divisor = 0; | |
38 | 244 |
662 | 245 *fraction_nitrogen *= diluent_divisor; |
246 *fraction_helium *= diluent_divisor; | |
247 } | |
38 | 248 } |
249 | |
250 | |
251 void decom_tissues_exposure(int period_in_seconds, SLifeData * pLifeData) | |
252 { | |
253 decom_tissues_exposure2(period_in_seconds, &pLifeData->actualGas, pLifeData->pressure_ambient_bar, pLifeData->tissue_nitrogen_bar, pLifeData->tissue_helium_bar); | |
254 } | |
255 | |
256 | |
257 void decom_tissues_exposure2(int period_in_seconds, SGas* pActualGas, float ambiant_pressure_bar, float *tissue_N2_selected_stage, float *tissue_He_selected_stage) | |
258 { | |
259 int ci; | |
260 float percent_N2; | |
261 float percent_He; | |
262 float partial_pressure_N2; | |
263 float partial_pressure_He; | |
264 | |
265 | |
266 | |
267 int period_in_seconds_left; | |
268 | |
57 | 269 if(period_in_seconds > 0) |
270 { | |
38 | 271 |
272 decom_get_inert_gases(ambiant_pressure_bar, pActualGas, &percent_N2, &percent_He); | |
273 | |
274 partial_pressure_N2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_N2; | |
275 partial_pressure_He = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_He; | |
57 | 276 period_in_seconds_left = period_in_seconds; |
38 | 277 |
57 | 278 while(period_in_seconds_left) |
279 { | |
280 if(period_in_seconds_left >= 3600) | |
281 period_in_seconds = 3600; | |
282 else | |
283 if(period_in_seconds_left >= 800) | |
284 period_in_seconds = 800; | |
285 else | |
286 if(period_in_seconds_left >= 300) | |
287 period_in_seconds = 300; | |
288 else | |
289 if(period_in_seconds_left >= 100) | |
290 period_in_seconds = 100; | |
291 else | |
292 if(period_in_seconds_left >= 60) | |
293 period_in_seconds = 60; | |
294 else | |
295 if(period_in_seconds_left == 36) | |
296 period_in_seconds = 18; | |
297 else | |
298 if(period_in_seconds_left >= 20) | |
299 period_in_seconds = 20; | |
300 else | |
301 if(period_in_seconds_left >= 18) | |
302 period_in_seconds = 18; | |
303 else | |
304 if(period_in_seconds_left >= 10) | |
305 period_in_seconds = 10; | |
306 else | |
307 if(period_in_seconds_left >= 8) | |
308 period_in_seconds = 8; | |
309 else | |
310 if(period_in_seconds_left >= 3) | |
311 period_in_seconds = 3; | |
312 else | |
313 period_in_seconds = 1; | |
38 | 314 |
57 | 315 period_in_seconds_left -= period_in_seconds; |
38 | 316 |
57 | 317 switch (period_in_seconds) |
38 | 318 { |
57 | 319 case 1: |
320 for (ci=0;ci<16;ci++) | |
321 { | |
322 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_one_second[ci]; | |
323 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_one_second[ci]; | |
324 } | |
325 break; | |
326 case 3: | |
327 for (ci=0;ci<16;ci++) | |
328 { | |
329 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_003_second[ci]; | |
330 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_003_second[ci]; | |
331 } | |
332 break; | |
333 case 8: | |
334 for (ci=0;ci<16;ci++) | |
335 { | |
336 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_008_second[ci]; | |
337 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_008_second[ci]; | |
338 } | |
339 break; | |
340 case 10: | |
341 for (ci=0;ci<16;ci++) | |
342 { | |
343 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_10_seconds[ci]; | |
344 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_10_seconds[ci]; | |
345 } | |
346 break; | |
347 case 18: | |
348 for (ci=0;ci<16;ci++) | |
349 { | |
350 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_18_seconds[ci]; | |
351 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_18_seconds[ci]; | |
352 } | |
353 break; | |
354 case 20: | |
355 for (ci=0;ci<16;ci++) | |
356 { | |
357 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_20_seconds[ci]; | |
358 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_20_seconds[ci]; | |
359 } | |
360 break; | |
361 case 60: | |
362 for (ci=0;ci<16;ci++) | |
363 { | |
364 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_one_minute[ci]; | |
365 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_one_minute[ci]; | |
366 } | |
367 break; | |
368 case 100: | |
369 for (ci=0;ci<16;ci++) | |
370 { | |
371 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_100_second[ci]; | |
372 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_100_second[ci]; | |
373 } | |
374 break; | |
375 case 300: | |
376 for (ci=0;ci<16;ci++) | |
377 { | |
378 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_five_minutes[ci]; | |
379 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_five_minutes[ci]; | |
380 } | |
381 break; | |
382 case 800: | |
383 for (ci=0;ci<16;ci++) | |
384 { | |
385 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_800_second[ci]; | |
386 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_800_second[ci]; | |
387 } | |
388 break; | |
389 case 3600: | |
390 for (ci=0;ci<16;ci++) | |
391 { | |
392 tissue_N2_selected_stage[ci] += (partial_pressure_N2 - tissue_N2_selected_stage[ci]) * float_buehlmann_N2_factor_expositon_one_hour[ci]; | |
393 tissue_He_selected_stage[ci] += (partial_pressure_He - tissue_He_selected_stage[ci]) * float_buehlmann_He_factor_expositon_one_hour[ci]; | |
394 } | |
395 break; | |
38 | 396 } |
397 } | |
398 } | |
399 } | |
400 | |
401 void decom_reset_with_1000mbar(SLifeData * pLifeData) | |
402 { | |
403 double saturation = 1.0; | |
404 | |
405 saturation -= WATER_VAPOUR_PRESSURE; | |
406 saturation *= FRACTION_N2_AIR; | |
407 | |
408 for(int i=0;i<16;i++) | |
409 { | |
410 pLifeData->tissue_nitrogen_bar[i] = saturation; | |
411 pLifeData->tissue_helium_bar[i] = 0; | |
412 } | |
413 pLifeData->otu = 0; | |
414 pLifeData->cns = 0; | |
415 pLifeData->desaturation_time_minutes = 0; | |
416 pLifeData->no_fly_time_minutes = 0; | |
417 } | |
418 | |
129
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
419 void decom_reset_with_ambientmbar(float ambient, SLifeData * pLifeData) |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
420 { |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
421 |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
422 float saturation = 1.0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
423 saturation = ambient; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
424 saturation -= WATER_VAPOUR_PRESSURE; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
425 saturation *= FRACTION_N2_AIR; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
426 |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
427 for(int i=0;i<16;i++) |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
428 { |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
429 pLifeData->tissue_nitrogen_bar[i] = saturation; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
430 pLifeData->tissue_helium_bar[i] = 0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
431 } |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
432 pLifeData->otu = 0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
433 pLifeData->cns = 0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
434 pLifeData->desaturation_time_minutes = 0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
435 pLifeData->no_fly_time_minutes = 0; |
239aa58b533d
Added function to initialise structures with the actual ambient pressure
Ideenmodellierer
parents:
57
diff
changeset
|
436 } |
38 | 437 |
438 /* =============================================================================== */ | |
439 /* NOTE ABOUT PRESSURE UNITS USED IN CALCULATIONS: */ | |
440 /* It is the convention in decompression calculations to compute all gas */ | |
441 /* loadings, absolute pressures, partial pressures, etc., in the units of */ | |
442 /* depth pressure that you are diving - either feet of seawater (fsw) or */ | |
443 /* meters of seawater (msw). This program follows that convention with the */ | |
444 /* the exception that all VPM calculations are performed in SI units (by */ | |
445 /* necessity). Accordingly, there are several conversions back and forth */ | |
446 /* between the diving pressure units and the SI units. */ | |
447 /* =============================================================================== */ | |
448 /* =============================================================================== */ | |
449 /* FUNCTION SUBPROGRAM FOR GAS LOADING CALCULATIONS - ASCENT AND DESCENT */ | |
450 /* =============================================================================== */ | |
451 | |
452 | |
453 float decom_schreiner_equation(float *initial_inspired_gas_pressure, | |
454 float *rate_change_insp_gas_pressure, | |
455 float *interval_time_minutes, | |
456 const float *gas_time_constant, | |
457 float *initial_gas_pressure) | |
458 { | |
459 /* System generated locals */ | |
460 float ret_val; | |
461 float time_null_pressure = 0.0f; | |
462 float time_rest = 0.0f; | |
463 float time = *interval_time_minutes; | |
464 /* =============================================================================== */ | |
465 /* Note: The Schreiner equation is applied when calculating the uptake or */ | |
466 /* elimination of compartment gases during linear ascents or descents at a */ | |
467 /* constant rate. For ascents, a negative number for rate must be used. */ | |
468 /* =============================================================================== */ | |
469 if( *rate_change_insp_gas_pressure < 0.0f) | |
470 { | |
471 time_null_pressure = -1.0f * *initial_inspired_gas_pressure / *rate_change_insp_gas_pressure; | |
472 if(time > time_null_pressure ) | |
473 { | |
474 time_rest = time - time_null_pressure; | |
475 time = time_null_pressure; | |
476 } | |
477 } | |
478 ret_val = | |
479 *initial_inspired_gas_pressure + | |
480 *rate_change_insp_gas_pressure * | |
481 (time - 1.f / *gas_time_constant) - | |
482 (*initial_inspired_gas_pressure - | |
483 *initial_gas_pressure - | |
484 *rate_change_insp_gas_pressure / *gas_time_constant) * | |
485 expf(-(*gas_time_constant) * time); | |
486 | |
487 if(time_rest > 0.0f) | |
488 { | |
489 ret_val = ret_val * expf(-(*gas_time_constant) * time_rest); | |
490 } | |
491 | |
492 | |
493 return ret_val; | |
494 }; /* schreiner_equation__2 */ | |
495 | |
496 void decom_tissues_exposure_stage_schreiner(int period_in_seconds, SGas* pGas, float starting_ambient_pressure_bar, float ending_ambient_pressure_bar, | |
497 float* pTissue_nitrogen_bar, float* pTissue_helium_bar) | |
498 { | |
499 | |
500 float initial_pressure_N2; | |
501 float initial_pressure_He; | |
502 | |
503 float ending_pressure_N2; | |
504 float ending_pressure_He; | |
505 | |
506 float fraction_N2_begin; | |
507 float fraction_N2_end; | |
508 float fraction_He_begin; | |
509 float fraction_He_end; | |
510 | |
511 float rate_N2; | |
512 float rate_He; | |
513 | |
514 float period_in_minutes; | |
515 | |
516 int ci; | |
517 | |
518 if(period_in_seconds <= 0) | |
519 return; | |
520 | |
521 decom_get_inert_gases(starting_ambient_pressure_bar, pGas, &fraction_N2_begin, &fraction_He_begin ); | |
522 decom_get_inert_gases(ending_ambient_pressure_bar, pGas, &fraction_N2_end, &fraction_He_end ); | |
523 | |
524 initial_pressure_N2 = (starting_ambient_pressure_bar - WATER_VAPOUR_PRESSURE) * fraction_N2_begin; | |
525 initial_pressure_He = (starting_ambient_pressure_bar - WATER_VAPOUR_PRESSURE) * fraction_He_begin; | |
526 | |
527 ending_pressure_N2 = (ending_ambient_pressure_bar - WATER_VAPOUR_PRESSURE) * fraction_N2_end; | |
528 ending_pressure_He = (ending_ambient_pressure_bar - WATER_VAPOUR_PRESSURE) * fraction_He_end; | |
529 | |
530 rate_N2 = (ending_pressure_N2 - initial_pressure_N2) / period_in_seconds; | |
531 rate_He = (ending_pressure_He - initial_pressure_He) / period_in_seconds; | |
532 | |
533 period_in_minutes = ((float)period_in_seconds) / 60.0f; | |
534 | |
535 for (ci=0;ci<16;ci++) | |
536 { | |
537 pTissue_nitrogen_bar[ci] = | |
538 decom_schreiner_equation( | |
539 &initial_pressure_N2, | |
540 &rate_N2, | |
541 &period_in_minutes, | |
542 &nitrogen_time_constant[ci], | |
543 &pTissue_nitrogen_bar[ci]); | |
544 | |
545 pTissue_helium_bar[ci] = | |
546 decom_schreiner_equation( | |
547 &initial_pressure_He, | |
548 &rate_He, | |
549 &period_in_minutes, | |
550 &helium_time_constant[ci], | |
551 &pTissue_helium_bar[ci]); | |
552 } | |
553 } | |
554 | |
555 _Bool nextSetpointChange(SDiveSettings* pDiveSettings, uint8_t depth_meter, uint8_t* change_depth_meter, char* setpoint) | |
556 { | |
557 uint8_t new_depth = 0; | |
558 char new_setpoint = 0; | |
559 for(int i = 1; i <= 5; i++) | |
560 { | |
561 if(pDiveSettings->setpoint[i].setpoint_cbar > 0 && pDiveSettings->setpoint[i].depth_meter > 0 ) | |
562 { | |
563 if( pDiveSettings->setpoint[i].depth_meter > new_depth && pDiveSettings->setpoint[i].depth_meter < depth_meter) | |
564 { | |
565 new_depth = pDiveSettings->setpoint[i].depth_meter; | |
566 new_setpoint = pDiveSettings->setpoint[i].setpoint_cbar; | |
567 } | |
568 } | |
569 } | |
570 if(new_depth) | |
571 { | |
572 * change_depth_meter = new_depth; | |
573 * setpoint = new_setpoint; | |
574 return 1; | |
575 } | |
576 return 0; | |
577 } | |
578 | |
579 | |
580 | |
581 void decom_CreateGasChangeList(SDiveSettings* pInput, const SLifeData* pLifeData) | |
582 { | |
583 int i=0, j = 0; | |
584 int count = 0; | |
585 for(i=0;i< 5;i++) | |
586 { | |
587 //FirstGas | |
588 | |
589 pInput->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero = 0; | |
590 pInput->decogaslist[i].GasIdInSettings = 255; | |
591 pInput->decogaslist[i].setPoint_cbar = 0; | |
592 pInput->decogaslist[i].helium_percentage = 0; | |
593 pInput->decogaslist[i].nitrogen_percentage = 0; | |
594 } | |
595 //pInput->liveData.dive_time_seconds = 0; | |
596 | |
597 /* FirstGas | |
598 * 0 = special gas, 1 to 5 ist OC gas, 6 to 10 is diluent | |
599 */ | |
600 | |
601 | |
602 | |
603 pInput->decogaslist[0] = pLifeData->actualGas; | |
604 | |
605 /* Add Deco Gases | |
606 * special (gasId == 0) is never a deco/travel gas but actual gas only | |
607 */ | |
608 if(pInput->diveMode == DIVEMODE_OC) | |
609 { | |
610 | |
611 for(i=1;i<= 5;i++) | |
612 { | |
613 if(pInput->gas[i].note.ub.active && pInput->gas[i].depth_meter | |
614 && (pLifeData->actualGas.GasIdInSettings != i) | |
615 &&(pInput->gas[i].depth_meter < pLifeData->depth_meter ) ) | |
616 { | |
617 count = 1; | |
618 for(j=1;j<= 5;j++) | |
619 { | |
620 if( (pInput->gas[j].note.ub.active && pInput->gas[j].depth_meter > 0) | |
621 && (pLifeData->actualGas.GasIdInSettings != j) // new hw 160905 | |
622 && (pInput->gas[j].depth_meter > pInput->gas[i].depth_meter)) | |
623 count++; | |
624 } | |
625 pInput->decogaslist[count].change_during_ascent_depth_meter_otherwise_zero = pInput->gas[i].depth_meter; | |
626 pInput->decogaslist[count].nitrogen_percentage = 100; | |
627 pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; | |
628 pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage; | |
629 pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage; | |
630 pInput->decogaslist[count].GasIdInSettings = i; | |
662 | 631 pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_OC; |
38 | 632 } |
633 } | |
634 } | |
635 else | |
636 { | |
662 | 637 //divmode CCR or PSCR |
38 | 638 for(i=6; i <= 10; i++) |
639 { | |
684
9bc817e9e221
Ignore automatic setpoint changes during ascend:
Ideenmodellierer
parents:
662
diff
changeset
|
640 if((pInput->gas[i].note.ub.active) && (pInput->gas[i].depth_meter) |
38 | 641 && (pLifeData->actualGas.GasIdInSettings != i) |
684
9bc817e9e221
Ignore automatic setpoint changes during ascend:
Ideenmodellierer
parents:
662
diff
changeset
|
642 && (pInput->gas[i].depth_meter < pLifeData->depth_meter )) |
38 | 643 { |
644 count = 1; | |
645 for(j=6;j<= 10;j++) | |
646 { | |
647 // if(pInput->gas[j].note.ub.active && pInput->gas[j].depth_meter > 0 &&pInput->gas[j].depth_meter > pInput->gas[i].depth_meter) | |
684
9bc817e9e221
Ignore automatic setpoint changes during ascend:
Ideenmodellierer
parents:
662
diff
changeset
|
648 if(((pInput->gas[j].note.ub.active) && (pInput->gas[j].depth_meter > 0)) |
38 | 649 && (pLifeData->actualGas.GasIdInSettings != j) // new hw 160905 |
650 && (pInput->gas[j].depth_meter > pInput->gas[i].depth_meter)) | |
651 count++; | |
652 } | |
653 pInput->decogaslist[count].change_during_ascent_depth_meter_otherwise_zero = pInput->gas[i].depth_meter; | |
654 pInput->decogaslist[count].nitrogen_percentage = 100; | |
662 | 655 if(pInput->diveMode == DIVEMODE_PSCR) |
656 { | |
657 pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_PSCR; | |
658 pInput->decogaslist[count].setPoint_cbar = decom_calc_SimppO2_O2based((float)(pInput->gas[i].depth_meter / 10.0 + 1.0), pInput->gas[i].oxygen_percentage, pInput->decogaslist[count].pscr_factor ) * 100; | |
659 pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; | |
660 } | |
661 else | |
662 { | |
663 pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].oxygen_percentage; | |
684
9bc817e9e221
Ignore automatic setpoint changes during ascend:
Ideenmodellierer
parents:
662
diff
changeset
|
664 pInput->decogaslist[count].AppliedDiveMode = DIVEMODE_CCR; |
9bc817e9e221
Ignore automatic setpoint changes during ascend:
Ideenmodellierer
parents:
662
diff
changeset
|
665 pInput->decogaslist[count].setPoint_cbar = pInput->decogaslist[0].setPoint_cbar; /* assume that current setpoint is kept till end of the dive */ |
662 | 666 } |
38 | 667 pInput->decogaslist[count].nitrogen_percentage -= pInput->gas[i].helium_percentage; |
668 pInput->decogaslist[count].helium_percentage = pInput->gas[i].helium_percentage; | |
669 pInput->decogaslist[count].GasIdInSettings = i; | |
670 } | |
671 } | |
672 } | |
673 } | |
674 void test_decom_CreateGasChangeList(void) | |
675 { | |
676 SDiveSettings diveSetting; | |
677 SLifeData lifeData; | |
678 lifeData.depth_meter = 100; | |
679 lifeData.actualGas.helium_percentage = 30; | |
680 lifeData.actualGas.nitrogen_percentage = 60; | |
681 lifeData.actualGas.setPoint_cbar = 18; | |
682 lifeData.actualGas.GasIdInSettings = 0; | |
683 lifeData.actualGas.change_during_ascent_depth_meter_otherwise_zero = 0; | |
684 diveSetting.diveMode = DIVEMODE_CCR; | |
685 diveSetting.gas[6].depth_meter = 0; | |
686 diveSetting.gas[6].helium_percentage = 30; | |
687 diveSetting.gas[6].oxygen_percentage = 10; | |
688 diveSetting.gas[6].note.ub.active = 1; | |
689 | |
690 diveSetting.gas[7].depth_meter = 60; | |
691 diveSetting.gas[7].helium_percentage = 0; | |
692 diveSetting.gas[7].oxygen_percentage = 10; | |
693 diveSetting.gas[7].note.ub.active = 1; | |
694 diveSetting.gas[8].note.ub.active = 0; | |
695 diveSetting.gas[9].note.ub.active = 0; | |
696 diveSetting.gas[10].note.ub.active = 0; | |
697 | |
698 diveSetting.setpoint[0].depth_meter = 0; | |
699 diveSetting.setpoint[1].depth_meter = 80; | |
700 diveSetting.setpoint[1].setpoint_cbar = 20; | |
701 diveSetting.setpoint[2].depth_meter = 60; | |
702 diveSetting.setpoint[2].setpoint_cbar = 25; | |
703 diveSetting.setpoint[3].depth_meter = 0; | |
704 diveSetting.setpoint[4].depth_meter = 0; | |
705 diveSetting.setpoint[5].depth_meter = 0; | |
706 | |
707 | |
708 decom_CreateGasChangeList(&diveSetting, &lifeData); | |
709 } | |
710 | |
711 uint8_t decom_tissue_test_tolerance(float* Tissue_nitrogen_bar, float* Tissue_helium_bar, float GF_value, float depth_in_bar_absolute) | |
712 { | |
713 float tissue_inertgas_saturation; | |
714 float inertgas_a; | |
715 float inertgas_b; | |
716 float inertgas_tolerance; | |
717 float gf_minus_1; | |
718 | |
719 gf_minus_1 = GF_value - 1.0f; | |
720 | |
721 for (int ci = 0; ci < 16; ci++) | |
722 { | |
723 if(Tissue_helium_bar[ci] == 0) | |
724 { | |
725 tissue_inertgas_saturation = Tissue_nitrogen_bar[ci]; | |
726 // | |
727 inertgas_a = buehlmann_N2_a[ci]; | |
728 inertgas_b = buehlmann_N2_b[ci]; | |
729 } | |
730 else | |
731 { | |
732 tissue_inertgas_saturation = Tissue_nitrogen_bar[ci] + Tissue_helium_bar[ci]; | |
733 // | |
734 inertgas_a = ( ( buehlmann_N2_a[ci] * Tissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * Tissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
735 inertgas_b = ( ( buehlmann_N2_b[ci] * Tissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * Tissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
736 } | |
737 // | |
738 inertgas_tolerance = ( (GF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( GF_value * inertgas_a ); | |
739 // | |
740 if(inertgas_tolerance < tissue_inertgas_saturation) | |
741 return 0; | |
742 } | |
743 return 1; | |
744 } | |
745 | |
746 | |
747 void decom_tissues_desaturation_time(const SLifeData* pLifeData, SLifeData2* pOutput) | |
748 { | |
749 float pressure_in_gas_for_complete; | |
750 float pressure_in_gas_for_desat; | |
751 float diff_to_complete; | |
752 float diff_to_desatpoint; | |
753 float necessary_halftimes; | |
754 float desattime; | |
755 | |
756 pressure_in_gas_for_complete = 0.7902f * ( pLifeData->pressure_surface_bar - 0.0627f); | |
757 pressure_in_gas_for_desat = 1.05f * pressure_in_gas_for_complete; | |
758 for(int i=0; i<16; i++) | |
759 { | |
760 diff_to_complete = pressure_in_gas_for_complete - pLifeData->tissue_nitrogen_bar[i]; | |
761 diff_to_desatpoint = pressure_in_gas_for_desat - pLifeData->tissue_nitrogen_bar[i]; | |
762 | |
763 if((diff_to_desatpoint >= 0) || (diff_to_complete >= 0)) | |
764 pOutput->tissue_nitrogen_desaturation_time_minutes[i] = 0; | |
765 else | |
766 { | |
767 necessary_halftimes = (logf(1.0f - (diff_to_desatpoint/diff_to_complete)) / -0.6931f); | |
768 desattime = buehlmann_N2_t_halflife[i] * necessary_halftimes; | |
769 if(desattime <= (float)0xFFFF) | |
770 pOutput->tissue_nitrogen_desaturation_time_minutes[i] = desattime; | |
771 else | |
772 pOutput->tissue_nitrogen_desaturation_time_minutes[i] = 0xFFFF; | |
773 } | |
774 } | |
775 | |
776 for(int i=0; i<16; i++) | |
777 { | |
778 diff_to_desatpoint = 0.05f - pLifeData->tissue_helium_bar[i]; | |
779 diff_to_complete = -1.0f * pLifeData->tissue_helium_bar[i]; | |
780 | |
781 if((diff_to_desatpoint >= 0) || (diff_to_complete >= 0)) | |
782 pOutput->tissue_helium_desaturation_time_minutes[i] = 0; | |
783 else | |
784 { | |
785 necessary_halftimes = (logf(1.0f - (diff_to_desatpoint/diff_to_complete)) / -0.6931f); | |
786 desattime = buehlmann_He_t_halflife[i] * necessary_halftimes; | |
787 if(desattime <= (float)0xFFFF) | |
788 pOutput->tissue_helium_desaturation_time_minutes[i] = desattime; | |
789 else | |
790 pOutput->tissue_helium_desaturation_time_minutes[i] = 0xFFFF; | |
791 } | |
792 } | |
793 } | |
794 | |
795 #define MAX_DEGRADE_OTU_TIME_MINUTES (1440) | |
796 //CNS&OTU: | |
797 #define OXY_TEN_MINUTES_IN_SECONDS (600) | |
798 #define OXY_HALF_LIVE_OF_TEN_MINUTES__INVERSE_NINTH_ROOT_OF_TWO (0.92587471f) | |
799 #define OXY_NINE_DAYS_IN_TEN_MINUTES (1296) | |
800 #define OXY_ONE_SIXTIETH_PART (0.0166667f) | |
801 #define OXY_NEGATIVE_FIVE_SIXTH_PARTS (-0.8333333f) | |
802 void decom_oxygen_calculate_otu(float* oxygen_otu, float pressure_oxygen_real) | |
803 { | |
804 if(pressure_oxygen_real <= 0.5f) | |
805 return; | |
806 *oxygen_otu += (pow((double)(0.5f / (pressure_oxygen_real - 0.5f)),OXY_NEGATIVE_FIVE_SIXTH_PARTS)) * OXY_ONE_SIXTIETH_PART; | |
807 } | |
808 | |
809 void decom_oxygen_calculate_otu_degrade(float* oxygen_otu, long seconds_since_last_dive) | |
810 { | |
811 static long otu_time_ticker = 0; | |
812 static double otu_degrade_every_10_minutes = 999.9; | |
813 long cycles_since_last_call; | |
814 | |
815 if((*oxygen_otu <= 0) || (seconds_since_last_dive == 0)) | |
816 *oxygen_otu = 0; | |
817 else if(seconds_since_last_dive < OXY_TEN_MINUTES_IN_SECONDS) | |
818 { | |
819 otu_time_ticker = 1; | |
820 otu_degrade_every_10_minutes = *oxygen_otu / (MAX_DEGRADE_OTU_TIME_MINUTES / 10); | |
821 } | |
822 else | |
823 { | |
824 cycles_since_last_call = seconds_since_last_dive / (otu_time_ticker * OXY_TEN_MINUTES_IN_SECONDS); | |
825 *oxygen_otu -= ((double)cycles_since_last_call) * otu_degrade_every_10_minutes; | |
826 otu_time_ticker += cycles_since_last_call; | |
827 if((*oxygen_otu < 0) || (otu_time_ticker > (MAX_DEGRADE_OTU_TIME_MINUTES / 10))) | |
828 *oxygen_otu = 0; | |
829 } | |
830 } | |
831 | |
832 | |
833 | |
834 void decom_oxygen_calculate_cns_degrade(float* oxygen_cns, long seconds_since_last_dive) | |
835 { | |
836 static long cns_time_ticker = 0; | |
837 int cns_max_cycles; | |
838 | |
839 if((*oxygen_cns <= 0.5f) || (seconds_since_last_dive == 0)) | |
840 *oxygen_cns = 0; | |
841 else if(seconds_since_last_dive < OXY_TEN_MINUTES_IN_SECONDS) | |
842 cns_time_ticker = 1; | |
843 else | |
844 { | |
845 cns_max_cycles = OXY_NINE_DAYS_IN_TEN_MINUTES; | |
846 while((*oxygen_cns >= 0.5f) && ((cns_time_ticker * OXY_TEN_MINUTES_IN_SECONDS) < seconds_since_last_dive) && cns_max_cycles) | |
847 { | |
848 cns_time_ticker++; | |
849 cns_max_cycles--; | |
850 *oxygen_cns *= OXY_HALF_LIVE_OF_TEN_MINUTES__INVERSE_NINTH_ROOT_OF_TWO; | |
851 } | |
852 } | |
853 } | |
854 | |
855 | |
856 // new hwOS style | |
857 void decom_oxygen_calculate_cns(float* oxygen_cns, float pressure_oxygen_real) | |
858 { | |
859 uint8_t char_I_actual_ppO2; | |
860 float CNS_fraction = 0; | |
861 const float time_factor = 3000.0f; | |
862 | |
863 if(pressure_oxygen_real < 0.15f) | |
864 char_I_actual_ppO2 = 15; | |
865 else | |
866 if(pressure_oxygen_real >= 2.5f) | |
867 char_I_actual_ppO2 = 255; | |
868 else | |
869 char_I_actual_ppO2 = (uint8_t)(pressure_oxygen_real * 100); | |
870 | |
871 if (char_I_actual_ppO2 < 50) | |
872 (void)0; // no changes | |
873 //------------------------------------------------------------------------ | |
874 // Below (and including) 1.60 bar | |
875 else if (char_I_actual_ppO2 < 61) | |
876 CNS_fraction += time_factor/(-533.07f * char_I_actual_ppO2 + 54000.0f); | |
877 else if (char_I_actual_ppO2 < 71) | |
878 CNS_fraction += time_factor/(-444.22f * char_I_actual_ppO2 + 48600.0f); | |
879 else if (char_I_actual_ppO2 < 81) | |
880 CNS_fraction += time_factor/(-355.38f * char_I_actual_ppO2 + 42300.0f); | |
881 else if (char_I_actual_ppO2 < 91) | |
882 CNS_fraction += time_factor/(-266.53f * char_I_actual_ppO2 + 35100.0f); | |
883 else if (char_I_actual_ppO2 < 111) | |
884 CNS_fraction += time_factor/(-177.69f * char_I_actual_ppO2 + 27000.0f); | |
885 else if (char_I_actual_ppO2 < 152) | |
886 CNS_fraction += time_factor/( -88.84f * char_I_actual_ppO2 + 17100.0f); | |
887 else if (char_I_actual_ppO2 < 167) | |
888 CNS_fraction += time_factor/(-222.11f * char_I_actual_ppO2 + 37350.0f); | |
889 //------------------------------------------------------------------------ | |
890 // Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity: | |
891 // J Appl Physiol 92: 248--256, 2002, doi:10.1152/japplphysiol.00434.2001 | |
892 // Formula (A1) based on value for 1.55 and c=20 | |
893 // example calculation: Sqrt((1.7/1.55)^20)*0.000404 | |
894 else if (char_I_actual_ppO2 < 172) | |
895 CNS_fraction += time_factor*0.00102f; | |
896 else if (char_I_actual_ppO2 < 177) | |
897 CNS_fraction += time_factor*0.00136f; | |
898 else if (char_I_actual_ppO2 < 182) | |
899 CNS_fraction += time_factor*0.00180f; | |
900 else if (char_I_actual_ppO2 < 187) | |
901 CNS_fraction += time_factor*0.00237f; | |
902 else if (char_I_actual_ppO2 < 192) | |
903 CNS_fraction += time_factor*0.00310f; | |
904 else if (char_I_actual_ppO2 < 198) | |
905 CNS_fraction += time_factor*0.00401f; | |
906 else if (char_I_actual_ppO2 < 203) | |
907 CNS_fraction += time_factor*0.00517f; | |
908 else if (char_I_actual_ppO2 < 233) | |
909 CNS_fraction += time_factor*0.0209f; | |
910 else | |
911 CNS_fraction += time_factor*0.0482f; // value for 2.5 | |
912 | |
913 if( CNS_fraction > 999.0f) // Limit display to 999% | |
914 CNS_fraction = 999.0f; | |
915 if( CNS_fraction < 0.0f ) | |
916 CNS_fraction = 0.0f; | |
917 | |
918 //calculate cns for the actual ppo2 for 1 second | |
919 *oxygen_cns += OXY_ONE_SIXTIETH_PART * CNS_fraction; | |
920 | |
921 if( *oxygen_cns > 999.0f) // Limit display to 999% | |
922 *oxygen_cns = 999.0f; | |
923 if( *oxygen_cns < 0.0f ) | |
924 *oxygen_cns = 0.0f; | |
925 } | |
926 | |
927 /* old DR5 style | |
928 void decom_oxygen_calculate_cns(float* oxygen_cns, float pressure_oxygen_real) | |
929 { | |
930 int cns_no_range = 0; | |
931 _Bool not_found = 1; | |
932 //for the cns calculation | |
933 const float cns_ppo2_ranges[60][2] = { | |
934 {0.50f, 0.00f}, {0.60f, 0.14f}, {0.64f, 0.15f}, {0.66f, 0.16f}, {0.68f, 0.17f}, {0.70f, 0.18f}, | |
935 {0.74f, 0.19f}, {0.76f, 0.20f}, {0.78f, 0.21f}, {0.80f, 0.22f}, {0.82f, 0.23f}, {0.84f, 0.24f}, | |
936 {0.86f, 0.25f}, {0.88f, 0.26f}, {0.90f, 0.28f}, {0.92f, 0.29f}, {0.94f, 0.30f}, {0.96f, 0.31f}, | |
937 {0.98f, 0.32f}, {1.00f, 0.33f}, {1.02f, 0.35f}, {1.04f, 0.36f}, {1.06f, 0.38f}, {1.08f, 0.40f}, | |
938 {1.10f, 0.42f}, {1.12f, 0.43f}, {1.14f, 0.43f}, {1.16f, 0.44f}, {1.18f, 0.46f}, {1.20f, 0.47f}, | |
939 {1.22f, 0.48f}, {1.24f, 0.51f}, {1.26f, 0.52f}, {1.28f, 0.54f}, {1.30f, 0.56f}, {1.32f, 0.57f}, | |
940 {1.34f, 0.60f}, {1.36f, 0.62f}, {1.38f, 0.63f}, {1.40f, 0.65f}, {1.42f, 0.68f}, {1.44f, 0.71f}, | |
941 {1.46f, 0.74f}, {1.48f, 0.78f}, {1.50f, 0.83f}, {1.52f, 0.93f}, {1.54f, 1.04f}, {1.56f, 1.19f}, | |
942 {1.58f, 1.47f}, {1.60f, 2.22f}, {1.62f, 5.00f}, {1.65f, 6.25f}, {1.67f, 7.69f}, {1.70f, 10.0f}, | |
943 {1.72f,12.50f}, {1.74f,20.00f}, {1.77f,25.00f}, {1.79f,31.25f}, {1.80f,50.00f}, {1.82f,100.0f}}; | |
944 //find the correct cns range for the corresponding ppo2 | |
945 cns_no_range = 58; | |
946 while (cns_no_range && not_found) | |
947 { | |
948 if (pressure_oxygen_real > cns_ppo2_ranges[cns_no_range][0]) | |
949 { | |
950 cns_no_range++; | |
951 not_found = 0; | |
952 } | |
953 else | |
954 cns_no_range--; | |
955 } | |
956 | |
957 //calculate cns for the actual ppo2 for 1 second | |
958 *oxygen_cns += OXY_ONE_SIXTIETH_PART * cns_ppo2_ranges[cns_no_range][1]; | |
959 } | |
960 */ | |
961 | |
962 void decom_oxygen_calculate_cns_exposure(int period_in_seconds, SGas* pActualGas, float pressure_ambient_bar, float* oxygen_cns) | |
963 { | |
964 float pressure_oxygen_real; | |
965 float one_second_cns; | |
966 | |
967 pressure_oxygen_real = decom_calc_ppO2(pressure_ambient_bar, pActualGas); | |
968 one_second_cns = 0; | |
969 decom_oxygen_calculate_cns(&one_second_cns, pressure_oxygen_real); | |
970 *oxygen_cns += one_second_cns * period_in_seconds; | |
971 } | |
972 | |
973 | |
974 void decom_oxygen_calculate_cns_stage_SchreinerStyle(int period_in_seconds, SGas* pGas, float starting_ambient_pressure_bar, float ending_ambient_pressure_bar, float* oxygen_cns) | |
975 { | |
976 if(ending_ambient_pressure_bar == starting_ambient_pressure_bar) | |
977 { | |
978 decom_oxygen_calculate_cns_exposure(period_in_seconds, pGas, starting_ambient_pressure_bar, oxygen_cns); | |
979 return; | |
980 } | |
981 | |
982 float pressure_oxygen_real; | |
983 float initial_pressure_oxygen; | |
984 float ending_pressure_oxygen; | |
985 float rate_oxygen; | |
986 | |
987 initial_pressure_oxygen = decom_calc_ppO2(starting_ambient_pressure_bar, pGas); | |
988 ending_pressure_oxygen = decom_calc_ppO2(ending_ambient_pressure_bar, pGas); | |
989 | |
990 rate_oxygen = (ending_pressure_oxygen - initial_pressure_oxygen) / period_in_seconds; | |
991 | |
992 pressure_oxygen_real = initial_pressure_oxygen; | |
993 for(int i = 0; i < period_in_seconds; i++) | |
994 { | |
995 decom_oxygen_calculate_cns(oxygen_cns, pressure_oxygen_real); | |
996 pressure_oxygen_real += rate_oxygen; | |
997 } | |
998 } | |
999 | |
1000 | |
1001 float decom_calc_ppO2(const float ambiant_pressure_bar, const SGas* pGas) | |
1002 { | |
662 | 1003 float percent_N2 = 0; |
38 | 1004 float percent_He = 0; |
1005 float percent_O2 = 0; | |
1006 | |
662 | 1007 decom_get_inert_gases(ambiant_pressure_bar, pGas, &percent_N2, &percent_He); |
1008 percent_O2 = 1 - percent_N2 - percent_He; | |
1009 | |
1010 return (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2; | |
38 | 1011 } |
1012 | |
1013 | |
662 | 1014 float decom_calc_SimppO2(float ambiant_pressure_bar, const SGas* pGas) |
1015 { | |
1016 float o2Ratio = 0.0; | |
1017 float inertGasRatio = 0.0; | |
1018 float simulatedPSCRppo2 = 0.0; | |
1019 | |
1020 o2Ratio = (100.0 - pGas->nitrogen_percentage - pGas->helium_percentage) / 100.0; | |
1021 inertGasRatio = 1.0 - o2Ratio; | |
1022 simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio; | |
1023 simulatedPSCRppo2 -= (inertGasRatio * pGas->pscr_factor); | |
1024 if(simulatedPSCRppo2 < 0.0) | |
1025 { | |
1026 simulatedPSCRppo2 = 0.0; | |
1027 } | |
1028 return simulatedPSCRppo2; | |
1029 } | |
1030 | |
1031 float decom_calc_SimppO2_O2based(float ambiant_pressure_bar, uint8_t O2PerCent, float factor) | |
1032 { | |
1033 float o2Ratio = 0.0; | |
1034 float inertGasRatio = 0.0; | |
1035 float simulatedPSCRppo2 = 0.0; | |
1036 | |
1037 o2Ratio = O2PerCent / 100.0; | |
1038 inertGasRatio = 1.0 - o2Ratio; | |
1039 simulatedPSCRppo2 = (ambiant_pressure_bar - WATER_VAPOUR_PRESSURE) * o2Ratio; | |
1040 simulatedPSCRppo2 -= (inertGasRatio * factor); | |
1041 if(simulatedPSCRppo2 < 0.0) | |
1042 { | |
1043 simulatedPSCRppo2 = 0.0; | |
1044 } | |
1045 return simulatedPSCRppo2; | |
1046 } | |
1047 | |
38 | 1048 uint8_t decom_get_actual_deco_stop(SDiveState* pDiveState) |
1049 { | |
1050 SDecoinfo* pDecoinfo; | |
1051 uint8_t depthNext, depthLast, depthSecond, depthInc; | |
1052 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
1053 pDecoinfo = &pDiveState->decolistBuehlmann; | |
1054 else | |
1055 pDecoinfo = &pDiveState->decolistVPM; | |
1056 | |
1057 depthLast = (uint8_t)(pDiveState->diveSettings.last_stop_depth_bar * 10); | |
1058 depthSecond = (uint8_t)(pDiveState->diveSettings.input_second_to_last_stop_depth_bar * 10); | |
1059 depthInc = (uint8_t)(pDiveState->diveSettings.input_next_stop_increment_depth_bar * 10); | |
1060 if(pDecoinfo->output_stop_length_seconds[0] > 0) | |
1061 { | |
1062 depthNext = depthLast; | |
1063 } | |
1064 else | |
1065 return 0; | |
1066 for(int i = DECOINFO_STRUCT_MAX_STOPS -1 ;i > 0; i--) | |
1067 { | |
1068 if(pDecoinfo->output_stop_length_seconds[i] > 0) | |
1069 { | |
1070 depthNext = depthSecond + ( (i - 1) * depthInc); | |
1071 break; | |
1072 } | |
1073 } | |
1074 return depthNext; | |
1075 } | |
1076 | |
1077 | |
1078 // =============================================================================== | |
1079 // decom_calc_desaturation_time | |
1080 /// @brief This code is used to calculate desat, calculated by RTE and send to Firmware | |
1081 /// similar but more technical in code than decom_tissues_desaturation_time() | |
1082 /// the later has 0.05 for helium in contrast to this one. | |
1083 /// This one goes down to 70%, the oterh | |
1084 /// | |
1085 /// output is desat time in minutes | |
1086 // =============================================================================== | |
1087 int decom_calc_desaturation_time(float* Tissue_nitrogen_bar, float* Tissue_helium_bar, float surface_pressure_bar) | |
1088 { | |
1089 const float N2_ratio = 0.7902; // FIXED sum as stated in b"uhlmann | |
1090 | |
1091 float pres_surface; | |
1092 float temp_atem; | |
1093 float float_desaturation_multiplier; | |
1094 float temp1,temp2,temp3,temp4; | |
1095 int ci; | |
1096 int int_temp; | |
1097 int int_O_desaturation_time; | |
1098 pres_surface = ((float)surface_pressure_bar); | |
1099 temp_atem = N2_ratio * (pres_surface - 0.0627f); | |
1100 | |
1101 int_O_desaturation_time = 0; | |
1102 float_desaturation_multiplier = 100 / 142.0f; // new in v.101 (70,42%/100.=142) | |
1103 | |
1104 for (ci=0;ci<16;ci++) | |
1105 { | |
1106 // saturation_time (for flight) and N2_saturation in multiples of halftime | |
1107 // version v.100: 1.1 = 10 percent distance to totally clean (totally clean is not possible, would take infinite time ) | |
1108 // new in version v.101: 1.07 = 7 percent distance to totally clean (totally clean is not possible, would take infinite time ) | |
1109 // changes in v.101: 1.05 = 5 percent dist to totally clean is new desaturation point for display and noFly calculations | |
1110 | |
1111 // N2 | |
1112 temp1 = 1.05f * temp_atem; | |
1113 temp1 = temp1 - (float)Tissue_nitrogen_bar[ci]; | |
1114 temp2 = temp_atem - (float)Tissue_nitrogen_bar[ci]; | |
1115 if (temp2 >= 0) | |
1116 { | |
1117 temp1 = 0; | |
1118 temp2 = 0; | |
1119 } | |
1120 else | |
1121 temp1 = temp1 / temp2; | |
1122 | |
1123 if (temp1 > 0) | |
1124 { | |
1125 temp1 = logf(1.0f - temp1); | |
1126 temp1 = temp1 / -0.6931f; // temp1 is the multiples of half times necessary. | |
1127 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. | |
1128 // minus because log is negative | |
1129 temp2 = buehlmann_N2_t_halflife[ci] * temp1 / float_desaturation_multiplier; // time necessary (in minutes ) for complete desaturation (see comment about 10 percent) , new in v.101: float_desaturation_multiplier | |
1130 } | |
1131 else | |
1132 { | |
1133 temp1 = 0; | |
1134 temp2 = 0; | |
1135 } | |
1136 | |
1137 // He | |
1138 temp3 = 0.1f - (float)Tissue_helium_bar[ci]; | |
1139 if (temp3 >= 0) | |
1140 { | |
1141 temp3 = 0; | |
1142 temp4 = 0; | |
1143 } | |
1144 else | |
1145 temp3 = -1.0f * temp3 / (float)Tissue_helium_bar[ci]; | |
1146 if (temp3 > 0) | |
1147 { | |
1148 temp3 = logf(1.0f - temp3); | |
1149 temp3 = temp3 / -0.6931f; // temp1 is the multiples of half times necessary. | |
1150 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested. | |
1151 // minus because log is negative | |
1152 temp4 = buehlmann_He_t_halflife[ci] * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier | |
1153 } | |
1154 else | |
1155 { | |
1156 temp3 = 0; | |
1157 temp4 = 0; | |
1158 } | |
1159 | |
1160 // saturation_time (for flight) | |
1161 if (temp4 > temp2) | |
1162 int_temp = (int)temp4; | |
1163 else | |
1164 int_temp = (int)temp2; | |
1165 if(int_temp > int_O_desaturation_time) | |
1166 int_O_desaturation_time = int_temp; | |
1167 | |
1168 /*// N2 saturation in multiples of halftime for display purposes | |
1169 temp2 = temp1 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8 | |
1170 temp2 = temp2 + 80.0; // set center | |
1171 if (temp2 < 0.0) | |
1172 temp2 = 0.0; | |
1173 if (temp2 > 255.0) | |
1174 temp2 = 255.0; | |
1175 U8_tissue_N2_saturation[ci] = (U8)temp2; | |
1176 // He saturation in multiples of halftime for display purposes | |
1177 temp4 = temp3 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8 | |
1178 temp4 = temp4 + 80.0; // set center | |
1179 if (temp4 < 0.0) | |
1180 temp4 = 0.0; | |
1181 if (temp4 > 255.0) | |
1182 temp4 = 255.0; | |
1183 U8_tissue_He_saturation[ci] = (char)temp4;*/ | |
1184 } | |
1185 | |
1186 return int_O_desaturation_time; | |
1187 } |