comparison code_part1/OSTC_code_c_part2/p2_deco_main - 090915b.c @ 0:96a35aeda5f2

Initial setup
author heinrichsweikamp
date Tue, 12 Jan 2010 15:05:59 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:96a35aeda5f2
1 /*
2 * OSTC - diving computer code
3 * ===========================
4 * PART 2 : C code
5 *
6 * p2_deco_main.c for OSTC Mk.2
7 * Created on: 31.08.2009
8 * Author: christian.w @ heinrichsweikamp.com
9 *
10 * #include <p2_tables.romdata>
11 * #include "ostc28.drx.txt"
12 * #include "ostc28.tbl.txt"
13 * #include "ostc48.tbl.txt"
14 * #include "ostc48.drx.txt"
15 * #include "ostc90.drx.txt"
16 * #include "ostc90.tbl.txt"
17 */
18
19 // Copyright (C) 2009 HeinrichsWeikamp GbR
20
21 // This program is free software: you can redistribute it and/or modify
22 // it under the terms of the GNU General Public License as published by
23 // the Free Software Foundation, either version 3 of the License, or
24 // (at your option) any later version.
25
26 // This program is distributed in the hope that it will be useful,
27 // but WITHOUT ANY WARRANTY; without even the implied warranty of
28 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 // GNU General Public License for more details.
30
31 // You should have received a copy of the GNU General Public License
32 // along with this program. If not, see <http://www.gnu.org/licenses/>.
33
34
35 // *****************************
36 // ** I N T R O D U C T I O N **
37 // *****************************
38 //
39 // OSTC
40 //
41 // code:
42 // p2_deco_main_c_v101.c
43 // part2 of the OSTC code
44 // code with constant O2 partial pressure routines
45 // experimental
46 //
47 // summary:
48 // decompression routines
49 // and display routines
50 // for the OSTC experimental project
51 // written by Christian Weikamp
52 // last revision __________
53 // comments added _________
54 //
55 // additional files:
56 // #include <p2_tables.romdata>
57 // #include "ostc28.drx.txt"
58 // #include "ostc28.tbl.txt"
59 // #include "ostc48.tbl.txt"
60 // #include "ostc48.drx.txt"
61 // #include "ostc90.drx.txt"
62 // #include "ostc90.tbl.txt"
63 // assembler code (PART 1) for working OSTC experimental plattform
64 //
65 // history:
66 // 14/09/09 v201: first alpha candidate for Mk. 2 based on v108 for OSTC
67 //
68 // literature:
69 // B"uhlmann, Albert: Tauchmedizin; 4. Auflage;
70 // Schr"oder, Kai & Reith, Steffen; 2000; S"attigungsvorg"ange beim Tauchen, das Modell ZH-L16, Funktionsweise von Tauchcomputern; http://www.achim-und-kai.de/kai/tausim/saett_faq
71 // Morrison, Stuart; 2000; DIY DECOMPRESSION; http://www.lizardland.co.uk/DIYDeco.html
72 // Balthasar, Steffen; Dekompressionstheorie I: Neo Haldane Modelle; http://www.txfreak.de/dekompressionstheorie_1.pdf
73 // Baker, Erik C.; Clearing Up The Confusion About "Deep Stops"
74 // Baker, Erik C.; Understanding M-values; http://www.txfreak.de/understanding_m-values.pdf
75
76
77 // *********************
78 // ** I N C L U D E S **
79 // *********************
80 #include <p18f4685.h>
81 #include <math.h>
82
83 // ********************************
84 // ** C O N F I G U R A T I O N **
85 // ** for simulation without asm **
86 // ********************************
87 #pragma config OSC = IRCIO67
88 #pragma config FCMEN = OFF
89 #pragma config IESO = OFF
90 #pragma config PWRT = ON
91 #pragma config BOREN = OFF
92 #pragma config WDT = OFF
93 #pragma config WDTPS = 128
94 #pragma config MCLRE = ON
95 #pragma config LPT1OSC = OFF
96 #pragma config PBADEN = OFF
97 #pragma config DEBUG = OFF
98 #pragma config XINST = OFF
99 #pragma config LVP = OFF
100 #pragma config STVREN = OFF
101
102 // ****************************
103 // ** D E F I N E S **
104 // ** missing in p18f4685.h **
105 // ****************************
106 #define INT0IF 1
107 #define INT1IF 0
108 #define TMR1IF 0
109
110
111 # define DBG_c_gas 0b0000000000000001
112 # define DBG_c_ppO2 0b0000000000000010
113 # define DBG_RUN 0b0000000000000100
114 # define DBG_RESTART 0b0000000000001000
115
116 # define DBG_CdeSAT 0b0000000000010000
117 # define DBG_C_MODE 0b0000000000100000
118 # define DBG_C_SURF 0b0000000001000000
119 # define DBG_HEwoHE 0b0000000010000000
120
121 # define DBG_C_DPPO2 0b0000000100000000
122 # define DBG_C_DGAS 0b0000001000000000
123 # define DBG_C_DIST 0b0000010000000000
124 # define DBG_C_LAST 0b0000100000000000
125
126 # define DBG_C_GF 0b0001000000000000
127 # define DBG_ZH16ERR 0b0010000000000000
128 # define DBG_PHIGH 0b0100000000000000
129 # define DBG_PLOW 0b1000000000000000
130
131
132 # define DBS_mode 0b0000000000000001
133 # define DBS_ppO2 0b0000000000000010
134 # define DBS_HE_sat 0b0000000000000100
135 # define DBS_ppO2chg 0b0000000000001000
136
137 # define DBS_SAT2l 0b0000000000010000
138 # define DBS_SAT2h 0b0000000000100000
139 # define DBS_GFLOW2l 0b0000000001000000
140 # define DBS_GFLOW2h 0b0000000010000000
141
142 # define DBS_GFHGH2l 0b0000000100000000
143 # define DBS_GFHGH2h 0b0000001000000000
144 # define DBS_GASO22l 0b0000010000000000
145 # define DBS_GASO22h 0b0000100000000000
146
147 # define DBS_DIST2h 0b0001000000000000
148 # define DBS_LAST2h 0b0010000000000000
149 # define DBS_DECOO2l 0b0100000000000000
150 # define DBS_DECOO2h 0b1000000000000000
151
152
153 # define DBS2_PRES2h 0b0000000000000001
154 # define DBS2_PRES2l 0b0000000000000010
155 # define DBS2_SURF2l 0b0000000000000100
156 # define DBS2_SURF2h 0b0000000000001000
157
158 # define DBS2_DESAT2l 0b0000000000010000
159 # define DBS2_DESAT2h 0b0000000000100000
160 # define DBS2_GFDneg 0b0000000001000000
161 # define DBS2_ 0b000000000000000
162
163 # define DBS2_ 0b000000000000000
164 # define DBS2_ 0b000000000000000
165 # define DBS2_ 0b000000000000000
166 # define DBS2_ 0b000000000000000
167
168 // NDL_at_20mtr
169
170
171
172 // ***********************
173 // ** V A R I A B L E S **
174 // ***********************
175 // prefixes etc:
176 // _O_ = output for use in the assembler code
177 // _I_ = input from the assembler code for the c code
178 // char_ and int_ = used to identify output and input size
179 // var = variable (from b"uhlmann)
180 // pres = pressure
181 // gtissue = guiding tissue, the one limiting the ascent
182 // e2secs = exp of the b"uhlmann formula precalculated for a 2 second step
183 // e1min = same for 1 minute step
184 // sim = used in simulating the ascent to the surface
185 // nullzeit = remaining ground/bottom time for "no deco"
186 // hauptroutine = main
187
188 #define WP_FONT_SMALL_HEIGHT 24
189 #define WP_FONT_MEDIUM_HEIGHT 32
190 #define WP_FONT_LARGE_HEIGHT 58
191
192 #define oled_rw PORTA,2,0
193 #define oled_rs PORTE,0,0
194
195 #define U8 unsigned char
196 #define U16 unsigned int
197
198 // IO assembler
199 #pragma udata bank0a=0x060
200 volatile unsigned char wp_stringstore[26];
201 volatile U8 wp_color1;
202 volatile U8 wp_color2;
203 volatile U8 wp_top;
204 volatile U8 wp_leftx2;
205 volatile U8 wp_font;
206 volatile U8 wp_invert;
207 volatile U8 wp_temp_U8;
208 // internal C
209 #pragma udata bank0b=0x081
210 volatile U8 wp_txtptr;
211 volatile unsigned char wp_char;
212 volatile U8 wp_command;
213 volatile U16 wp_data_16bit;
214 volatile U8 wp_data_8bit_one;
215 volatile U8 wp_data_8bit_two;
216 volatile U16 wp_start;
217 volatile U16 wp_end;
218 volatile U16 wp_i;
219 volatile U8 wp_black;
220 // some spare
221 volatile U8 wp_debug_U8;
222
223 // asm only
224 #pragma udata bank0c=0x0D0
225 #define LENGTH_kf_bank0 48
226 volatile unsigned char keep_free_bank0[LENGTH_kf_bank0];
227
228
229 #pragma udata bank1=0x100
230 #define LENGTH_kf_bank1 256
231 volatile unsigned char keep_free_bank1[LENGTH_kf_bank1]; // used by the assembler code
232
233 #pragma udata bank2a=0x200
234 // output:
235 static unsigned int int_O_tissue_for_debug[32];
236 static unsigned int int_O_GF_spare____; // 0x240
237 static unsigned int int_O_GF_step; // 0x242
238 static unsigned int int_O_gtissue_limit; // 0x244
239 static unsigned int int_O_gtissue_press; // 0x246
240 static unsigned int int_O_limit_GF_low; // 0x248
241 static unsigned int int_O_gtissue_press_at_GF_low; // 0x24A
242 // 0x24C + 0x24D noch unbenutzt
243
244 #pragma udata bank2b=0x24E
245 static unsigned char char_O_GF_low_pointer; // 0x24E
246 static unsigned char char_O_actual_pointer; // 0x24F
247 #pragma udata bank2c=0x250
248 static unsigned char char_O_deco_table[32]; // 0x250
249 #pragma udata bank2d=0x270
250 static unsigned char char_I_table_deco_done[32];
251 #pragma udata bank2e=0x290
252 static unsigned int int_O_calc_tissue_call_counter; // 0x290
253 // internal:
254 unsigned char lock_GF_depth_list;
255 static float temp_limit;
256 static float GF_low;
257 static float GF_high;
258 static float GF_delta;
259 static float GF_temp;
260 static float GF_step;
261 static float GF_step2;
262 static float temp_pres_gtissue;
263 static float temp_pres_gtissue_diff;
264 static float temp_pres_gtissue_limit_GF_low;
265 static float temp_pres_gtissue_limit_GF_low_below_surface;
266 static unsigned int temp_depth_limit;
267 static unsigned char temp_decotime;
268 static unsigned char temp_gtissue_no;
269 static unsigned int temp_depth_last_deco; // new in v.101
270
271 static unsigned char temp_depth_GF_low_meter;
272 static unsigned char temp_depth_GF_low_number;
273 static unsigned char internal_deco_pointer;
274 static unsigned char internal_deco_table[32];
275 static float temp_pres_deco_GF_low;
276
277 static unsigned int debug_temp;
278
279
280 #pragma udata bank3a=0x300
281 static char output[32];
282
283 #pragma udata bank3b=0x380
284 volatile float pres_tissue_vault[32];
285
286 #pragma udata bank4a=0x400
287 // internal:
288 unsigned char ci ; // don't move - used in _asm routines - if moved then modify movlb commands
289 unsigned char x;
290 unsigned int main_i;
291 unsigned int int_temp;
292 unsigned int int_temp_decostatus;
293 static float pres_respiration;
294 static float pres_surface;
295 static float temp1;
296 static float temp2;
297 static float temp3;
298 static float temp4;
299 static float temp_deco;
300 static float temp_atem;
301 static float temp2_atem;
302 static float temp_tissue;
303 static float temp_surface;
304 static float N2_ratio;
305 static float He_ratio;
306 static float temp_ratio;
307 static float var_a;
308 static float var2_a;
309 static float var_b;
310 static float var2_b;
311 static float var_t05nc;
312 static float var2_t05nc;
313 static float var_e2secs;
314 static float var2_e2secs;
315 static float var_e1min;
316 static float var2_e1min;
317 static float var_halftimes;
318 static float var2_halftimes;
319 static float pres_gtissue_limit;
320 static float temp_pres_gtissue_limit;
321 static float actual_ppO2; // new in v.102
322
323 #pragma udata bank4b=0x480
324 static float pres_tissue[32];
325
326 #pragma udata bank5=0x500
327 // don't move positions in this bank, the registers are addressed directly from assembler code
328 // input:
329 static unsigned int int_I_pres_respiration; // 0x500
330 static unsigned int int_I_pres_surface; // 0x502
331 static unsigned int int_I_temp; // 0x504 new in v101
332 static unsigned char char_I_temp; // 0x506 new in v101
333 static unsigned char char_I_actual_ppO2; // 0x507
334 static unsigned int int_I_spare_3;
335 static unsigned int int_I_spare_4;
336 static unsigned int int_I_spare_5;
337 static unsigned int int_I_spare_6;
338 static unsigned char char_I_N2_ratio; // 0x510
339 static unsigned char char_I_He_ratio; // 0x511
340 static unsigned char char_I_saturation_multiplier; // for conservatism/safety values 1.0 (no conservatism) to 1.5 (50% faster saturation
341 static unsigned char char_I_desaturation_multiplier; // for conservatism/safety values 0.66 (50% slower desaturation) to 1.0 (no conservatism)// consveratism used in calc_tissue(), calc_tissue_step_1_min() and sim_tissue_1min()
342 static unsigned char char_I_GF_High_percentage; // 0x514 new in v.102
343 static unsigned char char_I_GF_Low_percentage; // 0x515 new in v.102
344 static unsigned char char_I_spare; // 0x516
345 static unsigned char char_I_deco_distance; // 0x517
346 static unsigned char char_I_const_ppO2; // 0x518 new in v.101
347 static unsigned char char_I_deco_ppO2_change; // 0x519 new in v.101
348 static unsigned char char_I_deco_ppO2; // 0x51A new in v.101
349 static unsigned char char_I_deco_gas_change; // 0x51B new in v.101
350 static unsigned char char_I_deco_N2_ratio; // 0x51C new in v.101
351 static unsigned char char_I_deco_He_ratio; // 0x51D new in v.101
352 static unsigned char char_I_depth_last_deco; // 0x51E new in v.101 unit: [m]
353 static unsigned char char_I_deco_model; // 0x51F new in v.102 ( 1 = MultiGraF, sonst Std. mit (de-)saturation_multiplier)
354 // output:
355 static unsigned int int_O_desaturation_time; // 0x520
356 static unsigned char char_O_nullzeit; // 0x522
357 static unsigned char char_O_deco_status; // 0x523
358 static unsigned char char_O_array_decotime[7]; // 0x524
359 static unsigned char char_O_array_decodepth[6]; // 0x52B
360 static unsigned char char_O_ascenttime; // 0x531
361 static unsigned char char_O_gradient_factor; // 0x532
362 static unsigned char char_O_tissue_saturation[32]; // 0x533
363 static unsigned char char_O_array_gradient_weighted[16]; // 0x553
364 static unsigned char char_O_gtissue_no; // 0x563
365 static unsigned char char_O_diluent; // 0x564 new in v.101
366 static unsigned char char_O_CNS_fraction; // 0x565 new in v.101
367 static unsigned char char_O_relative_gradient_GF; // 0x566 new in v.102
368
369 // internal:
370 static float pres_tissue_limit[16];
371 static float sim_pres_tissue_limit[16];
372 static float pres_diluent; // new in v.101
373 static float deco_diluent; // new in v.101
374 static float const_ppO2; // new in v.101
375 static float deco_ppO2_change; // new in v.101
376 static float deco_ppO2; // new in v.101
377
378 #pragma udata bank6=0x600
379 // internal:
380 static float sim_pres_tissue[32];
381 static float sim_pres_tissue_backup[32];
382
383 //#pragma udata bank7=0x700
384 //const unsigned char keep_free_bank7[256]; // used by the assembler code
385
386 #pragma udata bank8=0x800
387 static char md_pi_subst[256];
388
389 #pragma udata bank9a=0x900
390 // output:
391 static char md_state[48]; // DONT MOVE !! // has to be at the beginning of bank 9 for the asm code!!!
392 #pragma udata bank9b=0x930
393 // output:
394 static unsigned int int_O_DBS_bitfield; // 0x930 new in v.108
395 static unsigned int int_O_DBS2_bitfield; // 0x932 new in v.108
396 static unsigned int int_O_DBG_pre_bitfield; // 0x934 new in v.108
397 static unsigned int int_O_DBG_post_bitfield; // 0x936 new in v.108
398 static char char_O_NDL_at_20mtr; // 0x938 new in v.108 // 0xFF == undefined, max. 254
399 // internal:
400 static char md_t;
401 static char md_buffer[16];
402 static char md_cksum[16];
403 static char md_i;
404 static char md_j;
405 static char md_temp;
406 static unsigned int md_pointer;
407 static float deco_N2_ratio; // new in v.101
408 static float deco_He_ratio; // new in v.101
409 static float calc_N2_ratio; // new in v.101
410 static float calc_He_ratio; // new in v.101
411 static float deco_gas_change; // new in v.101
412 static float CNS_fraction; // new in v.101
413 static float float_saturation_multiplier; // new in v.101
414 static float float_desaturation_multiplier; // new in v.101
415 static float float_deco_distance; // new in v.101
416 // internal, dbg:
417 static unsigned char DBG_char_I_deco_model; // new in v.108
418 static unsigned char DBG_char_I_depth_last_deco; // new in v.108
419 static float DBG_pres_surface; // new in v.108
420 static float DBG_GF_low; // new in v.108
421 static float DBG_GF_high; // new in v.108
422 static float DBG_const_ppO2; // new in v.108
423 static float DBG_deco_ppO2_change; // new in v.108
424 static float DBG_deco_ppO2; // new in v.108
425 static float DBG_deco_N2_ratio; // new in v.108
426 static float DBG_deco_He_ratio; // new in v.108
427 static float DBG_deco_gas_change; // new in v.108
428 static float DBG_float_saturation_multiplier; // new in v.108
429 static float DBG_float_desaturation_multiplier; // new in v.108
430 static float DBG_float_deco_distance; // new in v.108
431 static float DBG_deco_N2_ratio; // new in v.108
432 static float DBG_deco_He_ratio; // new in v.108
433 static float DBG_N2_ratio; // new in v.108
434 static float DBG_He_ratio; // new in v.108
435 static char flag_in_divemode; // new in v.108
436 static int int_dbg_i; // new in v.108
437 unsigned int temp_DBS;
438
439 // *************************
440 // ** P R O T O T Y P E S **
441 // *************************
442 void main_calc_hauptroutine(void);
443 void main_calc_without_deco(void);
444 void main_clear_tissue(void);
445 void main_calc_percentage(void);
446 void main_calc_wo_deco_step_1_min(void);
447 void main_debug(void);
448 void main_gradient_array(void);
449 void main_hash(void);
450
451 void calc_hauptroutine(void);
452 void calc_tissue(void);
453 void calc_nullzeit(void);
454 void backup_sim_pres_tissue(void);
455 void restore_sim_pres_tissue(void);
456
457 void calc_without_deco(void);
458 void clear_tissue(void);
459 void calc_ascenttime(void);
460 void update_startvalues(void);
461 void clear_decoarray(void);
462 void update_decoarray(void);
463 void sim_tissue_1min(void);
464 void sim_tissue_10min(void);
465 void calc_gradient_factor(void);
466 void calc_gradient_array_only(void);
467 void calc_desaturation_time(void);
468 void calc_wo_deco_step_1_min(void);
469 void calc_tissue_step_1_min(void);
470 void hash(void);
471 void clear_CNS_fraction(void);
472 void calc_CNS_fraction(void);
473 void calc_CNS_decrease_15min(void);
474 void calc_percentage(void);
475 void main(void);
476 void calc_hauptroutine_data_input(void);
477 void calc_hauptroutine_update_tissues(void);
478 void calc_hauptroutine_calc_deco(void);
479 void calc_hauptroutine_calc_ascend_to_deco(void);
480 void calc_nextdecodepth_GF(void);
481 void copy_deco_table_GF(void);
482 void clear_internal_deco_table_GF(void);
483 void update_internal_deco_table_GF(void);
484 void push_tissues_to_vault(void);
485 void pull_tissues_from_vault(void);
486 void main_push_tissues_to_vault(void);
487 void main_pull_tissues_from_vault(void);
488 void wordprocessor(void);
489
490 // *******************************
491 // ** start **
492 // ** necessary for compilation **
493 // *******************************
494 #pragma romdata der_code = 0x0000
495 #pragma code der_start = 0x0000
496 void der_start(void)
497 {
498 _asm
499 goto main
500 _endasm
501 }
502
503 // ***********************************
504 // ** main code for simulation / **
505 // ** tests without assembler code **
506 // ** is NOT a part of the OSTC **
507 // ***********************************
508 #pragma code main = 0x9000
509 void main(void)
510 {
511 for(wp_temp_U8=0;wp_temp_U8<LENGTH_kf_bank0 - 1;wp_temp_U8++)
512 keep_free_bank0[wp_temp_U8] = 7;
513 keep_free_bank0[LENGTH_kf_bank0 - 1] = 7;
514
515 for(wp_temp_U8=0;wp_temp_U8<LENGTH_kf_bank1 - 1;wp_temp_U8++)
516 keep_free_bank1[wp_temp_U8] = 7;
517 keep_free_bank1[LENGTH_kf_bank1 - 1] = 7;
518
519 #if 1
520 // new main to test DR-5
521
522 wp_top = 10;
523 wp_leftx2 = 10;
524 wp_color1 = 255;
525 wp_color2 = 255;
526 wp_font = 0;
527 wp_invert = 0;
528 wp_stringstore[0] = ' ';
529 wp_stringstore[1] = '!';
530 wp_stringstore[2] = '"';
531 wp_stringstore[3] = ':';
532 wp_stringstore[4] = 0;
533 wordprocessor();
534
535 GF_low = 1.0;
536 GF_high = 1.0;
537
538 GF_temp = GF_low * GF_high;
539
540 clear_CNS_fraction();
541 //char_I_const_ppO2 = 100;
542 //for (main_i=0;main_i<255;main_i++)
543 //{
544 //calc_CNS_fraction();
545 //} //for
546
547
548
549
550 int_I_pres_respiration = 1000;//980;
551 int_I_pres_surface = 1000;//980;
552 char_I_N2_ratio = 39; //38;
553 char_I_He_ratio = 40; //50;
554 char_I_deco_distance = 0; // 10 = 1 meter
555 char_I_depth_last_deco = 3; // values below 3 (meter) are ignored
556
557 char_I_const_ppO2 = 0;
558 char_I_deco_ppO2_change = 0; // [dm] 10 = 1 meter
559 char_I_deco_ppO2 = 0;
560
561 char_I_deco_gas_change = 0; // [m] 1 = 1 meter
562 char_I_deco_N2_ratio = 0;
563 char_I_deco_He_ratio = 0;
564
565 //char_I_actual_ppO2; // 0x507
566 char_I_GF_High_percentage = 100; // 0x514 new in v.102
567 char_I_GF_Low_percentage = 100; // 0x515 new in v.102
568
569 char_I_saturation_multiplier = 110;
570 char_I_desaturation_multiplier = 90;
571
572 char_I_deco_model = 0;
573
574 main_clear_tissue();
575
576 int_I_pres_respiration = 1000 + int_I_pres_surface;
577 main_calc_wo_deco_step_1_min();
578 int_I_pres_respiration = 3000 + int_I_pres_surface;
579 main_calc_wo_deco_step_1_min();
580 int_I_pres_respiration = 5000 + int_I_pres_surface;
581 main_calc_wo_deco_step_1_min();
582
583 /*
584 int_I_pres_respiration = 6000 + int_I_pres_surface;
585 for (main_i=0;main_i<27;main_i++)
586 main_calc_wo_deco_step_1_min();
587 */
588
589 char_O_deco_status = 255;
590 while (char_O_deco_status)
591 main_calc_hauptroutine();
592 _asm
593 nop
594 _endasm
595
596 for (main_i=0;main_i<50;main_i++)
597 {
598 main_calc_hauptroutine();
599 }
600 int_I_pres_respiration = 10000;
601 for (main_i=0;main_i<1500;main_i++)
602 {
603 main_calc_hauptroutine();
604 }
605
606 _asm
607 nop
608 _endasm
609
610
611 int_I_pres_respiration = 3000;
612 for (main_i=0;main_i<150;main_i++)
613 {
614 calc_hauptroutine_data_input();
615 calc_hauptroutine_update_tissues();
616 } //for
617
618 update_startvalues();
619 clear_decoarray();
620 clear_internal_deco_table_GF();
621 calc_hauptroutine_calc_ascend_to_deco();
622 if (char_O_deco_status > 15) // can't go up to first deco, too deep to calculate in the given time slot
623 {
624 char_O_deco_status = 2;
625 // char_O_lock_depth_list = 255;
626 }
627 else
628 {
629 // char_O_lock_depth_list = lock_GF_depth_list;
630 calc_hauptroutine_calc_deco();
631 }
632 // build_debug_output();
633
634 _asm
635 nop
636 _endasm
637 while (char_O_deco_status == 1)
638 {
639 char_O_deco_status = 0;
640 // char_O_lock_depth_list = 255;
641 calc_hauptroutine_calc_deco();
642 // build_debug_output();
643 _asm
644 nop
645 _endasm
646 };
647 debug_temp = 60; // [mtr Aufstieg in 10 mtr/min (30steps'2sec/min]
648 int_I_pres_respiration = 9980;
649 for (main_i=0;main_i<debug_temp;main_i++)
650 {
651 int_I_pres_respiration = int_I_pres_respiration - 33;
652 calc_hauptroutine_data_input();
653 calc_hauptroutine_update_tissues();
654 int_I_pres_respiration = int_I_pres_respiration - 33;
655 calc_hauptroutine_data_input();
656 calc_hauptroutine_update_tissues();
657 int_I_pres_respiration = int_I_pres_respiration - 34;
658 calc_hauptroutine_data_input();
659 calc_hauptroutine_update_tissues();
660 } //for
661 _asm
662 nop
663 _endasm
664
665 update_startvalues();
666 clear_decoarray();
667 clear_internal_deco_table_GF();
668 calc_hauptroutine_calc_ascend_to_deco();
669 if (char_O_deco_status > 15) // can't go up to first deco, too deep to calculate in the given time slot
670 {
671 char_O_deco_status = 2;
672 // char_O_lock_depth_list = 255;
673 }
674 else
675 {
676 // char_O_lock_depth_list = lock_GF_depth_list;
677 calc_hauptroutine_calc_deco();
678 }
679 // build_debug_output();
680
681 _asm
682 nop
683 _endasm
684 while (char_O_deco_status == 1)
685 {
686 char_O_deco_status = 0;
687 // char_O_lock_depth_list = 255;
688 calc_hauptroutine_calc_deco();
689 // build_debug_output();
690 _asm
691 nop
692 _endasm
693 };
694 _asm
695 nop
696 _endasm
697 debug_temp = 60; // [mtr Aufstieg in 10 mtr/min (30steps'2sec/min]
698 int_I_pres_respiration = 9980;
699 debug_temp = debug_temp * 3;
700 for (main_i=0;main_i<debug_temp;main_i++)
701 {
702 calc_hauptroutine_data_input();
703 calc_hauptroutine_update_tissues();
704 } //for
705 _asm
706 nop
707 _endasm
708 #endif
709 // -----------------------
710
711 } // main
712
713 // ******************************************************
714 // ******************************************************
715 // ** THE FOLLOWING CODE HAS TO BE COPPIED TO THE OSTC **
716 // ******************************************************
717 // ******************************************************
718
719 // ***************
720 // ***************
721 // ** THE FONTS **
722 // ***************
723 // ***************
724 // all new for bigscreen
725
726 // a bit is left (C4)
727 #pragma romdata font_data_small = 0x0A0C4
728 rom const rom U16 wp_small_data[] =
729 {
730 #include "ostc28.drx.txt"
731 };
732
733 #pragma romdata font_table_small = 0x0B548
734 rom const rom U16 wp_small_table[] =
735 {
736 #include "ostc28.tbl.txt" // length 0xEC
737 };
738
739 #pragma romdata font_table_medium = 0x0B632
740 rom const rom U16 wp_medium_table[] =
741 {
742 #include "ostc48.tbl.txt" // length 0x22
743 };
744
745 #pragma romdata font_data_medium = 0x0B656
746 rom const rom U16 wp_medium_data[] =
747 {
748 #include "ostc48.drx.txt" // length 0x390
749 };
750
751 #pragma romdata font_data_large = 0x0BA46
752 rom const rom U16 wp_large_data[] =
753 {
754 #include "ostc90.drx.txt"
755 };
756
757 #pragma romdata font_table_large = 0x0BFE6
758 rom const rom U16 wp_large_table[] =
759 {
760 #include "ostc90.tbl.txt"
761 };
762
763 // ***********************
764 // ***********************
765 // ** THE SUBROUTINES 2 **
766 // ***********************
767 // ***********************
768 // all new in v.102
769 // moved from 0x0D000 to 0x0C000 in v.108
770
771 #pragma code subroutines2 = 0x0C000 // can be adapted to fit the romdata tables ahead
772
773 // -------------------------------
774 // DBS - debug on start of dive //
775 // -------------------------------
776 void create_dbs_set_dbg_and_ndl20mtr(void)
777 {
778 int_O_DBS_bitfield = 0;
779 int_O_DBS2_bitfield = 0;
780 if(int_O_DBG_pre_bitfield & DBG_RUN)
781 int_O_DBG_pre_bitfield = DBG_RESTART;
782 else
783 int_O_DBG_pre_bitfield = DBG_RUN;
784 int_O_DBG_post_bitfield = 0;
785 char_O_NDL_at_20mtr = 255;
786
787 DBG_N2_ratio = N2_ratio;
788 DBG_He_ratio = He_ratio;
789 DBG_char_I_deco_model = char_I_deco_model;
790 DBG_char_I_depth_last_deco = char_I_depth_last_deco;
791 DBG_pres_surface = pres_surface;
792 DBG_GF_low = GF_low;
793 DBG_GF_high = GF_high;
794 DBG_const_ppO2 = const_ppO2;
795 DBG_deco_ppO2_change = deco_ppO2_change;
796 DBG_deco_ppO2 = deco_ppO2;
797 DBG_deco_N2_ratio = deco_N2_ratio;
798 DBG_deco_He_ratio = deco_He_ratio;
799 DBG_deco_gas_change = deco_gas_change;
800 DBG_float_saturation_multiplier = float_saturation_multiplier;
801 DBG_float_desaturation_multiplier = float_desaturation_multiplier;
802 DBG_float_deco_distance = float_deco_distance;
803
804 if(char_I_deco_model)
805 int_O_DBS_bitfield |= DBS_mode;
806 if(const_ppO2)
807 int_O_DBS_bitfield |= DBS_ppO2;
808 for(int_dbg_i = 16; int_dbg_i < 32; int_dbg_i++)
809 if(pres_tissue[int_dbg_i])
810 int_O_DBS_bitfield |= DBS_HE_sat;
811 if(deco_ppO2_change)
812 int_O_DBS_bitfield |= DBS_ppO2chg;
813 if(float_saturation_multiplier < 0.99)
814 int_O_DBS_bitfield |= DBS_SAT2l;
815 if(float_saturation_multiplier > 1.3)
816 int_O_DBS_bitfield |= DBS_SAT2h;
817 if(GF_low < 0.19)
818 int_O_DBS_bitfield |= DBS_GFLOW2l;
819 if(GF_low > 1.01)
820 int_O_DBS_bitfield |= DBS_GFLOW2h;
821 if(GF_high < 0.6)
822 int_O_DBS_bitfield |= DBS_GFHGH2l;
823 if(GF_high > 1.01)
824 int_O_DBS_bitfield |= DBS_GFHGH2h;
825 if((N2_ratio + He_ratio) > 0.95)
826 int_O_DBS_bitfield |= DBS_GASO22l;
827 if((N2_ratio + He_ratio) < 0.05)
828 int_O_DBS_bitfield |= DBS_GASO22h;
829 if(float_deco_distance > 0.25)
830 int_O_DBS_bitfield |= DBS_DIST2h;
831 if(char_I_depth_last_deco > 8)
832 int_O_DBS_bitfield |= DBS_LAST2h;
833 if(DBG_deco_gas_change && ((deco_N2_ratio + deco_He_ratio) > 0.95))
834 int_O_DBS_bitfield |= DBS_DECOO2l;
835 if(DBG_deco_gas_change && ((deco_N2_ratio + deco_He_ratio) < 0.05))
836 int_O_DBS_bitfield |= DBS_DECOO2h;
837 if(pres_respiration > 3.0)
838 int_O_DBS2_bitfield |= DBS2_PRES2h;
839 if(pres_surface - pres_respiration > 0.2)
840 int_O_DBS2_bitfield |= DBS2_PRES2l;
841 if(pres_surface < 0.75)
842 int_O_DBS2_bitfield |= DBS2_SURF2l;
843 if(pres_surface > 1.11)
844 int_O_DBS2_bitfield |= DBS2_SURF2h;
845 if(float_desaturation_multiplier < 0.70)
846 int_O_DBS2_bitfield |= DBS2_DESAT2l;
847 if(float_desaturation_multiplier > 1.01)
848 int_O_DBS2_bitfield |= DBS2_DESAT2h;
849 if(GF_low > GF_high)
850 int_O_DBS2_bitfield |= DBS2_GFDneg;
851 }
852
853 // -------------------------------
854 // DBG - set DBG to end_of_dive //
855 // -------------------------------
856 void set_dbg_end_of_dive(void)
857 {
858 int_O_DBG_pre_bitfield &= (~DBG_RUN);
859 int_O_DBG_post_bitfield &= (~DBG_RUN);
860 }
861
862 // -------------------------------
863 // DBG - NDL at first 20 m. hit //
864 // -------------------------------
865 void check_ndl(void)
866 {
867 if((char_O_NDL_at_20mtr == -1) && (int_I_pres_respiration > 3000))
868 {
869 char_O_NDL_at_20mtr = char_O_nullzeit;
870 if(char_O_NDL_at_20mtr == 255)
871 char_O_NDL_at_20mtr == 254;
872 }
873 }
874
875 // -------------------------------
876 // DBG - multi main during dive //
877 // -------------------------------
878 void check_dbg(char is_post_check)
879 {
880 temp_DBS = 0;
881 if( (DBG_N2_ratio != N2_ratio) || (DBG_He_ratio != He_ratio) )
882 temp_DBS |= DBG_c_gas;
883 if(DBG_const_ppO2 != const_ppO2)
884 temp_DBS |= DBG_c_ppO2;
885 if((DBG_float_saturation_multiplier != float_saturation_multiplier) || (DBG_float_desaturation_multiplier != float_desaturation_multiplier))
886 temp_DBS |= DBG_CdeSAT;
887 if(DBG_char_I_deco_model != char_I_deco_model)
888 temp_DBS |= DBG_C_MODE;
889 if(DBG_pres_surface != pres_surface)
890 temp_DBS |= DBG_C_SURF;
891 if((!DBS_HE_sat) && (!He_ratio))
892 for(int_dbg_i = 16; int_dbg_i < 32; int_dbg_i++)
893 if(pres_tissue[int_dbg_i])
894 temp_DBS |= DBG_HEwoHE;
895 if(DBG_deco_ppO2 != deco_ppO2)
896 temp_DBS |= DBG_C_DPPO2;
897 if((DBG_deco_gas_change != deco_gas_change) || (DBG_deco_N2_ratio != deco_N2_ratio) || (DBG_deco_He_ratio != deco_He_ratio))
898 temp_DBS |= DBG_C_DGAS;
899 if(DBG_float_deco_distance != float_deco_distance)
900 temp_DBS |= DBG_C_DIST;
901 if(DBG_char_I_depth_last_deco != char_I_depth_last_deco)
902 temp_DBS |= DBG_C_LAST;
903 if((DBG_GF_low != GF_low) || (DBG_GF_high != GF_high))
904 temp_DBS |= DBG_C_GF;
905 if(pres_respiration > 13.0)
906 temp_DBS |= DBG_PHIGH;
907 if(pres_surface - pres_respiration > 0.2)
908 temp_DBS |= DBG_PLOW;
909 /*
910 if()
911 temp_DBS |= ;
912 if()
913 temp_DBS |= ;
914 */
915 if(is_post_check)
916 int_O_DBG_post_bitfield |= temp_DBS;
917 else
918 int_O_DBG_pre_bitfield |= temp_DBS;
919 }
920
921 // -------------------------------
922 // DBG - prior to calc. of dive //
923 // -------------------------------
924 void check_pre_dbg(void)
925 {
926 check_dbg(0);
927 }
928
929 // -------------------------------
930 // DBG - after decocalc of dive //
931 // -------------------------------
932 void check_post_dbg(void)
933 {
934 check_dbg(1);
935 }
936
937
938
939 // -------------------------
940 // calc_next_decodepth_GF //
941 // -------------------------
942 // new in v.102
943 void calc_nextdecodepth_GF(void)
944 {
945 // INPUT, changing during dive:
946 // temp_pres_gtissue_limit_GF_low
947 // temp_pres_gtissue_limit_GF_low_below_surface
948 // temp_pres_gtissue
949 // temp_pres_gtissue_diff
950 // lock_GF_depth_list
951
952 // INPUT, fixed during dive:
953 // pres_surface
954 // GF_delta
955 // GF_high
956 // GF_low
957 // temp_depth_last_deco
958 // float_deco_distance
959
960 // OUTPUT
961 // GF_step
962 // temp_deco
963 // temp_depth_limt
964 // lock_GF_depth_list
965
966 // USES
967 // temp1
968 // temp2
969 // int_temp
970
971 char_I_table_deco_done[0] = 0; // safety if changed somewhere else. Needed for exit
972 if (char_I_deco_model == 1)
973 {
974 if (lock_GF_depth_list == 0)
975 {
976 temp2 = temp_pres_gtissue_limit_GF_low_below_surface / 0.29985; // = ... / 99.95 / 0.003;
977 int_temp = (int) (temp2 + 0.99);
978 if (int_temp > 31)
979 int_temp = 31; // deepest deco at 93 meter (31 deco stops)
980 if (int_temp < 0)
981 int_temp = 0;
982 temp_depth_GF_low_number = int_temp;
983 temp_depth_GF_low_meter = 3 * temp_depth_GF_low_number;
984 temp2 = (float)temp_depth_GF_low_meter * 0.09995;
985 temp_pres_deco_GF_low = temp2 + float_deco_distance + pres_surface;
986 if (temp_depth_GF_low_number == 0)
987 GF_step = 0;
988 else
989 GF_step = GF_delta / (float)temp_depth_GF_low_number;
990 if (GF_step < 0)
991 GF_step = 0;
992 if (GF_step > GF_delta)
993 GF_step = GF_delta;
994 int_O_GF_step = (int)(GF_step * 10000);
995 int_O_limit_GF_low = (int)(temp_pres_deco_GF_low * 1000);
996 int_O_gtissue_press_at_GF_low = (int)(temp_pres_gtissue * 1000);
997 char_O_GF_low_pointer = temp_depth_GF_low_number;
998 lock_GF_depth_list = 1;
999 internal_deco_pointer = 0;
1000 }
1001 if (internal_deco_pointer == 0) // new run
1002 {
1003 internal_deco_pointer = temp_depth_GF_low_number;
1004 GF_temp = GF_high - ((float)internal_deco_pointer * GF_step);
1005 int_temp = char_I_table_deco_done[internal_deco_pointer];
1006 output[8] = int_temp;
1007 output[9] = 33;
1008 }
1009 else
1010 {
1011 int_temp = 1;
1012 }
1013 while (int_temp == 1)
1014 {
1015 int_temp = internal_deco_pointer - 1;
1016 if (int_temp == 1) // new in v104
1017 {
1018 temp2 = (float)(temp_depth_last_deco * int_temp) * 0.09995;
1019 GF_step2 = GF_step/3.0 * ((float)(6 - temp_depth_last_deco));
1020 }
1021 else
1022 if (int_temp == 0)
1023 {
1024 temp2 = 0.0;
1025 GF_step2 = GF_high - GF_temp;
1026 }
1027 else
1028 {
1029 temp2 = (float)(3 *int_temp) * 0.09995;
1030 GF_step2 = GF_step;
1031 }
1032 temp2 = temp2 + pres_surface; // next deco stop to be tested
1033 temp1 = ((GF_temp + GF_step2)* temp_pres_gtissue_diff) + temp_pres_gtissue; // upper limit (lowest pressure allowed) // changes GF_step2 in v104
1034 if (temp1 > temp2) // check if ascent to next deco stop is ok
1035 {
1036 int_temp = 0; // no
1037 }
1038 else
1039 {
1040 internal_deco_pointer = int_temp;
1041 GF_temp = GF_temp + GF_step2; // changed in v104
1042 int_temp = char_I_table_deco_done[internal_deco_pointer]; // yes and check for ascent to even next stop if deco_done is set
1043 }
1044 } // while
1045 if (internal_deco_pointer > 0)
1046 {
1047 temp2 = (float)(0.29985 * internal_deco_pointer);
1048 temp_deco = temp2 + float_deco_distance + pres_surface;
1049 if (internal_deco_pointer == 1) // new in v104
1050 temp_depth_limit = temp_depth_last_deco;
1051 else
1052 temp_depth_limit = 3 * internal_deco_pointer;
1053 if (output[9] == 33)
1054 {
1055 output[9] = internal_deco_pointer;
1056 output[10] = char_I_table_deco_done[internal_deco_pointer];
1057 output[12] = output[12] + 1;
1058 if (output[12] == 100)
1059 output[12] = 0;
1060 }
1061 }
1062 else // if (char_I_deco_model == 1)
1063 {
1064 temp_deco = pres_surface;
1065 temp_depth_limit = 0;
1066 }
1067 }
1068 else
1069 {
1070 // calc_nextdecodepth - original
1071 // optimized in v.101
1072 // depth_last_deco included in v.101
1073
1074 temp1 = temp_pres_gtissue_limit - pres_surface;
1075 if (temp1 >= 0)
1076 {
1077 temp1 = temp1 / 0.29985; // = temp1 / 99.95 / 0.003;
1078 temp_depth_limit = (int) (temp1 + 0.99);
1079 temp_depth_limit = 3 * temp_depth_limit; // depth for deco [m]
1080 if (temp_depth_limit == 0)
1081 temp_deco = pres_surface;
1082 else
1083 {
1084 if (temp_depth_limit < temp_depth_last_deco)
1085 temp_depth_limit = temp_depth_last_deco;
1086 temp1 = (float)temp_depth_limit * 0.09995;
1087 temp_deco = temp1 + float_deco_distance + pres_surface; // depth for deco [bar]
1088 } // if (temp_depth_limit == 0)
1089 } // if (temp1 >= 0)
1090 else
1091 {
1092 temp_deco = pres_surface;
1093 temp_depth_limit = 0;
1094 } // if (temp1 >= 0)
1095 } // calc_nextdecodepth original
1096 } // calc_nextdecodepth_GF
1097
1098
1099 #if 0
1100 void build_debug_output(void)
1101 {
1102 output[0] = 0; // not used in asm PLED output
1103 output[1] = (int) (GF_low * 100);
1104 output[2] = (int) (GF_high * 100);
1105 output[3] = (int) (GF_step * 100);
1106 output[4] = (int) temp_depth_GF_low_number;
1107 output[5] = (int) temp_depth_GF_low_meter;
1108 //output[6]
1109 output[7] = (int) internal_deco_pointer;
1110 //output[8] = char_I_table_deco_done[temp_depth_GF_low_number]
1111 //output[9] = internal_deco_pointer @ new run
1112 //output[10] = char_I_table_deco_done[internal_deco_pointer] @ new run
1113 output [11] = (int) (temp_pres_deco_GF_low * 10);
1114 } // build_debug_output
1115 #endif
1116
1117 // ---------------------
1118 // copy_deco_table_GF //
1119 // ---------------------
1120 // new in v.102
1121 void copy_deco_table_GF(void)
1122 {
1123 if (char_I_deco_model == 1)
1124 {
1125 int_temp = 32;
1126 for (ci=0;ci<int_temp;ci++)
1127 char_O_deco_table[ci] = internal_deco_table[ci];
1128 }
1129 } // copy_deco_table_GF
1130
1131
1132 // ------------------------------
1133 // clear_internal_deco_table_GF//
1134 // ------------------------------
1135 // new in v.102
1136 void clear_internal_deco_table_GF(void)
1137 {
1138 if (char_I_deco_model == 1)
1139 {
1140 for (ci=0;ci<32;ci++) // cycle through the 16 b"uhlmann tissues for Helium
1141 {
1142 internal_deco_table[ci] = 0;
1143 }
1144 }
1145 } // clear_internal_deco_table_GF
1146
1147
1148 // --------------------------------
1149 // update_internal_deco_table_GF //
1150 // --------------------------------
1151 // new in v.102
1152 void update_internal_deco_table_GF(void)
1153 {
1154 if ((char_I_deco_model == 1) && (internal_deco_table[internal_deco_pointer] < 255))
1155 internal_deco_table[internal_deco_pointer] = internal_deco_table[internal_deco_pointer] + 1;
1156 } // update_internal_deco_table_GF
1157
1158
1159 // ---------------------
1160 // temp_tissue_safety //
1161 // ---------------------
1162 // outsourced in v.102
1163 void temp_tissue_safety(void)
1164 {
1165 if (char_I_deco_model == 1)
1166 {
1167 }
1168 else
1169 {
1170 if (temp_tissue < 0.0)
1171 temp_tissue = temp_tissue * float_desaturation_multiplier;
1172 else
1173 temp_tissue = temp_tissue * float_saturation_multiplier;
1174 }
1175 } // temp_tissue_safety
1176
1177
1178 // **********************
1179 // **********************
1180 // ** THE JUMP-IN CODE **
1181 // ** for the asm code **
1182 // **********************
1183 // **********************
1184 #pragma code main_calc_hauptroutine = 0x10000
1185 void main_calc_hauptroutine(void)
1186 {
1187 calc_hauptroutine();
1188 int_O_desaturation_time = 65535;
1189 } // divemode
1190 #pragma code main_without_deco = 0x10020
1191 void main_calc_without_deco(void)
1192 {
1193 calc_without_deco();
1194 calc_desaturation_time();
1195 }
1196
1197 #pragma code main_clear_CNS_fraction = 0x10030
1198 void main_clear_CNS_fraction(void)
1199 {
1200 clear_CNS_fraction();
1201 }
1202
1203 #pragma code main_calc_CNS_decrease_15min = 0x10034
1204 void main_calc_CNS_decrease_15min(void)
1205 {
1206 calc_CNS_decrease_15min();
1207 }
1208
1209 #pragma code main_calc_percentage = 0x10038
1210 void main_calc_percentage (void)
1211 {
1212 calc_percentage();
1213 }
1214
1215 #pragma code main_clear_tissue = 0x10040
1216 void main_clear_tissue(void)
1217 {
1218 clear_tissue();
1219 char_I_depth_last_deco = 0; // for compatibility with v.101pre_no_last_deco
1220 }
1221
1222 #pragma code main_calc_CNS_fraction = 0x10050
1223 void main_calc_CNS_fraction(void)
1224 {
1225 calc_CNS_fraction();
1226 }
1227
1228 #pragma code main_calc_desaturation_time = 0x10060
1229 void main_calc_desaturation_time(void)
1230 {
1231 calc_desaturation_time();
1232 }
1233
1234 #pragma code main_calc_wo_deco_step_1_min = 0x10080
1235 void main_calc_wo_deco_step_1_min(void)
1236 {
1237 calc_wo_deco_step_1_min();
1238 char_O_deco_status = 3; // surface new in v.102 overwrites value of calc_wo_deco_step_1_min
1239 calc_desaturation_time();
1240 } // surface mode
1241
1242 #pragma code main_debug = 0x100A0
1243 void main_debug(void)
1244 {
1245 //debug();
1246 }
1247
1248 #pragma code main_DD2_write_incon42 = 0x100B0
1249 void main_DD2_write_incon42(void)
1250 {
1251 return;
1252 }
1253
1254 #pragma code main_DD2_write_incon24 = 0x100B4
1255 void main_DD2_write_incon24(void)
1256 {
1257 return;
1258 }
1259
1260 #pragma code main_wordprocessor = 0x100B8
1261 void main_wordprocessor(void)
1262 {
1263 wordprocessor();
1264 }
1265
1266 #pragma code main_gradient_array = 0x100C0
1267 void main_gradient_array(void)
1268 {
1269 calc_gradient_array_only();
1270 }
1271 #pragma code main_push_tissues = 0x100C4
1272 void main_push_tissues_to_vault(void)
1273 {
1274 push_tissues_to_vault();
1275 }
1276 #pragma code main_pull_tissues = 0x100C8
1277 void main_pull_tissues_from_vault(void)
1278 {
1279 pull_tissues_from_vault();
1280 }
1281
1282 #pragma code main_hash = 0x100E0
1283 void main_hash(void)
1284 {
1285 hash();
1286 }
1287
1288 // ***********************
1289 // ***********************
1290 // ** THE LOOKUP TABLES **
1291 // ***********************
1292 // ***********************
1293
1294 #pragma romdata tables = 0x10200
1295 #include <p2_tables.romdata> // new table for deco_main_v.101 (var_a modified)
1296
1297 #pragma romdata tables2 = 0x10600
1298 rom const rom unsigned int md_pi[] =
1299 {
1300 0x292E, 0x43C9, 0xA2D8, 0x7C01, 0x3D36, 0x54A1, 0xECF0, 0x0613
1301 , 0x62A7, 0x05F3, 0xC0C7, 0x738C, 0x9893, 0x2BD9, 0xBC4C, 0x82CA
1302 , 0x1E9B, 0x573C, 0xFDD4, 0xE016, 0x6742, 0x6F18, 0x8A17, 0xE512
1303 , 0xBE4E, 0xC4D6, 0xDA9E, 0xDE49, 0xA0FB, 0xF58E, 0xBB2F, 0xEE7A
1304 , 0xA968, 0x7991, 0x15B2, 0x073F, 0x94C2, 0x1089, 0x0B22, 0x5F21
1305 , 0x807F, 0x5D9A, 0x5A90, 0x3227, 0x353E, 0xCCE7, 0xBFF7, 0x9703
1306 , 0xFF19, 0x30B3, 0x48A5, 0xB5D1, 0xD75E, 0x922A, 0xAC56, 0xAAC6
1307 , 0x4FB8, 0x38D2, 0x96A4, 0x7DB6, 0x76FC, 0x6BE2, 0x9C74, 0x04F1
1308 , 0x459D, 0x7059, 0x6471, 0x8720, 0x865B, 0xCF65, 0xE62D, 0xA802
1309 , 0x1B60, 0x25AD, 0xAEB0, 0xB9F6, 0x1C46, 0x6169, 0x3440, 0x7E0F
1310 , 0x5547, 0xA323, 0xDD51, 0xAF3A, 0xC35C, 0xF9CE, 0xBAC5, 0xEA26
1311 , 0x2C53, 0x0D6E, 0x8528, 0x8409, 0xD3DF, 0xCDF4, 0x4181, 0x4D52
1312 , 0x6ADC, 0x37C8, 0x6CC1, 0xABFA, 0x24E1, 0x7B08, 0x0CBD, 0xB14A
1313 , 0x7888, 0x958B, 0xE363, 0xE86D, 0xE9CB, 0xD5FE, 0x3B00, 0x1D39
1314 , 0xF2EF, 0xB70E, 0x6658, 0xD0E4, 0xA677, 0x72F8, 0xEB75, 0x4B0A
1315 , 0x3144, 0x50B4, 0x8FED, 0x1F1A, 0xDB99, 0x8D33, 0x9F11, 0x8314
1316 };
1317
1318 // *********************
1319 // *********************
1320 // ** THE SUBROUTINES **
1321 // *********************
1322 // *********************
1323
1324 #pragma code subroutines = 0x10700 // can be adapted to fit the romdata tables ahead
1325
1326
1327 // ---------------
1328 // CLEAR tissue //
1329 // ---------------
1330 // optimized in v.101 (var_a)
1331
1332 void clear_tissue(void) // preload tissues with standard pressure for the given ambient pressure
1333 {
1334
1335 flag_in_divemode = 0;
1336 int_O_DBS_bitfield = 0;
1337 int_O_DBS2_bitfield = 0;
1338 int_O_DBG_pre_bitfield = 0;
1339 int_O_DBG_post_bitfield = 0;
1340 char_O_NDL_at_20mtr = 255;
1341
1342 _asm
1343 lfsr 1, 0x300 // C math routines shall use this variable bank
1344 movlw 0x01
1345 movwf TBLPTRU,0
1346 _endasm
1347
1348 // N2_ratio = (float)char_I_N2_ratio; // the 0.0002 of 0.7902 are missing with standard air
1349 N2_ratio = 0.7902; // N2_ratio / 100.0;
1350 pres_respiration = (float)int_I_pres_respiration / 1000.0;
1351 for (ci=0;ci<16;ci++) // cycle through the 16 b"uhlmann tissues
1352 {
1353 pres_tissue[ci] = N2_ratio * (pres_respiration - 0.0627) ;
1354 _asm
1355 movlw 0x02
1356 movwf TBLPTRH,0
1357 movlb 4 // fuer ci
1358 movf ci,0,1
1359 addwf ci,0,1
1360 addwf ci,0,1
1361 addwf ci,0,1
1362 addlw 0x80
1363 movwf TBLPTRL,0
1364 TBLRDPOSTINC
1365 movff TABLAT,var_a+1
1366 TBLRDPOSTINC
1367 movff TABLAT,var_a
1368 TBLRDPOSTINC
1369 movff TABLAT,var_a+3
1370 TBLRD
1371 movff TABLAT,var_a+2
1372 addlw 0x80
1373 movwf TBLPTRL,0
1374 incf TBLPTRH,1,0
1375 TBLRDPOSTINC
1376 movff TABLAT,var_b+1
1377 TBLRDPOSTINC
1378 movff TABLAT,var_b
1379 TBLRDPOSTINC
1380 movff TABLAT,var_b+3
1381 TBLRD
1382 movff TABLAT,var_b+2
1383 _endasm
1384
1385 pres_tissue_limit[ci] = (pres_tissue[ci] - var_a) * var_b ;
1386 // now update the guiding tissue
1387 if (pres_tissue_limit[ci] < 0)
1388 pres_tissue_limit[ci] = 0;
1389 } // for 0 to 16
1390
1391 for (ci=16;ci<32;ci++) // cycle through the 16 b"uhlmann tissues for Helium
1392 {
1393 pres_tissue[ci] = 0.0;
1394 } // for
1395
1396 clear_decoarray();
1397 char_O_deco_status = 0;
1398 char_O_nullzeit = 0;
1399 char_O_ascenttime = 0;
1400 char_O_gradient_factor = 0;
1401 char_O_relative_gradient_GF = 0;
1402 } // clear_tissue(void)
1403
1404
1405 // --------------------
1406 // calc_without_deco //
1407 // fixed N2_ratio ! //
1408 // --------------------
1409 // optimized in v.101 (float_..saturation_multiplier)
1410
1411 void calc_without_deco(void)
1412 {
1413 _asm
1414 lfsr 1, 0x300
1415 _endasm
1416 N2_ratio = 0.7902; // FIXED RATIO !! sum as stated in b"uhlmann
1417 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system
1418 pres_surface = (float)int_I_pres_surface / 1000.0;
1419 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body
1420 temp2_atem = 0.0;
1421 temp_surface = pres_surface; // the b"uhlmann formula using temp_surface does apply to the pressure without any inert ratio
1422 float_desaturation_multiplier = char_I_desaturation_multiplier / 100.0;
1423 float_saturation_multiplier = char_I_saturation_multiplier / 100.0;
1424
1425 calc_tissue(); // update the pressure in the 16 tissues in accordance with the new ambient pressure
1426
1427 clear_decoarray();
1428 char_O_deco_status = 0;
1429 char_O_nullzeit = 0;
1430 char_O_ascenttime = 0;
1431 calc_gradient_factor();
1432
1433 } // calc_without_deco
1434
1435
1436 // --------------------
1437 // calc_hauptroutine //
1438 // --------------------
1439 // this is the major code in dive mode
1440 // calculates:
1441 // the tissues,
1442 // the bottom time
1443 // and simulates the ascend with all deco stops
1444
1445 void calc_hauptroutine(void)
1446 {
1447 calc_hauptroutine_data_input();
1448
1449 if(!flag_in_divemode)
1450 {
1451 flag_in_divemode = 1;
1452 create_dbs_set_dbg_and_ndl20mtr();
1453 }
1454 else
1455 check_pre_dbg();
1456
1457 calc_hauptroutine_update_tissues();
1458 calc_gradient_factor();
1459
1460
1461 switch (char_O_deco_status) // toggle between calculation for nullzeit (bottom time), deco stops and more deco stops (continue)
1462 {
1463 case 0:
1464 update_startvalues();
1465 calc_nullzeit();
1466 check_ndl();
1467 char_O_deco_status = 255; // calc deco next time
1468 break;
1469 case 1:
1470 if (char_O_deco_status == 3)
1471 break;
1472 char_O_deco_status = 0;
1473 // char_O_lock_depth_list = 255;
1474 calc_hauptroutine_calc_deco();
1475 // build_debug_output();
1476 break;
1477 case 3: // new dive
1478 clear_decoarray();
1479 clear_internal_deco_table_GF();
1480 copy_deco_table_GF();
1481 internal_deco_pointer = 0;
1482 lock_GF_depth_list = 0;
1483 update_startvalues();
1484 calc_nextdecodepth_GF();
1485 char_O_deco_status = 0;
1486 break;
1487 default:
1488 update_startvalues();
1489 clear_decoarray();
1490 clear_internal_deco_table_GF();
1491 output[6] = 1;
1492 calc_hauptroutine_calc_ascend_to_deco();
1493 if (char_O_deco_status > 15) // can't go up to first deco, too deep to calculate in the given time slot
1494 {
1495 char_O_deco_status = 2;
1496 // char_O_lock_depth_list = 255;
1497 }
1498 else
1499 {
1500 // char_O_lock_depth_list = lock_GF_depth_list;
1501 calc_hauptroutine_calc_deco();
1502 }
1503 // build_debug_output();
1504 break;
1505 }
1506 calc_ascenttime();
1507 check_post_dbg();
1508 }
1509
1510 void calc_hauptroutine_data_input(void)
1511 {
1512 pres_respiration = (float)int_I_pres_respiration / 1000.0;
1513 pres_surface = (float)int_I_pres_surface / 1000.0;
1514
1515 N2_ratio = (float)char_I_N2_ratio / 100.0;; // the 0.0002 of 0.7902 are missing with standard air
1516 He_ratio = (float)char_I_He_ratio / 100.0;;
1517 deco_N2_ratio = (float)char_I_deco_N2_ratio / 100.0;
1518 deco_He_ratio = (float)char_I_deco_He_ratio / 100.0;
1519 float_deco_distance = (float)char_I_deco_distance / 100.0;
1520 if(char_I_deco_gas_change)
1521 {
1522 deco_gas_change = (float)char_I_deco_gas_change / 9.995 + pres_surface;
1523 deco_gas_change = deco_gas_change + float_deco_distance;
1524 }
1525 else
1526 deco_gas_change = 0;
1527 const_ppO2 = (float)char_I_const_ppO2 / 100.0;
1528 deco_ppO2_change = (float)char_I_deco_ppO2_change / 99.95 + pres_surface;
1529 deco_ppO2_change = deco_ppO2_change + float_deco_distance;
1530 deco_ppO2 = (float)char_I_deco_ppO2 / 100.0;
1531 float_desaturation_multiplier = char_I_desaturation_multiplier / 100.0;
1532 float_saturation_multiplier = char_I_saturation_multiplier / 100.0;
1533 GF_low = (float)char_I_GF_Low_percentage / 100.0;
1534 GF_high = (float)char_I_GF_High_percentage / 100.0;
1535 GF_delta = GF_high - GF_low;
1536
1537 temp2 = (pres_respiration - pres_surface) / 0.29985;
1538 int_temp = (int)(temp2);
1539 if (int_temp < 0)
1540 int_temp = 0;
1541 if (int_temp > 255)
1542 int_temp = 255;
1543 char_O_actual_pointer = int_temp;
1544
1545 temp_depth_last_deco = (int)char_I_depth_last_deco;
1546 }
1547
1548 void calc_hauptroutine_update_tissues(void)
1549 {
1550 int_O_calc_tissue_call_counter = int_O_calc_tissue_call_counter + 1;
1551 if (char_I_const_ppO2 == 0) // new in v.101
1552 pres_diluent = pres_respiration; // new in v.101
1553 else // new in v.101
1554 pres_diluent = ((pres_respiration - const_ppO2)/(N2_ratio + He_ratio)); // new in v.101
1555 if (pres_diluent > pres_respiration) // new in v.101
1556 pres_diluent = pres_respiration; // new in v.101
1557 if (pres_diluent > 0.0627) // new in v.101
1558 {
1559 temp_atem = N2_ratio * (pres_diluent - 0.0627); // changed in v.101
1560 temp2_atem = He_ratio * (pres_diluent - 0.0627); // changed in v.101
1561 char_O_diluent = (char)(pres_diluent/pres_respiration*100.0);
1562 }
1563 else // new in v.101
1564 {
1565 temp_atem = 0.0; // new in v.101
1566 temp2_atem = 0.0; // new in v.101
1567 char_O_diluent = 0;
1568 }
1569 temp_surface = pres_surface;
1570 calc_tissue();
1571 int_O_gtissue_limit = (int)(pres_tissue_limit[char_O_gtissue_no] * 1000);
1572 int_O_gtissue_press = (int)((pres_tissue[char_O_gtissue_no] + pres_tissue[char_O_gtissue_no+16]) * 1000);
1573 if (char_I_deco_model == 1)
1574 {
1575 temp1 = temp1 * GF_high;
1576 }
1577 else
1578 {
1579 temp1 = temp_surface;
1580 }
1581 if (pres_gtissue_limit > temp1 && char_O_deco_status == 0) // if guiding tissue can not be exposed to surface pressure immediately
1582 {
1583 char_O_nullzeit = 0; // deco necessary
1584 char_O_deco_status = 255; // calculate deco skip nullzeit calculation
1585 }
1586 } // calc_hauptroutine_update_tissues
1587 void calc_hauptroutine_calc_deco(void)
1588 {
1589 do
1590 {
1591 int_temp_decostatus = 0;
1592 calc_nextdecodepth_GF();
1593 if (temp_depth_limit > 0)
1594 {
1595 if (char_I_const_ppO2 == 0) // new in v.101
1596 {
1597 deco_diluent = temp_deco; // new in v.101
1598 if (temp_deco > deco_gas_change)
1599 {
1600 calc_N2_ratio = N2_ratio;
1601 calc_He_ratio = He_ratio;
1602 }
1603 else
1604 {
1605 calc_N2_ratio = deco_N2_ratio;
1606 calc_He_ratio = deco_He_ratio;
1607 }
1608 }
1609 else // new in v.101
1610 {
1611 calc_N2_ratio = N2_ratio;
1612 calc_He_ratio = He_ratio;
1613 if (temp_deco > deco_ppO2_change)
1614 {
1615 deco_diluent = ((temp_deco - const_ppO2)/(N2_ratio + He_ratio)); // new in v.101
1616 }
1617 else
1618 {
1619 deco_diluent = ((temp_deco - deco_ppO2)/(N2_ratio + He_ratio)); // new in v.101
1620 }
1621 }
1622 if (deco_diluent > temp_deco) // new in v.101
1623 deco_diluent = temp_deco; // new in v.101
1624 if (deco_diluent > 0.0627) // new in v.101
1625 {
1626 temp_atem = calc_N2_ratio * (deco_diluent - 0.0627); // changed in v.101
1627 temp2_atem = calc_He_ratio * (deco_diluent - 0.0627); // changed in v.101
1628 }
1629 else // new in v.101
1630 {
1631 temp_atem = 0.0; // new in v.101
1632 temp2_atem = 0.0; // new in v.101
1633 }
1634 sim_tissue_1min();
1635 update_internal_deco_table_GF();
1636 temp_decotime = 1;
1637 update_decoarray();
1638 char_O_deco_status = char_O_deco_status + 1;
1639 if (char_O_deco_status < 16)
1640 int_temp_decostatus = 1;
1641 }
1642 else // if (temp_depth_limit > 0)
1643 {
1644 char_O_deco_status = 0;
1645 }
1646 } while (int_temp_decostatus == 1);
1647 if (char_O_deco_status > 15)
1648 {
1649 char_O_deco_status = 1;
1650 }
1651 else
1652 {
1653 copy_deco_table_GF();
1654 char_O_deco_status = 0;
1655 }
1656 }
1657
1658 void calc_hauptroutine_calc_ascend_to_deco(void)
1659 {
1660 update_startvalues();
1661 char_O_deco_status = 0;
1662 temp_deco = pres_respiration;
1663 lock_GF_depth_list = 1; // new in v.102
1664 do // go up to first deco
1665 {
1666 int_temp_decostatus = 0;
1667 temp_deco = temp_deco - 1.0;
1668 if ( char_I_deco_model == 1) // new in v.102 , 4 = deep stops
1669 temp_limit = temp_pres_gtissue_limit_GF_low;
1670 else
1671 temp_limit = temp_pres_gtissue_limit;
1672 if ((temp_deco > temp_limit) && (temp_deco > pres_surface)) // changes in v.102
1673 {
1674 lock_GF_depth_list = 0; // new in v.102, distance to first stop > 10 mtr.
1675 output[6] = 0;
1676 if (char_I_const_ppO2 == 0) // new in v.101 // calculate at half of the ascent
1677 {
1678 deco_diluent = temp_deco + 0.5; // new in v.101
1679 if (temp_deco + 0.5 > deco_gas_change)
1680 {
1681 calc_N2_ratio = N2_ratio;
1682 calc_He_ratio = He_ratio;
1683 }
1684 else
1685 {
1686 calc_N2_ratio = deco_N2_ratio;
1687 calc_He_ratio = deco_He_ratio;
1688 }
1689 }
1690 else // new in v.101
1691 {
1692 calc_N2_ratio = N2_ratio;
1693 calc_He_ratio = He_ratio;
1694 if (temp_deco + 0.5 > deco_ppO2_change)
1695 deco_diluent = ((temp_deco + 0.5 - const_ppO2)/(N2_ratio + He_ratio)); // new in v.101 // calculate at half of the ascent
1696 else
1697 deco_diluent = ((temp_deco + 0.5 - deco_ppO2)/(N2_ratio + He_ratio)); // new in v.101 // calculate at half of the ascent
1698 if (deco_diluent > (temp_deco +0.5)) // new in v.101
1699 deco_diluent = temp_deco + 0.5; // new in v.101 // calculate at half of the ascent
1700 }
1701 if (deco_diluent > 0.0627) // new in v.101
1702 {
1703 temp_atem = calc_N2_ratio * (deco_diluent - 0.0627); // changed in v.101
1704 temp2_atem = calc_He_ratio * (deco_diluent - 0.0627); // changed in v.101
1705 }
1706 else // new in v.101
1707 {
1708 temp_atem = 0.0; // new in v.101
1709 temp2_atem = 0.0; // new in v.101
1710 }
1711 sim_tissue_1min();
1712 char_O_deco_status = char_O_deco_status + 1;
1713 if (char_O_deco_status < 16) // 16 is the limit of calculations for one time slot
1714 int_temp_decostatus = 1;
1715 }
1716 } while (int_temp_decostatus == 1);
1717 } // calc_hauptroutine_calc_ascend_to_deco
1718
1719 // --------------
1720 // calc_tissue //
1721 // --------------
1722 // optimized in v.101
1723
1724 void calc_tissue(void)
1725 {
1726 _asm
1727 lfsr 1, 0x300
1728 movlw 0x01
1729 movwf TBLPTRU,0
1730 _endasm
1731
1732 char_O_gtissue_no = 255;
1733 pres_gtissue_limit = 0.0;
1734
1735 for (ci=0;ci<16;ci++)
1736 {
1737 _asm
1738 movlw 0x02
1739 movwf TBLPTRH,0
1740 movlb 4 // fuer ci
1741 movf ci,0,1
1742 addwf ci,0,1
1743 addwf ci,0,1
1744 addwf ci,0,1
1745 movwf TBLPTRL,0
1746 TBLRDPOSTINC
1747 movff TABLAT,var_e2secs+1 // the order is confussing
1748 TBLRDPOSTINC
1749 movff TABLAT,var_e2secs // low byte first, high afterwards
1750 TBLRDPOSTINC
1751 movff TABLAT,var_e2secs+3
1752 TBLRD
1753 movff TABLAT,var_e2secs+2
1754 addlw 0x40
1755 movwf TBLPTRL,0
1756 TBLRDPOSTINC
1757 movff TABLAT,var2_e2secs+1
1758 TBLRDPOSTINC
1759 movff TABLAT,var2_e2secs
1760 TBLRDPOSTINC
1761 movff TABLAT,var2_e2secs+3
1762 TBLRD
1763 movff TABLAT,var2_e2secs+2
1764 addlw 0x40
1765 movwf TBLPTRL,0
1766 TBLRDPOSTINC
1767 movff TABLAT,var_a+1
1768 TBLRDPOSTINC
1769 movff TABLAT,var_a
1770 TBLRDPOSTINC
1771 movff TABLAT,var_a+3
1772 TBLRD
1773 movff TABLAT,var_a+2
1774 addlw 0x40
1775 movwf TBLPTRL,0
1776 TBLRDPOSTINC
1777 movff TABLAT,var2_a+1
1778 TBLRDPOSTINC
1779 movff TABLAT,var2_a
1780 TBLRDPOSTINC
1781 movff TABLAT,var2_a+3
1782 TBLRD
1783 movff TABLAT,var2_a+2
1784 addlw 0x40
1785 movwf TBLPTRL,0
1786 incf TBLPTRH,1,0
1787 TBLRDPOSTINC
1788 movff TABLAT,var_b+1
1789 TBLRDPOSTINC
1790 movff TABLAT,var_b
1791 TBLRDPOSTINC
1792 movff TABLAT,var_b+3
1793 TBLRD
1794 movff TABLAT,var_b+2
1795 addlw 0x40
1796 movwf TBLPTRL,0
1797 TBLRDPOSTINC
1798 movff TABLAT,var2_b+1
1799 TBLRDPOSTINC
1800 movff TABLAT,var2_b
1801 TBLRDPOSTINC
1802 movff TABLAT,var2_b+3
1803 TBLRD
1804 movff TABLAT,var2_b+2
1805 _endasm
1806 // the start values are the previous end values // write new values in temp
1807
1808 if( (var_e2secs < 0.0000363)
1809 || (var_e2secs > 0.00577)
1810 || (var2_e2secs < 0.0000961)
1811 || (var2_e2secs > 0.150)
1812 || (var_a < 0.231)
1813 || (var_a > 1.27)
1814 || (var_b < 0.504)
1815 || (var_b > 0.966)
1816 || (var2_a < 0.510)
1817 || (var2_a > 1.75)
1818 || (var2_b < 0.423)
1819 || (var2_b > 0.927)
1820 )
1821 int_O_DBG_pre_bitfield |= DBG_ZH16ERR;
1822
1823 // N2
1824 temp_tissue = (temp_atem - pres_tissue[ci]) * var_e2secs;
1825 temp_tissue_safety();
1826 pres_tissue[ci] = pres_tissue[ci] + temp_tissue;
1827
1828 // He
1829 temp_tissue = (temp2_atem - pres_tissue[ci+16]) * var2_e2secs;
1830 temp_tissue_safety();
1831 pres_tissue[ci+16] = pres_tissue[ci+16] + temp_tissue;
1832
1833 temp_tissue = pres_tissue[ci] + pres_tissue[ci+16];
1834
1835 var_a = (var_a * pres_tissue[ci] + var2_a * pres_tissue[ci+16]) / temp_tissue;
1836 var_b = (var_b * pres_tissue[ci] + var2_b * pres_tissue[ci+16]) / temp_tissue;
1837 pres_tissue_limit[ci] = (temp_tissue - var_a) * var_b;
1838 if (pres_tissue_limit[ci] < 0)
1839 pres_tissue_limit[ci] = 0;
1840 if (pres_tissue_limit[ci] > pres_gtissue_limit)
1841 {
1842 pres_gtissue_limit = pres_tissue_limit[ci];
1843 char_O_gtissue_no = ci;
1844 }//if
1845 } // for
1846 }//calc_tissue(void)
1847
1848 // ----------------
1849 // calc_nullzeit //
1850 // ----------------
1851 // calculates the remaining bottom time
1852
1853 // unchanged in v.101
1854
1855 void calc_nullzeit(void)
1856 {
1857 char_O_nullzeit = 0;
1858 int_temp = 1;
1859 do
1860 {
1861 backup_sim_pres_tissue();
1862 sim_tissue_10min();
1863 char_O_nullzeit = char_O_nullzeit + 10;
1864 int_temp = int_temp + 1;
1865 if (char_I_deco_model == 1)
1866 temp1 = GF_high * temp_pres_gtissue_diff + temp_pres_gtissue;
1867 else
1868 temp1 = temp_pres_gtissue_limit;
1869 if (temp1 > temp_surface) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately
1870 int_temp = 255;
1871 } while (int_temp < 17);
1872 if (int_temp == 255)
1873 {
1874 restore_sim_pres_tissue();
1875 char_O_nullzeit = char_O_nullzeit - 10;
1876 } //if int_temp == 255]
1877 int_temp = 1;
1878 if (char_O_nullzeit < 60)
1879 {
1880 do
1881 {
1882 sim_tissue_1min();
1883 char_O_nullzeit = char_O_nullzeit + 1;
1884 int_temp = int_temp + 1; // new in v.102a
1885 if (char_I_deco_model == 1)
1886 temp1 = GF_high * temp_pres_gtissue_diff + temp_pres_gtissue;
1887 else
1888 temp1 = temp_pres_gtissue_limit;
1889 if (temp1 > temp_surface) // changed in v.102 , if guiding tissue can not be exposed to surface pressure immediately
1890 int_temp = 255;
1891 } while (int_temp < 10);
1892 if (int_temp == 255)
1893 char_O_nullzeit = char_O_nullzeit - 1;
1894 } // if char_O_nullzeit < 60
1895 } //calc_nullzeit
1896
1897 // -------------------------
1898 // backup_sim_pres_tissue //
1899 // -------------------------
1900 void backup_sim_pres_tissue(void)
1901 {
1902 for (x = 0;x<16;x++)
1903 {
1904 sim_pres_tissue_backup[x] = sim_pres_tissue[x];
1905 sim_pres_tissue_backup[x+16] = sim_pres_tissue[x+16];
1906 }
1907 } // backup_sim
1908
1909 // --------------------------
1910 // restore_sim_pres_tissue //
1911 // --------------------------
1912 void restore_sim_pres_tissue(void)
1913 {
1914 for (x = 0;x<16;x++)
1915 {
1916 sim_pres_tissue[x] = sim_pres_tissue_backup[x];
1917 sim_pres_tissue[x+16] = sim_pres_tissue_backup[x+16];
1918 }
1919 } // restore_sim
1920
1921 // ------------------
1922 // calc_ascenttime //
1923 // ------------------
1924
1925 void calc_ascenttime(void)
1926 {
1927 if (pres_respiration > pres_surface)
1928 {
1929 switch (char_O_deco_status)
1930 {
1931 case 2:
1932 char_O_ascenttime = 255;
1933 break;
1934 case 1:
1935 break;
1936 default:
1937 temp1 = pres_respiration - pres_surface + 0.6; // + 0.6 hence 1 minute ascent time from a depth of 4 meter on
1938 if (temp1 < 0)
1939 temp1 = 0;
1940 if (temp1 > 255)
1941 temp1 = 255;
1942 char_O_ascenttime = (char)temp1;
1943
1944 for(ci=0;ci<7;ci++)
1945 {
1946 x = char_O_ascenttime + char_O_array_decotime[ci];
1947 if (x < char_O_ascenttime)
1948 char_O_ascenttime = 255;
1949 else
1950 char_O_ascenttime = x;
1951 }
1952 }
1953 }
1954 else
1955 char_O_ascenttime = 0;
1956 } // calc_ascenttime()
1957
1958
1959 // ---------------------
1960 // update_startvalues //
1961 // ---------------------
1962 // updated in v.102
1963
1964 void update_startvalues(void)
1965 {
1966 temp_pres_gtissue_limit = pres_gtissue_limit;
1967 temp_pres_gtissue = pres_tissue[char_O_gtissue_no] + pres_tissue[char_O_gtissue_no+16];
1968 temp_pres_gtissue_diff = temp_pres_gtissue_limit - temp_pres_gtissue; // negative number
1969 temp_pres_gtissue_limit_GF_low = GF_low * temp_pres_gtissue_diff + temp_pres_gtissue;
1970 temp_pres_gtissue_limit_GF_low_below_surface = temp_pres_gtissue_limit_GF_low - pres_surface;
1971 if (temp_pres_gtissue_limit_GF_low_below_surface < 0)
1972 temp_pres_gtissue_limit_GF_low_below_surface = 0;
1973
1974 temp_gtissue_no = char_O_gtissue_no;
1975 for (x = 0;x<16;x++)
1976 {
1977 sim_pres_tissue[x] = pres_tissue[x];
1978 sim_pres_tissue[x+16] = pres_tissue[x+16];
1979 sim_pres_tissue_limit[x] = pres_tissue_limit[x];
1980 }
1981 } // update_startvalues
1982
1983
1984 // ------------------
1985 // sim_tissue_1min //
1986 // ------------------
1987 // optimized in v.101
1988
1989 void sim_tissue_1min(void)
1990 {
1991 temp_pres_gtissue_limit = 0.0;
1992 temp_gtissue_no = 255;
1993
1994 _asm
1995 lfsr 1, 0x300
1996 movlw 0x01
1997 movwf TBLPTRU,0
1998 _endasm
1999
2000
2001 for (ci=0;ci<16;ci++)
2002 {
2003 _asm
2004 movlw 0x02
2005 movwf TBLPTRH,0
2006 movlb 4 // fuer ci
2007 movf ci,0,1
2008 addwf ci,0,1
2009 addwf ci,0,1
2010 addwf ci,0,1
2011 addlw 0x80
2012 movwf TBLPTRL,0
2013 TBLRDPOSTINC
2014 movff TABLAT,var_a+1
2015 TBLRDPOSTINC
2016 movff TABLAT,var_a
2017 TBLRDPOSTINC
2018 movff TABLAT,var_a+3
2019 TBLRD
2020 movff TABLAT,var_a+2
2021 addlw 0x40
2022 movwf TBLPTRL,0
2023 TBLRDPOSTINC
2024 movff TABLAT,var2_a+1
2025 TBLRDPOSTINC
2026 movff TABLAT,var2_a
2027 TBLRDPOSTINC
2028 movff TABLAT,var2_a+3
2029 TBLRD
2030 movff TABLAT,var2_a+2
2031 addlw 0x40
2032 movwf TBLPTRL,0
2033 incf TBLPTRH,1,0
2034 TBLRDPOSTINC
2035 movff TABLAT,var_b+1
2036 TBLRDPOSTINC
2037 movff TABLAT,var_b
2038 TBLRDPOSTINC
2039 movff TABLAT,var_b+3
2040 TBLRD
2041 movff TABLAT,var_b+2
2042 addlw 0x40
2043 movwf TBLPTRL,0
2044 TBLRDPOSTINC
2045 movff TABLAT,var2_b+1
2046 TBLRDPOSTINC
2047 movff TABLAT,var2_b
2048 TBLRDPOSTINC
2049 movff TABLAT,var2_b+3
2050 TBLRD
2051 movff TABLAT,var2_b+2
2052 addlw 0xC0
2053 movwf TBLPTRL,0
2054 incf TBLPTRH,1,0
2055 TBLRDPOSTINC
2056 movff TABLAT,var_e1min+1
2057 TBLRDPOSTINC
2058 movff TABLAT,var_e1min
2059 TBLRDPOSTINC
2060 movff TABLAT,var_e1min+3
2061 TBLRD
2062 movff TABLAT,var_e1min+2
2063 addlw 0x40
2064 movwf TBLPTRL,0
2065 TBLRDPOSTINC
2066 movff TABLAT,var2_e1min+1
2067 TBLRDPOSTINC
2068 movff TABLAT,var2_e1min
2069 TBLRDPOSTINC
2070 movff TABLAT,var2_e1min+3
2071 TBLRD
2072 movff TABLAT,var2_e1min+2
2073 _endasm
2074 // N2
2075 temp_tissue = (temp_atem - sim_pres_tissue[ci]) * var_e1min;
2076 temp_tissue_safety();
2077 sim_pres_tissue[ci] = sim_pres_tissue[ci] + temp_tissue;
2078 // He
2079 temp_tissue = (temp2_atem - sim_pres_tissue[ci+16]) * var2_e1min;
2080 temp_tissue_safety();
2081 sim_pres_tissue[ci+16] = sim_pres_tissue[ci+16] + temp_tissue;
2082 // pressure limit
2083 temp_tissue = sim_pres_tissue[ci] + sim_pres_tissue[ci+16];
2084 var_a = (var_a * sim_pres_tissue[ci] + var2_a * sim_pres_tissue[ci+16]) / temp_tissue;
2085 var_b = (var_b * sim_pres_tissue[ci] + var2_b * sim_pres_tissue[ci+16]) / temp_tissue;
2086 sim_pres_tissue_limit[ci] = (temp_tissue - var_a) * var_b;
2087
2088 if (sim_pres_tissue_limit[ci] < 0)
2089 sim_pres_tissue_limit[ci] = 0;
2090 if (sim_pres_tissue_limit[ci] > temp_pres_gtissue_limit)
2091 {
2092 temp_pres_gtissue = temp_tissue;
2093 temp_pres_gtissue_limit = sim_pres_tissue_limit[ci];
2094 temp_gtissue_no = ci;
2095 }
2096 } // for
2097 temp_pres_gtissue_diff = temp_pres_gtissue_limit - temp_pres_gtissue;
2098 temp_pres_gtissue_limit_GF_low = GF_low * temp_pres_gtissue_diff + temp_pres_gtissue;
2099 temp_pres_gtissue_limit_GF_low_below_surface = temp_pres_gtissue_limit_GF_low - pres_surface;
2100 if (temp_pres_gtissue_limit_GF_low_below_surface < 0)
2101 temp_pres_gtissue_limit_GF_low_below_surface = 0;
2102 } //sim_tissue_1min()
2103
2104 //--------------------
2105 // sim_tissue_10min //
2106 //--------------------
2107
2108 // Attention!! uses var_e1min und var2_e1min to load 10min data !!!
2109 // is identical to sim_tissue_1min routine except for the different load of those variables
2110
2111 // optimized in v.101
2112
2113 void sim_tissue_10min(void)
2114 {
2115 temp_pres_gtissue_limit = 0.0;
2116 temp_gtissue_no = 255;
2117
2118 _asm
2119 lfsr 1, 0x300
2120 movlw 0x01
2121 movwf TBLPTRU,0
2122 _endasm
2123
2124 for (ci=0;ci<16;ci++)
2125 {
2126 _asm
2127 movlw 0x02
2128 movwf TBLPTRH,0
2129 movlb 4 // fuer ci
2130 movf ci,0,1
2131 addwf ci,0,1
2132 addwf ci,0,1
2133 addwf ci,0,1
2134 addlw 0x80
2135 movwf TBLPTRL,0
2136 TBLRDPOSTINC
2137 movff TABLAT,var_a+1
2138 TBLRDPOSTINC
2139 movff TABLAT,var_a
2140 TBLRDPOSTINC
2141 movff TABLAT,var_a+3
2142 TBLRD
2143 movff TABLAT,var_a+2
2144 addlw 0x40
2145 movwf TBLPTRL,0
2146 TBLRDPOSTINC
2147 movff TABLAT,var2_a+1
2148 TBLRDPOSTINC
2149 movff TABLAT,var2_a
2150 TBLRDPOSTINC
2151 movff TABLAT,var2_a+3
2152 TBLRD
2153 movff TABLAT,var2_a+2
2154 addlw 0x40
2155 movwf TBLPTRL,0
2156 incf TBLPTRH,1,0
2157 TBLRDPOSTINC
2158 movff TABLAT,var_b+1
2159 TBLRDPOSTINC
2160 movff TABLAT,var_b
2161 TBLRDPOSTINC
2162 movff TABLAT,var_b+3
2163 TBLRD
2164 movff TABLAT,var_b+2
2165 addlw 0x40
2166 movwf TBLPTRL,0
2167 TBLRDPOSTINC
2168 movff TABLAT,var2_b+1
2169 TBLRDPOSTINC
2170 movff TABLAT,var2_b
2171 TBLRDPOSTINC
2172 movff TABLAT,var2_b+3
2173 TBLRD
2174 movff TABLAT,var2_b+2
2175 addlw 0xC0 // different to 1 min
2176 movwf TBLPTRL,0
2177 incf TBLPTRH,1,0
2178 incf TBLPTRH,1,0 // different to 1 min
2179 TBLRDPOSTINC
2180 movff TABLAT,var_e1min+1
2181 TBLRDPOSTINC
2182 movff TABLAT,var_e1min
2183 TBLRDPOSTINC
2184 movff TABLAT,var_e1min+3
2185 TBLRD
2186 movff TABLAT,var_e1min+2
2187 addlw 0x40
2188 movwf TBLPTRL,0
2189 //incf TBLPTRH,1,0 // different to 1 min
2190 TBLRDPOSTINC
2191 movff TABLAT,var2_e1min+1
2192 TBLRDPOSTINC
2193 movff TABLAT,var2_e1min
2194 TBLRDPOSTINC
2195 movff TABLAT,var2_e1min+3
2196 TBLRD
2197 movff TABLAT,var2_e1min+2
2198 _endasm
2199 // N2
2200 temp_tissue = (temp_atem - sim_pres_tissue[ci]) * var_e1min;
2201 temp_tissue_safety();
2202 sim_pres_tissue[ci] = sim_pres_tissue[ci] + temp_tissue;
2203 // He
2204 temp_tissue = (temp2_atem - sim_pres_tissue[ci+16]) * var2_e1min;
2205 temp_tissue_safety();
2206 sim_pres_tissue[ci+16] = sim_pres_tissue[ci+16] + temp_tissue;
2207 // pressure limit
2208 temp_tissue = sim_pres_tissue[ci] + sim_pres_tissue[ci+16];
2209 var_a = (var_a * sim_pres_tissue[ci] + var2_a * sim_pres_tissue[ci+16]) / temp_tissue;
2210 var_b = (var_b * sim_pres_tissue[ci] + var2_b * sim_pres_tissue[ci+16]) / temp_tissue;
2211
2212 sim_pres_tissue_limit[ci] = (temp_tissue - var_a) * var_b;
2213 if (sim_pres_tissue_limit[ci] < 0)
2214 sim_pres_tissue_limit[ci] = 0;
2215 if (sim_pres_tissue_limit[ci] > temp_pres_gtissue_limit)
2216 {
2217 temp_pres_gtissue = temp_tissue;
2218 temp_pres_gtissue_limit = sim_pres_tissue_limit[ci];
2219 temp_gtissue_no = ci;
2220 }
2221 } // for
2222 temp_pres_gtissue_diff = temp_pres_gtissue_limit - temp_pres_gtissue; // negative number
2223 temp_pres_gtissue_limit_GF_low = GF_low * temp_pres_gtissue_diff + temp_pres_gtissue;
2224 temp_pres_gtissue_limit_GF_low_below_surface = temp_pres_gtissue_limit_GF_low - pres_surface;
2225 if (temp_pres_gtissue_limit_GF_low_below_surface < 0)
2226 temp_pres_gtissue_limit_GF_low_below_surface = 0;
2227 } //sim_tissue_10min()
2228
2229
2230 // ------------------
2231 // clear_decoarray //
2232 // ------------------
2233 // unchanged in v.101
2234
2235 void clear_decoarray(void)
2236 {
2237 char_O_array_decodepth[0] = 0;
2238 char_O_array_decodepth[1] = 0;
2239 char_O_array_decodepth[2] = 0;
2240 char_O_array_decodepth[3] = 0;
2241 char_O_array_decodepth[4] = 0;
2242 char_O_array_decodepth[5] = 0;
2243 char_O_array_decotime[0] = 0;
2244 char_O_array_decotime[1] = 0;
2245 char_O_array_decotime[2] = 0;
2246 char_O_array_decotime[3] = 0;
2247 char_O_array_decotime[4] = 0;
2248 char_O_array_decotime[5] = 0;
2249 char_O_array_decotime[6] = 0;
2250 } // clear_decoarray
2251
2252
2253 // -------------------
2254 // update_decoarray //
2255 // -------------------
2256 // unchanged in v.101
2257
2258 void update_decoarray()
2259 {
2260 x = 0;
2261 do
2262 {
2263 if (char_O_array_decodepth[x] == temp_depth_limit)
2264 {
2265 int_temp = char_O_array_decotime[x] + temp_decotime;
2266 if (int_temp < 0)
2267 int_temp = 0;
2268 if (int_temp > 240)
2269 int_temp = 240;
2270 char_O_array_decotime[x] = int_temp;
2271 x = 10; // exit
2272 } // if
2273 else
2274 {
2275 if (char_O_array_decodepth[x] == 0)
2276 {
2277 if (temp_depth_limit > 255)
2278 char_O_array_decodepth[x] = 255;
2279 else
2280 char_O_array_decodepth[x] = (char)temp_depth_limit;
2281 int_temp = char_O_array_decotime[x] + temp_decotime;
2282 if (int_temp > 240)
2283 char_O_array_decotime[x] = 240;
2284 else
2285 char_O_array_decotime[x] = (char)int_temp;
2286 x = 10; // exit
2287 } // if
2288 else
2289 x++;
2290 } // else
2291 } while (x<6);
2292 if (x == 6)
2293 {
2294 int_temp = char_O_array_decotime[6] + temp_decotime;
2295 if (int_temp > 220)
2296 char_O_array_decotime[6] = 220;
2297 else
2298 char_O_array_decotime[6] = (char)int_temp;
2299 } // if x == 6
2300 } // update_decoarray
2301
2302
2303 // -----------------------
2304 // calc_gradient_factor //
2305 // -----------------------
2306 // optimized in v.101 (var_a)
2307 // new code in v.102
2308
2309 void calc_gradient_factor(void)
2310 {
2311 // tissue > respiration (entsaettigungsvorgang)
2312 // gradient ist wieviel prozent an limit mit basis tissue
2313 // dh. 0% = respiration == tissue
2314 // dh. 100% = respiration == limit
2315 temp_tissue = pres_tissue[char_O_gtissue_no] + pres_tissue[char_O_gtissue_no+16];
2316 temp1 = temp_tissue - pres_respiration;
2317 temp2 = temp_tissue - pres_tissue_limit[char_O_gtissue_no]; // changed in v.102
2318 temp2 = temp1/temp2;
2319 temp2 = temp2 * 100; // displayed in percent
2320 if (temp2 < 0)
2321 temp2 = 0;
2322 if (temp2 > 255)
2323 temp2 = 255;
2324 if (temp1 < 0)
2325 char_O_gradient_factor = 0;
2326 else
2327 char_O_gradient_factor = (char)temp2;
2328
2329 temp3 = temp2;
2330
2331 if (char_I_deco_model == 1) // calculate relative gradient factor
2332 {
2333 temp1 = (float)temp_depth_GF_low_meter * 0.09995;
2334 temp2 = pres_respiration - pres_surface;
2335 if (temp2 <= 0)
2336 temp1 = GF_high;
2337 else
2338 if (temp2 >= temp1)
2339 temp1 = GF_low;
2340 else
2341 temp1 = GF_low + (temp1 - temp2)/temp1*GF_delta;
2342 if (temp_depth_GF_low_meter == 0)
2343 temp1 = GF_high;
2344 temp2 = temp3 / temp1; // temp3 is already in percent
2345 if (temp2 < 0)
2346 temp2 = 0;
2347 if (temp2 > 255)
2348 temp2 = 255;
2349 char_O_relative_gradient_GF = (char)temp2;
2350 } // calc relative gradient factor
2351 else
2352 {
2353 char_O_relative_gradient_GF = char_O_gradient_factor;
2354 }
2355 } // calc_gradient
2356
2357 // ---------------------------
2358 // calc_gradient_array_only //
2359 // ---------------------------
2360 // optimized in v.101 (var_a)
2361 // new code in v.102
2362
2363 void calc_gradient_array_only()
2364 {
2365 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system
2366 for (ci=0;ci<16;ci++)
2367 {
2368 temp_tissue = pres_tissue[ci] + pres_tissue[ci+16];
2369 temp1 = temp_tissue - pres_respiration;
2370 temp2 = temp_tissue - pres_tissue_limit[ci];
2371 temp2 = temp1/temp2;
2372 temp2 = temp2 * 200; // because of output in (Double-)percentage
2373 if (temp2 < 0)
2374 temp2 = 0;
2375 if (temp2 > 255)
2376 temp2 = 255;
2377 if (temp1 < 0)
2378 char_O_array_gradient_weighted[ci] = 0;
2379 else
2380 char_O_array_gradient_weighted[ci] = (char)temp2;
2381 } // for
2382 } // calc_gradient_array_only
2383
2384
2385 // -------------------------
2386 // calc_desaturation_time //
2387 // -------------------------
2388 // FIXED N2_ratio
2389 // unchanged in v.101
2390
2391 void calc_desaturation_time(void)
2392 {
2393 _asm
2394 lfsr 1, 0x300
2395 movlw 0x01
2396 movwf TBLPTRU,0
2397 _endasm
2398 N2_ratio = 0.7902; // FIXED sum as stated in b"uhlmann
2399 pres_surface = (float)int_I_pres_surface / 1000.0;
2400 temp_atem = N2_ratio * (pres_surface - 0.0627);
2401 int_O_desaturation_time = 0;
2402 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142)
2403
2404 for (ci=0;ci<16;ci++)
2405 {
2406 _asm
2407 movlw 0x04
2408 movwf TBLPTRH,0
2409 movlb 4 // fuer ci
2410 movf ci,0,1
2411 addwf ci,0,1
2412 addwf ci,0,1
2413 addwf ci,0,1
2414 addlw 0x80
2415 movwf TBLPTRL,0
2416 TBLRDPOSTINC
2417 movff TABLAT,var_halftimes+1
2418 TBLRDPOSTINC
2419 movff TABLAT,var_halftimes
2420 TBLRDPOSTINC
2421 movff TABLAT,var_halftimes+3
2422 TBLRD
2423 movff TABLAT,var_halftimes+2
2424 addlw 0x40
2425 movwf TBLPTRL,0
2426 TBLRDPOSTINC
2427 movff TABLAT,var2_halftimes+1
2428 TBLRDPOSTINC
2429 movff TABLAT,var2_halftimes
2430 TBLRDPOSTINC
2431 movff TABLAT,var2_halftimes+3
2432 TBLRD
2433 movff TABLAT,var2_halftimes+2
2434 _endasm
2435
2436 // saturation_time (for flight) and N2_saturation in multiples of halftime
2437 // version v.100: 1.1 = 10 percent distance to totally clean (totally clean is not possible, would take infinite time )
2438 // new in version v.101: 1.07 = 7 percent distance to totally clean (totally clean is not possible, would take infinite time )
2439 // changes in v.101: 1.05 = 5 percent dist to totally clean is new desaturation point for display and noFly calculations
2440 // N2
2441 temp1 = 1.05 * temp_atem;
2442 temp1 = temp1 - pres_tissue[ci];
2443 temp2 = temp_atem - pres_tissue[ci];
2444 if (temp2 >= 0.0)
2445 {
2446 temp1 = 0;
2447 temp2 = 0;
2448 }
2449 else
2450 temp1 = temp1 / temp2;
2451 if (temp1 > 0.0)
2452 {
2453 temp1 = log(1.0 - temp1);
2454 temp1 = temp1 / -0.6931; // temp1 is the multiples of half times necessary.
2455 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested.
2456 // minus because log is negative
2457 temp2 = var_halftimes * temp1 / float_desaturation_multiplier; // time necessary (in minutes ) for complete desaturation (see comment about 10 percent) , new in v.101: float_desaturation_multiplier
2458 }
2459 else
2460 {
2461 temp1 = 0;
2462 temp2 = 0;
2463 }
2464
2465 // He
2466 temp3 = 0.1 - pres_tissue[ci+16];
2467 if (temp3 >= 0.0)
2468 {
2469 temp3 = 0;
2470 temp4 = 0;
2471 }
2472 else
2473 temp3 = -1.0 * temp3 / pres_tissue[ci+16];
2474 if (temp3 > 0.0)
2475 {
2476 temp3 = log(1.0 - temp3);
2477 temp3 = temp3 / -0.6931; // temp1 is the multiples of half times necessary.
2478 // 0.6931 is ln(2), because the math function log() calculates with a base of e not 2 as requested.
2479 // minus because log is negative
2480 temp4 = var2_halftimes * temp3 / float_desaturation_multiplier; // time necessary (in minutes ) for "complete" desaturation, new in v.101 float_desaturation_multiplier
2481 }
2482 else
2483 {
2484 temp3 = 0;
2485 temp4 = 0;
2486 }
2487
2488 // saturation_time (for flight)
2489 if (temp4 > temp2)
2490 int_temp = (int)temp4;
2491 else
2492 int_temp = (int)temp2;
2493 if(int_temp > int_O_desaturation_time)
2494 int_O_desaturation_time = int_temp;
2495
2496 // N2 saturation in multiples of halftime for display purposes
2497 temp2 = temp1 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8
2498 temp2 = temp2 + 80.0; // set center
2499 if (temp2 < 0.0)
2500 temp2 = 0.0;
2501 if (temp2 > 255.0)
2502 temp2 = 255.0;
2503 char_O_tissue_saturation[ci] = (char)temp2;
2504 // He saturation in multiples of halftime for display purposes
2505 temp4 = temp3 * 20.0; // 0 = 1/8, 120 = 0, 249 = 8
2506 temp4 = temp4 + 80.0; // set center
2507 if (temp4 < 0.0)
2508 temp4 = 0.0;
2509 if (temp4 > 255.0)
2510 temp4 = 255.0;
2511 char_O_tissue_saturation[ci+16] = (char)temp4;
2512 } // for
2513 } // calc_desaturation_time
2514
2515
2516 // --------------------------
2517 // calc_wo_deco_step_1_min //
2518 // --------------------------
2519 // FIXED N2 Ratio
2520 // optimized in v.101 (...saturation_multiplier)
2521 // desaturation slowed down to 70,42%
2522
2523 void calc_wo_deco_step_1_min(void)
2524 {
2525 if(flag_in_divemode)
2526 {
2527 flag_in_divemode = 0;
2528 set_dbg_end_of_dive();
2529 }
2530 _asm
2531 lfsr 1, 0x300
2532 _endasm
2533 N2_ratio = 0.7902; // FIXED, sum lt. buehlmann
2534 pres_respiration = (float)int_I_pres_respiration / 1000.0; // assembler code uses different digit system
2535 pres_surface = (float)int_I_pres_surface / 1000.0;
2536 temp_atem = N2_ratio * (pres_respiration - 0.0627); // 0.0627 is the extra pressure in the body
2537 temp2_atem = 0.0;
2538 temp_surface = pres_surface; // the b"uhlmann formula using temp_surface does not use the N2_ratio
2539 float_desaturation_multiplier = char_I_desaturation_multiplier / 142.0; // new in v.101 (70,42%/100.=142)
2540 float_saturation_multiplier = char_I_saturation_multiplier / 100.0;
2541
2542 calc_tissue_step_1_min(); // update the pressure in the 16 tissues in accordance with the new ambient pressure
2543 clear_decoarray();
2544 char_O_deco_status = 0;
2545 char_O_nullzeit = 0;
2546 char_O_ascenttime = 0;
2547 calc_gradient_factor();
2548
2549 } // calc_wo_deco_step_1_min(void)
2550
2551
2552 // -------------------------
2553 // calc_tissue_step_1_min //
2554 // -------------------------
2555 // optimized in v.101
2556
2557 void calc_tissue_step_1_min(void)
2558 {
2559 _asm
2560 lfsr 1, 0x300
2561 movlw 0x01
2562 movwf TBLPTRU,0
2563 _endasm
2564
2565 char_O_gtissue_no = 255;
2566 pres_gtissue_limit = 0.0;
2567
2568 for (ci=0;ci<16;ci++)
2569 {
2570 _asm
2571 movlw 0x02
2572 movwf TBLPTRH,0
2573 movlb 4 // fuer ci
2574 movf ci,0,1
2575 addwf ci,0,1
2576 addwf ci,0,1
2577 addwf ci,0,1
2578 addlw 0x80
2579 movwf TBLPTRL,0
2580 TBLRDPOSTINC
2581 movff TABLAT,var_a+1
2582 TBLRDPOSTINC
2583 movff TABLAT,var_a
2584 TBLRDPOSTINC
2585 movff TABLAT,var_a+3
2586 TBLRD
2587 movff TABLAT,var_a+2
2588 addlw 0x40
2589 movwf TBLPTRL,0
2590 TBLRDPOSTINC
2591 movff TABLAT,var2_a+1
2592 TBLRDPOSTINC
2593 movff TABLAT,var2_a
2594 TBLRDPOSTINC
2595 movff TABLAT,var2_a+3
2596 TBLRD
2597 movff TABLAT,var2_a+2
2598 addlw 0x40
2599 movwf TBLPTRL,0
2600 incf TBLPTRH,1,0
2601 TBLRDPOSTINC
2602 movff TABLAT,var_b+1
2603 TBLRDPOSTINC
2604 movff TABLAT,var_b
2605 TBLRDPOSTINC
2606 movff TABLAT,var_b+3
2607 TBLRD
2608 movff TABLAT,var_b+2
2609 addlw 0x40
2610 movwf TBLPTRL,0
2611 TBLRDPOSTINC
2612 movff TABLAT,var2_b+1
2613 TBLRDPOSTINC
2614 movff TABLAT,var2_b
2615 TBLRDPOSTINC
2616 movff TABLAT,var2_b+3
2617 TBLRD
2618 movff TABLAT,var2_b+2
2619 addlw 0xC0
2620 movwf TBLPTRL,0
2621 incf TBLPTRH,1,0
2622 TBLRDPOSTINC
2623 movff TABLAT,var_e1min+1
2624 TBLRDPOSTINC
2625 movff TABLAT,var_e1min
2626 TBLRDPOSTINC
2627 movff TABLAT,var_e1min+3
2628 TBLRD
2629 movff TABLAT,var_e1min+2
2630 addlw 0x40
2631 movwf TBLPTRL,0
2632 TBLRDPOSTINC
2633 movff TABLAT,var2_e1min+1
2634 TBLRDPOSTINC
2635 movff TABLAT,var2_e1min
2636 TBLRDPOSTINC
2637 movff TABLAT,var2_e1min+3
2638 TBLRD
2639 movff TABLAT,var2_e1min+2
2640 _endasm
2641
2642 // N2 1 min
2643 temp_tissue = (temp_atem - pres_tissue[ci]) * var_e1min;
2644 temp_tissue_safety();
2645 pres_tissue[ci] = pres_tissue[ci] + temp_tissue;
2646
2647 // He 1 min
2648 temp_tissue = (temp2_atem - pres_tissue[ci+16]) * var2_e1min;
2649 temp_tissue_safety();
2650 pres_tissue[ci+16] = pres_tissue[ci+16] + temp_tissue;
2651
2652 temp_tissue = pres_tissue[ci] + pres_tissue[ci+16];
2653 var_a = (var_a * pres_tissue[ci] + var2_a * pres_tissue[ci+16]) / temp_tissue;
2654 var_b = (var_b * pres_tissue[ci] + var2_b * pres_tissue[ci+16]) / temp_tissue;
2655 pres_tissue_limit[ci] = (temp_tissue - var_a) * var_b;
2656 if (pres_tissue_limit[ci] < 0)
2657 pres_tissue_limit[ci] = 0;
2658 if (pres_tissue_limit[ci] > pres_gtissue_limit)
2659 {
2660 pres_gtissue_limit = pres_tissue_limit[ci];
2661 char_O_gtissue_no = ci;
2662 }//if
2663
2664 // gradient factor array for graphical display
2665 // display range is 0 to 250! in steps of 5 for 1 pixel
2666 // the display is divided in 6 blocks
2667 // -> double the gradient 100% = 200
2668 // tissue > respiration (entsaettigungsvorgang)
2669 // gradient ist wieviel prozent an limit von tissue aus
2670 // dh. 0% = respiration == tissue
2671 // dh. 100% = respiration == limit
2672 temp1 = temp_tissue - pres_respiration;
2673 temp2 = temp_tissue - pres_tissue_limit[ci]; // changed in v.102
2674 temp2 = temp1/temp2;
2675 temp2 = temp2 * 200; // because of output in (Double-)percentage
2676 if (temp2 < 0)
2677 temp2 = 0;
2678 if (temp2 > 255)
2679 temp2 = 255;
2680 if (temp1 < 0)
2681 char_O_array_gradient_weighted[ci] = 0;
2682 else
2683 char_O_array_gradient_weighted[ci] = (char)temp2;
2684
2685 } // for
2686 } // calc wo deco 1min
2687
2688 #if 0
2689 // --------
2690 // debug //
2691 // --------
2692 void debug(void)
2693 {
2694 for (ci=0;ci<32;ci++)
2695 {
2696 int_O_tissue_for_debug[ci] = (unsigned int)(pres_tissue[ci] *1000);
2697 }
2698 } // void debug(void)
2699 #endif
2700
2701 // ----------
2702 // md hash //
2703 // ----------
2704 void hash(void)
2705 {
2706 // init
2707 for (md_i=0;md_i<16;md_i++)
2708 {
2709 md_state[md_i] = 0;
2710 md_cksum[md_i] = 0;
2711 } // for md_i 16
2712
2713 _asm
2714 movlw 0x01
2715 movwf TBLPTRU,0
2716 movlw 0x06
2717 movwf TBLPTRH,0
2718 movlw 0x00
2719 movwf TBLPTRL,0
2720 _endasm
2721 for (md_i=0;md_i<127;md_i++)
2722 {
2723 _asm
2724 TBLRDPOSTINC
2725 movff TABLAT,md_temp
2726 _endasm
2727 md_pi_subst[md_i] = md_temp;
2728 } // for md_i 256
2729 _asm
2730 TBLRDPOSTINC
2731 movff TABLAT,md_temp
2732 _endasm
2733 md_pi_subst[127] = md_temp;
2734 for (md_i=0;md_i<127;md_i++)
2735 {
2736 _asm
2737 TBLRDPOSTINC
2738 movff TABLAT,md_temp
2739 _endasm
2740 md_pi_subst[md_i+128] = md_temp;
2741 } // for md_i 256
2742 _asm
2743 TBLRD
2744 movff TABLAT,md_temp
2745 _endasm
2746 md_pi_subst[255] = md_temp;
2747
2748 _asm
2749 movlw 0x00
2750 movwf TBLPTRU,0
2751 movlw 0x00
2752 movwf TBLPTRH,0
2753 movlw 0x00
2754 movwf TBLPTRL,0
2755 _endasm
2756 // cycle buffers
2757 for (md_pointer=0x0000;md_pointer<0x17f3;md_pointer++)
2758 {
2759 md_t = 0;
2760 for (md_i=0;md_i<16;md_i++)
2761 {
2762 if(md_pointer == 9)
2763 md_temp = md_cksum[md_i];
2764 else
2765 {
2766 _asm
2767 TBLRDPOSTINC
2768 movff TABLAT,md_temp
2769 _endasm
2770 } // else
2771 md_buffer[md_i] = md_temp;
2772 md_state[md_i+16] = md_buffer[md_i];
2773 md_state[md_i+32] = (unsigned char)(md_buffer[md_i] ^ md_state[md_i]);
2774 } // for md_i 16
2775
2776 for (md_i=0;md_i<18;md_i++)
2777 {
2778 for (md_j=0;md_j<48;md_j++)
2779 {
2780 md_state[md_j] = (unsigned char)(md_state[md_j] ^ md_pi_subst[md_t]);
2781 md_t = md_state[md_j];
2782 } // for md_j 48
2783 md_t = (unsigned char)(md_t+1);
2784 } // for md_i 18
2785 md_t = md_cksum[15];
2786
2787 for (md_i=0;md_i<16;md_i++)
2788 {
2789 md_cksum[md_i] = (unsigned char)(md_cksum[md_i] ^ md_pi_subst[(md_buffer[md_i] ^ md_t)]);
2790 md_t = md_cksum[md_i];
2791 } // for md_i 16
2792 } // for md_pointer
2793 } // void hash(void)
2794
2795 // ---------------------
2796 // clear_CNS_fraction //
2797 // ---------------------
2798 // new in v.101
2799
2800 void clear_CNS_fraction(void)
2801 {
2802 CNS_fraction = 0.0;
2803 char_O_CNS_fraction = 0;
2804 } // void clear_CNS_fraction(void)
2805
2806
2807 // --------------------
2808 // calc_CNS_fraction //
2809 // --------------------
2810 // new in v.101
2811 // optimized in v.102 : with new variables char_I_actual_ppO2 and actual_ppO2
2812
2813 // Input: char_I_actual_ppO2
2814 // Output: char_O_CNS_fraction
2815 // Uses and Updates: CNS_fraction
2816 // Uses: acutal_ppO2
2817
2818 void calc_CNS_fraction(void)
2819 {
2820 actual_ppO2 = (float)char_I_actual_ppO2 / 100.0;
2821
2822 if (char_I_actual_ppO2 < 50)
2823 CNS_fraction = CNS_fraction;// no changes
2824 else if (char_I_actual_ppO2 < 60)
2825 CNS_fraction = 1/(-54000.0 * actual_ppO2 + 54000.0) + CNS_fraction;
2826 else if (char_I_actual_ppO2 < 70)
2827 CNS_fraction = 1/(-45000.0 * actual_ppO2 + 48600.0) + CNS_fraction;
2828 else if (char_I_actual_ppO2 < 80)
2829 CNS_fraction = 1/(-36000.0 * actual_ppO2 + 42300.0) + CNS_fraction;
2830 else if (char_I_actual_ppO2 < 90)
2831 CNS_fraction = 1/(-27000.0 * actual_ppO2 + 35100.0) + CNS_fraction;
2832 else if (char_I_actual_ppO2 < 110)
2833 CNS_fraction = 1/(-18000.0 * actual_ppO2 + 27000.0) + CNS_fraction;
2834 else if (char_I_actual_ppO2 < 150)
2835 CNS_fraction = 1/(-9000.0 * actual_ppO2 + 17100.0) + CNS_fraction;
2836 else if (char_I_actual_ppO2 < 160)
2837 CNS_fraction = 1/(-22500.0 * actual_ppO2 + 37350.0) + CNS_fraction;
2838 else if (char_I_actual_ppO2 < 165)
2839 CNS_fraction = 0.000755 + CNS_fraction; // Arieli et all.(2002): Modeling pulmonary and CNS O2 toxicity... Formula (A1) based on value for 1.55 and c=20
2840 else if (char_I_actual_ppO2 < 170)
2841 CNS_fraction = 0.00102 + CNS_fraction; // example calculation: Sqrt((1.7/1.55)^20)*0.000404
2842 else if (char_I_actual_ppO2 < 175)
2843 CNS_fraction = 0.00136 + CNS_fraction;
2844 else if (char_I_actual_ppO2 < 180)
2845 CNS_fraction = 0.00180 + CNS_fraction;
2846 else if (char_I_actual_ppO2 < 185)
2847 CNS_fraction = 0.00237 + CNS_fraction;
2848 else if (char_I_actual_ppO2 < 190)
2849 CNS_fraction = 0.00310 + CNS_fraction;
2850 else if (char_I_actual_ppO2 < 195)
2851 CNS_fraction = 0.00401 + CNS_fraction;
2852 else if (char_I_actual_ppO2 < 200)
2853 CNS_fraction = 0.00517 + CNS_fraction;
2854 else if (char_I_actual_ppO2 < 230)
2855 CNS_fraction = 0.0209 + CNS_fraction;
2856 else
2857 CNS_fraction = 0.0482 + CNS_fraction; // value for 2.5
2858
2859 if (CNS_fraction > 2.5)
2860 CNS_fraction = 2.5;
2861 if (CNS_fraction < 0.0)
2862 CNS_fraction = 0.0;
2863 char_O_CNS_fraction = (char)((CNS_fraction + 0.005)* 100.0);
2864 } // void calc_CNS_fraction(void)
2865
2866 // --------------------------
2867 // calc_CNS_decrease_15min //
2868 // --------------------------
2869 // new in v.101
2870
2871 // calculates the half time of 90 minutes in 6 steps of 15 min
2872
2873 // Output: char_O_CNS_fraction
2874 // Uses and Updates: CNS_fraction
2875
2876 void calc_CNS_decrease_15min(void)
2877 {
2878 CNS_fraction = 0.890899 * CNS_fraction;
2879 char_O_CNS_fraction = (char)((CNS_fraction + 0.005)* 100.0);
2880 }// calc_CNS_decrease_15min(void)
2881
2882
2883 // ------------------
2884 // calc_percentage //
2885 // ------------------
2886 // new in v.101
2887
2888 // calculates int_I_temp * char_I_temp / 100
2889 // output is int_I_temp
2890
2891 void calc_percentage(void)
2892 {
2893 temp1 = (float)int_I_temp;
2894 temp2 = (float)char_I_temp / 100.0;
2895 temp3 = temp1 * temp2;
2896 int_I_temp = (int)temp3;
2897 }
2898 void push_tissues_to_vault(void)
2899 {
2900 for (ci=0;ci<32;ci++)
2901 pres_tissue_vault[ci] = pres_tissue[ci];
2902 }
2903 void pull_tissues_from_vault(void)
2904 {
2905 for (ci=0;ci<32;ci++)
2906 pres_tissue[ci] = pres_tissue_vault[ci];
2907 }
2908
2909 void wp_write_command(void)
2910 {
2911 _asm
2912 bcf oled_rs
2913 movff wp_command,PORTD
2914 bcf oled_rw
2915 bsf oled_rw
2916 _endasm
2917 }
2918
2919 void wp_write_data(void)
2920 {
2921 wp_data_8bit_one = wp_data_16bit >> 8;
2922 wp_data_8bit_two = wp_data_16bit;
2923 _asm
2924 bsf oled_rs
2925 movff wp_data_8bit_one,PORTD
2926 bcf oled_rw
2927 bsf oled_rw
2928 movff wp_data_8bit_two,PORTD
2929 bcf oled_rw
2930 bsf oled_rw
2931 _endasm
2932 }
2933
2934 void wp_write_black(void)
2935 {
2936 _asm
2937 movff wp_black,PORTD
2938 bcf oled_rw
2939 bsf oled_rw
2940 bcf oled_rw
2941 bsf oled_rw
2942 _endasm
2943 }
2944
2945 void wp_write_color(void)
2946 {
2947 _asm
2948 movff wp_color1,PORTD
2949 bcf oled_rw
2950 bsf oled_rw
2951 movff wp_color2,PORTD
2952 bcf oled_rw
2953 bsf oled_rw
2954 _endasm
2955 }
2956
2957 void wp_set_window(void)
2958 {
2959 // x axis start ( 0 - 319)
2960 wp_command = 0x35;
2961 wp_write_command();
2962 wp_data_16bit = ((U16)wp_leftx2) << 1;
2963 wp_write_data();
2964 // x axis end ( 0 - 319)
2965 wp_command = 0x36;
2966 wp_write_command();
2967 wp_data_16bit = 319;
2968 wp_write_data();
2969 // y axis start + end ( 0 - 239 )
2970 wp_command = 0x37;
2971 wp_write_command();
2972 // the bottom part
2973 wp_data_16bit = wp_top;
2974 if(wp_font == 2)
2975 wp_data_16bit += WP_FONT_LARGE_HEIGHT;
2976 else if(wp_font == 1)
2977 wp_data_16bit += WP_FONT_MEDIUM_HEIGHT;
2978 else
2979 wp_data_16bit += WP_FONT_SMALL_HEIGHT;
2980 wp_data_16bit--;
2981 if(wp_data_16bit > 239)
2982 wp_data_16bit = 239;
2983 // the top part
2984 wp_data_16bit |= ((U16)wp_top) << 8;
2985 // all together in one 16bit transfer
2986 wp_write_data();
2987
2988 // start
2989 wp_command = 0x20;
2990 wp_write_command();
2991 wp_data_16bit = wp_top;
2992 wp_write_data();
2993
2994 wp_command = 0x21;
2995 wp_write_command();
2996 wp_data_16bit = ((U16)wp_leftx2) << 1;
2997 wp_write_data();
2998 }
2999
3000 void wp_set_char_font_small(void)
3001 {
3002 if (wp_char == ' ')
3003 wp_char = '¶';
3004
3005 if((wp_char < '!') || (wp_char > '¶')) // font has 34 chars after ~ // ¾ + 4 chars limit to end of battery at the moment
3006 wp_char = '¤'; // 0x82; // ¤
3007
3008 if (wp_char > 0x7E) // skip space between ~ and ¡
3009 wp_char -= 34;
3010
3011 wp_start = wp_small_table[wp_char - '!'];
3012 wp_end = wp_small_table[1 + wp_char - '!'];
3013 }
3014
3015 void wp_set_char_font_medium(void)
3016 {
3017 // space is 3E
3018 if (wp_char == 0x27) // 0x27 == '
3019 wp_char = 0x3B;
3020 if (wp_char == '"')
3021 wp_char = 0x3C;
3022 if (wp_char == 'm')
3023 wp_char = 0x3D;
3024 if (wp_char == ' ')
3025 wp_char = 0x3E;
3026
3027 if((wp_char < '.') || (wp_char > 0x3E))
3028 wp_char = 0x3E;
3029 wp_start = wp_medium_table[wp_char - '.'];
3030 wp_end = wp_medium_table[1 + wp_char - '.'];
3031 }
3032
3033 void wp_set_char_font_large(void)
3034 {
3035 // space is / = 0x2F
3036 if (wp_char == ' ')
3037 wp_char = 0x2F;
3038
3039 if((wp_char < '.') || (wp_char > '9'))
3040 wp_char = 0x2F;
3041 wp_start = wp_large_table[wp_char - '.'];
3042 wp_end = wp_large_table[1 + wp_char - '.'];
3043 }
3044
3045 void wordprocessor(void)
3046 {
3047 wp_set_window();
3048
3049 // access to GRAM
3050 wp_command = 0x22;
3051 wp_write_command();
3052 _asm
3053 bsf oled_rs
3054 _endasm
3055
3056 wp_txtptr = 0;
3057 wp_char = wp_stringstore[wp_txtptr];
3058
3059 while(wp_char)
3060 {
3061 if(wp_font == 2)
3062 wp_set_char_font_large();
3063 else if(wp_font == 1)
3064 wp_set_char_font_medium();
3065 else
3066 wp_set_char_font_small();
3067
3068 wp_black = 0;
3069
3070 for(wp_i = wp_start; wp_i<wp_end;wp_i++)
3071 {
3072 if(wp_font == 2)
3073 wp_data_16bit = wp_large_data[wp_i / 2];
3074 else if(wp_font == 1)
3075 wp_data_16bit = wp_medium_data[wp_i / 2];
3076 else
3077 wp_data_16bit = wp_small_data[wp_i / 2];
3078 if(wp_i & 1)
3079 wp_temp_U8 = wp_data_16bit & 0xFF;
3080 else
3081 wp_temp_U8 = wp_data_16bit >> 8;
3082 if((wp_temp_U8 & 128))
3083 {
3084 wp_temp_U8 -= 127;
3085 if(wp_invert)
3086 {
3087 while(wp_temp_U8 > 0)
3088 {
3089 wp_temp_U8--;
3090 wp_write_color();
3091 }
3092 }
3093 else
3094 {
3095 _asm
3096 movff wp_black,PORTD
3097 _endasm
3098 while(wp_temp_U8 > 0)
3099 {
3100 wp_temp_U8--;
3101 _asm
3102 bcf oled_rw
3103 bsf oled_rw
3104 bcf oled_rw
3105 bsf oled_rw
3106 _endasm
3107 }
3108 }
3109 }
3110 else
3111 {
3112 wp_temp_U8++;
3113 if(wp_invert)
3114 {
3115 _asm
3116 movff wp_black,PORTD
3117 _endasm
3118 while(wp_temp_U8 > 0)
3119 {
3120 wp_temp_U8--;
3121 _asm
3122 bcf oled_rw
3123 bsf oled_rw
3124 bcf oled_rw
3125 bsf oled_rw
3126 _endasm
3127 }
3128 }
3129 else
3130 {
3131 while(wp_temp_U8 > 0)
3132 {
3133 wp_temp_U8--;
3134 wp_write_color();
3135 }
3136 }
3137 }
3138 }
3139 wp_txtptr++;
3140 wp_char = wp_stringstore[wp_txtptr];
3141 }
3142 wp_command = 0x00;
3143 wp_write_command();
3144 }