Mercurial > public > ostc4
comparison Discovery/Src/simulation.c @ 983:7891160acde3 GasConsumption
Bugfix calculation of needed gas:
Sometimes a gas was not calculated because of it's change depth calculation. Rootcause was a problem in the setup of the gas change list. The old function collecting milestones like time to first stop etc. has been removed because after the deco compression the complete profile is available. Instead of doing another way of profile calculation the existing profil is now evaluated and the time stamps / gas consumption derived from there.
| author | Ideenmodellierer |
|---|---|
| date | Sun, 02 Mar 2025 21:43:08 +0100 |
| parents | 7149f372b0ba |
| children | 5a690195b6b7 |
comparison
equal
deleted
inserted
replaced
| 982:22d5b477c903 | 983:7891160acde3 |
|---|---|
| 497 { | 497 { |
| 498 pDecoinfo->output_time_to_surface_seconds--; | 498 pDecoinfo->output_time_to_surface_seconds--; |
| 499 } | 499 } |
| 500 } | 500 } |
| 501 | 501 |
| 502 SDecoinfo* simulation_decoplaner(uint16_t depth_meter, uint16_t intervall_time_minutes, uint16_t dive_time_minutes, uint8_t *gasChangeListDepthGas20x2) | 502 SDecoinfo* simulation_decoplaner(uint16_t depth_meter, uint16_t intervall_time_minutes, uint16_t dive_time_minutes, SgasChangeList *pGasChangeList) |
| 503 { | 503 { |
| 504 uint8_t ptrGasChangeList = 0; // new hw 160704 | 504 uint8_t GasChangeIndex = 0; |
| 505 #ifdef ENABLE_DECOCALC_OPTION | 505 |
| 506 uint8_t index = 0; | 506 for (GasChangeIndex = 0; GasChangeIndex < GAS_CHANGE_LIST_ITEMS; GasChangeIndex++) |
| 507 #endif | 507 { |
| 508 for (int i = 0; i < 40; i++) | 508 pGasChangeList[GasChangeIndex].depth = 0; |
| 509 gasChangeListDepthGas20x2[i] = 0; | 509 pGasChangeList[GasChangeIndex].gasId = 0; |
| 510 | 510 } |
| 511 SDiveState * pDiveState = &stateSim; | 511 SDiveState * pDiveState = &stateSim; |
| 512 copyDiveSettingsToSim(); | 512 copyDiveSettingsToSim(); |
| 513 | |
| 514 #ifdef ENABLE_DECOCALC_OPTION | |
| 515 /* activate deco calculation for all deco gases */ | |
| 516 for(index = 0; index < 1 + (2*NUM_GASES); index++) | |
| 517 { | |
| 518 if(pDiveState->diveSettings.gas[index].note.ub.deco) | |
| 519 { | |
| 520 pDiveState->diveSettings.gas[index].note.ub.decocalc = 1; | |
| 521 } | |
| 522 } | |
| 523 #endif | |
| 524 | 513 |
| 525 vpm_init(&pDiveState->vpm, pDiveState->diveSettings.vpm_conservatism, 0, 0); | 514 vpm_init(&pDiveState->vpm, pDiveState->diveSettings.vpm_conservatism, 0, 0); |
| 526 //buehlmann_init(); | 515 //buehlmann_init(); |
| 527 //timer_init(); | 516 //timer_init(); |
| 528 memset(&pDiveState->events,0, sizeof(SEvents)); | 517 memset(&pDiveState->events,0, sizeof(SEvents)); |
| 536 } | 525 } |
| 537 | 526 |
| 538 //Switch to first Gas | 527 //Switch to first Gas |
| 539 setActualGasFirst(&pDiveState->lifeData); | 528 setActualGasFirst(&pDiveState->lifeData); |
| 540 | 529 |
| 541 // new hw 160704 | 530 GasChangeIndex = 0; |
| 542 if(gasChangeListDepthGas20x2) | 531 |
| 543 { | 532 if(pGasChangeList) |
| 544 gasChangeListDepthGas20x2[ptrGasChangeList++] = 0; | 533 { |
| 545 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->lifeData.actualGas.GasIdInSettings; | 534 pGasChangeList[GasChangeIndex].depth = 0; |
| 546 gasChangeListDepthGas20x2[0] =0; // depth zero | 535 pGasChangeList[GasChangeIndex].gasId = pDiveState->lifeData.actualGas.GasIdInSettings; |
| 536 GasChangeIndex++; | |
| 547 } | 537 } |
| 548 | 538 |
| 549 //Going down / descent | 539 //Going down / descent |
| 550 simulation_set_aim_depth(depth_meter); | 540 simulation_set_aim_depth(depth_meter); |
| 551 sim_aim_time_minutes = 0; | 541 sim_aim_time_minutes = 0; |
| 554 simulation_UpdateLifeData(0); | 544 simulation_UpdateLifeData(0); |
| 555 check_warning2(pDiveState); | 545 check_warning2(pDiveState); |
| 556 if(pDiveState->warnings.betterGas) | 546 if(pDiveState->warnings.betterGas) |
| 557 { | 547 { |
| 558 setActualGas(&pDiveState->lifeData,actualBetterGasId(),pDiveState->lifeData.actualGas.setPoint_cbar); | 548 setActualGas(&pDiveState->lifeData,actualBetterGasId(),pDiveState->lifeData.actualGas.setPoint_cbar); |
| 559 if(gasChangeListDepthGas20x2 && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) | 549 if(pGasChangeList && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) |
| 560 { | 550 { |
| 561 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->lifeData.depth_meter; | 551 pGasChangeList[GasChangeIndex].depth = pDiveState->lifeData.depth_meter; |
| 562 gasChangeListDepthGas20x2[ptrGasChangeList++] = actualBetterGasId(); | 552 pGasChangeList[GasChangeIndex].gasId = actualBetterGasId(); |
| 553 GasChangeIndex++; | |
| 563 } | 554 } |
| 564 } | 555 } |
| 565 } | 556 } |
| 566 | 557 |
| 567 decom_CreateGasChangeList(&pDiveState->diveSettings, &pDiveState->lifeData); // was there before and needed for buehlmann_calc_deco and vpm_calc | 558 decom_CreateGasChangeList(&pDiveState->diveSettings, &pDiveState->lifeData); // was there before and needed for buehlmann_calc_deco and vpm_calc |
| 568 | 559 |
| 569 // new hw 160704 | 560 if(pGasChangeList && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) |
| 570 if(gasChangeListDepthGas20x2 && (pDiveState->diveSettings.diveMode == DIVEMODE_OC)) | |
| 571 { | 561 { |
| 572 // change direction from better gas to deco gas | 562 // change direction from better gas to deco gas |
| 573 gasChangeListDepthGas20x2[ptrGasChangeList++] = 255; | 563 pGasChangeList[GasChangeIndex].depth = 255; |
| 574 gasChangeListDepthGas20x2[ptrGasChangeList++] = 255; | 564 pGasChangeList[GasChangeIndex].gasId = 255; |
| 565 GasChangeIndex++; | |
| 575 | 566 |
| 576 // ascend (deco) gases | 567 // ascend (deco) gases |
| 577 for(int i=1; i<=5;i++) | 568 for(int i=1; i<=5;i++) |
| 578 { | 569 { |
| 579 if((pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | 570 if((pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero != 0) |
| 580 #ifdef ENABLE_DECOCALC_OPTION | 571 && (pDiveState->diveSettings.gas[pDiveState->diveSettings.decogaslist[i].GasIdInSettings].note.ub.deco)) |
| 581 || (pDiveState->diveSettings.gas[pDiveState->diveSettings.decogaslist[i].GasIdInSettings].note.ub.decocalc == 0) | 572 { |
| 582 #endif | 573 pGasChangeList[GasChangeIndex].depth = pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero; |
| 583 ) | 574 pGasChangeList[GasChangeIndex].gasId = pDiveState->diveSettings.decogaslist[i].GasIdInSettings; |
| 584 break; | 575 GasChangeIndex++; |
| 585 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero; | 576 } |
| 586 gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].GasIdInSettings; | 577 } |
| 587 } | |
| 588 gasChangeListDepthGas20x2[0] = 0; | |
| 589 } | 578 } |
| 590 | 579 |
| 591 // deco and ascend calc | 580 // deco and ascend calc |
| 592 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | 581 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) |
| 593 { | 582 { |
| 625 ambient = (meter + surface); | 614 ambient = (meter + surface); |
| 626 | 615 |
| 627 return ambient; | 616 return ambient; |
| 628 } | 617 } |
| 629 | 618 |
| 630 | 619 void getNextDecoDepthAndTime(uint8_t* pDepth, uint16_t* pTime, uint8_t currentDepth, SDecoinfo *decoInfoInput) |
| 631 /** | 620 { |
| 632 ****************************************************************************** | 621 uint8_t depthLast, depthSecond, depthInc; |
| 633 * @brief simulation_helper_change_points | 622 uint8_t decoIndex = 0; |
| 634 ****************************************************************************** | 623 |
| 635 * @param | 624 depthLast = (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10); |
| 636 * @return void | 625 depthSecond = (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10); |
| 637 */ | 626 depthInc = (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10); |
| 638 void simulation_helper_change_points(SSimDataSummary *outputSummary, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, const uint8_t *gasChangeListDepthGas20x2) | 627 |
| 639 { | 628 if(currentDepth > depthLast) |
| 640 uint8_t ptrDecoInfo = 0; | 629 { |
| 641 uint16_t actualDepthPoint = 0; | 630 for(decoIndex = DECOINFO_STRUCT_MAX_STOPS-1; decoIndex > 0; decoIndex--) |
| 642 uint16_t nextDepthPoint = 0; | 631 { |
| 643 uint8_t actualConsumGasId = 0; | 632 if(decoInfoInput->output_stop_length_seconds[decoIndex]) |
| 633 { | |
| 634 *pDepth = depthSecond + ( decoIndex - 1 ) * depthInc; | |
| 635 if(*pDepth < currentDepth) | |
| 636 { | |
| 637 break; | |
| 638 } | |
| 639 } | |
| 640 } | |
| 641 | |
| 642 if(decoIndex == 0) | |
| 643 { | |
| 644 *pDepth = depthLast; | |
| 645 } | |
| 646 *pTime = decoInfoInput->output_stop_length_seconds[decoIndex]; | |
| 647 } | |
| 648 else | |
| 649 { | |
| 650 *pDepth = 0; | |
| 651 *pTime = 0; | |
| 652 } | |
| 653 } | |
| 654 | |
| 655 void simulation_evaluate_profil(uint16_t *outputConsumptionList, | |
| 656 SSimDataSummary *outputSummary, | |
| 657 uint16_t depth_meter, uint16_t dive_time_minutes,uint8_t gasConsumTravelInput, uint8_t gasConsumDecoInput, | |
| 658 SDecoinfo *decoInfoInput, | |
| 659 const SgasChangeList *pGasChangeList) | |
| 660 { | |
| 661 uint16_t nextDecoTime = 0; | |
| 662 uint8_t nextDecoDepth = 0; | |
| 663 | |
| 664 uint8_t currentConsumGasId = 0; | |
| 644 uint8_t nextGasChangeMeter = 0; | 665 uint8_t nextGasChangeMeter = 0; |
| 645 uint8_t ptrChangeList = 0; | 666 uint8_t nextGasChangeGasId = 0; |
| 646 | 667 uint8_t ChangeListIndex = 0; |
| 647 float timeThis = 0; | 668 uint8_t firstDecoGasIndex = 0; |
| 648 float timeSummary = 0; | 669 float outputConsumptionTempFloat[6]; |
| 649 float sim_descent_rate_meter_per_min_local = 10; | 670 |
| 650 float sim_ascent_rate_meter_per_min_local = 10; | 671 float sim_descent_rate_meter_per_sec_local = 10.0; |
| 672 float sim_ascent_rate_meter_per_sec_local = 10.0; | |
| 673 | |
| 674 float currentDepth_m = 0.0; | |
| 675 uint16_t currentTime_sec = 0; | |
| 676 float currentGasConsumption = 0.0; | |
| 651 | 677 |
| 652 SDiveState * pDiveState = &stateSim; | 678 SDiveState * pDiveState = &stateSim; |
| 653 | 679 |
| 654 uint8_t depthDecoNext, depthLast, depthSecond, depthInc; | 680 for(ChangeListIndex = 0; ChangeListIndex < 6; ChangeListIndex++) |
| 681 { | |
| 682 outputConsumptionTempFloat[ChangeListIndex] = 0.0; | |
| 683 } | |
| 655 | 684 |
| 656 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | 685 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) |
| 657 { | 686 { |
| 658 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | 687 sim_descent_rate_meter_per_sec_local = sim_descent_rate_meter_per_min / 60.0; |
| 659 sim_ascent_rate_meter_per_min_local = pDiveState->diveSettings.ascentRate_meterperminute; | 688 sim_ascent_rate_meter_per_sec_local = pDiveState->diveSettings.ascentRate_meterperminute / 60.0; |
| 660 } | 689 } |
| 661 else | 690 else |
| 662 { | 691 { |
| 663 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | 692 sim_descent_rate_meter_per_sec_local = sim_descent_rate_meter_per_min / 60.0; |
| 664 sim_ascent_rate_meter_per_min_local = 10;// fix in vpm_calc_deco(); | 693 sim_ascent_rate_meter_per_sec_local = 10.0 / 60.0; // fix in vpm_calc_deco(); |
| 665 } | 694 } |
| 666 | 695 |
| 667 outputSummary->descentRateMeterPerMinute = sim_descent_rate_meter_per_min_local; | 696 outputSummary->descentRateMeterPerMinute = sim_descent_rate_meter_per_sec_local * 60; |
| 668 outputSummary->ascentRateMeterPerMinute = sim_ascent_rate_meter_per_min_local; | 697 outputSummary->ascentRateMeterPerMinute = sim_ascent_rate_meter_per_sec_local * 60; |
| 669 | 698 outputSummary->timeToBottom = 0; |
| 670 // bottom gas ppO2 | 699 outputSummary->timeToFirstStop = 0; |
| 671 if(gasChangeListDepthGas20x2) | 700 outputSummary->depthMeterFirstStop = 0; |
| 672 { | 701 outputSummary->timeAtBottom = 0; |
| 673 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | 702 outputSummary->timeToSurface = 0; |
| 674 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | 703 |
| 675 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | 704 currentConsumGasId = pGasChangeList[0].gasId; |
| 676 | 705 |
| 677 while(actualDepthPoint < depth_meter) | 706 /* ascent + at depth loop at the moment work gas does not support change depth => no need to check */ |
| 678 { | 707 while(currentTime_sec < dive_time_minutes * 60) |
| 679 if(nextGasChangeMeter && (nextGasChangeMeter < depth_meter) && (gasChangeListDepthGas20x2[ptrChangeList] != 255)) // list has 255,255 for turn from travel to deco | 708 { |
| 680 { | 709 if(currentDepth_m < depth_meter) |
| 681 nextDepthPoint = nextGasChangeMeter; | 710 { |
| 682 } | 711 currentDepth_m += sim_descent_rate_meter_per_sec_local; |
| 683 else | 712 currentGasConsumption = ((float)gasConsumTravelInput) * sGChelper_bar(currentDepth_m ) / 60.0; |
| 684 { | 713 } |
| 685 nextDepthPoint = depth_meter; | 714 else |
| 686 } | 715 { |
| 687 | 716 if(outputSummary->timeToBottom == 0) |
| 688 if(actualConsumGasId > 5) // safety first | 717 { |
| 689 actualConsumGasId = 0; | 718 currentDepth_m = depth_meter; |
| 690 | 719 outputSummary->timeToBottom = currentTime_sec / 60; |
| 691 actualDepthPoint = nextDepthPoint; | 720 outputSummary->ppO2AtBottom = (sGChelper_bar(depth_meter) - WATER_VAPOUR_PRESSURE) * pDiveState->diveSettings.gas[currentConsumGasId].oxygen_percentage / 100.0f; |
| 692 | 721 } |
| 693 if(actualDepthPoint != depth_meter) | 722 } |
| 694 { | 723 currentTime_sec++; |
| 695 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | 724 outputConsumptionTempFloat[currentConsumGasId] += currentGasConsumption; |
| 696 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | 725 } |
| 697 } | 726 |
| 698 } | 727 outputSummary->timeAtBottom = (currentTime_sec / 60); /* - outputSummary->timeToBottom; */ |
| 728 | |
| 729 /* move forward to deco gas section (behind 255 entry) */ | |
| 730 for(ChangeListIndex = 0; ChangeListIndex < GAS_CHANGE_LIST_ITEMS; ChangeListIndex++) | |
| 731 { | |
| 732 if(pGasChangeList[ChangeListIndex].depth == 255) | |
| 733 { | |
| 734 ChangeListIndex++; | |
| 735 firstDecoGasIndex = ChangeListIndex; | |
| 736 nextGasChangeMeter = pGasChangeList[firstDecoGasIndex].depth; | |
| 737 nextGasChangeGasId = pGasChangeList[firstDecoGasIndex].gasId; | |
| 738 } | |
| 739 if((firstDecoGasIndex != 0) && (pGasChangeList[ChangeListIndex].depth > nextGasChangeMeter) /* find deepest gas switch */ | |
| 740 && (pGasChangeList[ChangeListIndex].depth < currentDepth_m)) | |
| 741 { | |
| 742 nextGasChangeMeter = pGasChangeList[ChangeListIndex].depth; | |
| 743 nextGasChangeGasId = pGasChangeList[ChangeListIndex].gasId; | |
| 744 } | |
| 745 } | |
| 746 | |
| 747 /* do ascent with stops */ | |
| 748 getNextDecoDepthAndTime(&nextDecoDepth, &nextDecoTime, currentDepth_m, decoInfoInput); | |
| 749 while(currentDepth_m > 0) | |
| 750 { | |
| 751 if(currentDepth_m > nextDecoDepth) | |
| 752 { | |
| 753 currentDepth_m -= sim_ascent_rate_meter_per_sec_local; | |
| 754 currentGasConsumption = ((float)gasConsumDecoInput) * sGChelper_bar(currentDepth_m ) / 60.0; | |
| 755 } | |
| 756 else | |
| 757 { | |
| 758 if(outputSummary->timeToFirstStop == 0) | |
| 759 { | |
| 760 currentDepth_m = nextDecoDepth; | |
| 761 outputSummary->timeToFirstStop = currentTime_sec / 60; | |
| 762 outputSummary->depthMeterFirstStop = nextDecoDepth; | |
| 763 } | |
| 764 if(nextDecoTime) | |
| 765 { | |
| 766 nextDecoTime--; | |
| 767 } | |
| 768 else | |
| 769 { | |
| 770 getNextDecoDepthAndTime(&nextDecoDepth, &nextDecoTime, currentDepth_m, decoInfoInput); | |
| 771 } | |
| 772 } | |
| 773 if(currentDepth_m <= nextGasChangeMeter) /* switch gas ? */ | |
| 774 { | |
| 775 nextGasChangeMeter = 0; | |
| 776 currentConsumGasId = nextGasChangeGasId; | |
| 777 for(ChangeListIndex = firstDecoGasIndex; ChangeListIndex < GAS_CHANGE_LIST_ITEMS; ChangeListIndex++) | |
| 778 { | |
| 779 if((pGasChangeList[ChangeListIndex].depth > nextGasChangeMeter) /* find deepest gas switch */ | |
| 780 && (pGasChangeList[ChangeListIndex].depth < currentDepth_m)) | |
| 781 { | |
| 782 nextGasChangeMeter = pGasChangeList[ChangeListIndex].depth; | |
| 783 nextGasChangeGasId = pGasChangeList[ChangeListIndex].gasId; | |
| 784 } | |
| 785 } | |
| 786 } | |
| 787 currentTime_sec++; | |
| 788 outputConsumptionTempFloat[currentConsumGasId] += currentGasConsumption; | |
| 789 } | |
| 790 | |
| 791 if(decoInfoInput->output_time_to_surface_seconds) | |
| 792 { | |
| 793 outputSummary->timeToSurface = outputSummary->timeAtBottom + (decoInfoInput->output_time_to_surface_seconds / 60); | |
| 699 } | 794 } |
| 700 else | 795 else |
| 701 { | 796 { |
| 702 actualConsumGasId = pDiveState->lifeData.actualGas.GasIdInSettings; | 797 outputSummary->timeToSurface = currentTime_sec / 60; |
| 703 nextGasChangeMeter = 0; | 798 } |
| 704 } | 799 |
| 705 outputSummary->ppO2AtBottom = (sGChelper_bar(depth_meter) - WATER_VAPOUR_PRESSURE) * pDiveState->diveSettings.gas[actualConsumGasId].oxygen_percentage / 100.0f; | 800 for(ChangeListIndex = 0; ChangeListIndex < 6; ChangeListIndex++) |
| 706 | 801 { |
| 707 | 802 outputConsumptionList[ChangeListIndex] = (uint16_t)outputConsumptionTempFloat[ChangeListIndex]; |
| 708 // going down | 803 } |
| 709 actualDepthPoint = 0; | 804 } |
| 710 nextDepthPoint = depth_meter; | 805 |
| 711 | |
| 712 timeThis = ((float)(nextDepthPoint - actualDepthPoint)) / sim_descent_rate_meter_per_min_local; | |
| 713 timeSummary += timeThis; | |
| 714 outputSummary->timeToBottom = (uint16_t)timeThis; | |
| 715 | |
| 716 // bottom time | |
| 717 timeThis = ((float)dive_time_minutes) - timeSummary; | |
| 718 timeSummary += timeThis; | |
| 719 outputSummary->timeAtBottom = (uint16_t)timeSummary; | |
| 720 | |
| 721 | |
| 722 // ascend to first deco stop | |
| 723 actualDepthPoint = depth_meter; // that is where we are | |
| 724 timeThis = 0; | |
| 725 | |
| 726 if(!decoInfoInput->output_stop_length_seconds[0]) // NDL dive | |
| 727 { | |
| 728 depthLast = 0; | |
| 729 ptrDecoInfo = 0; | |
| 730 depthDecoNext = 0; | |
| 731 } | |
| 732 else | |
| 733 { | |
| 734 // prepare deco stop list | |
| 735 depthLast = (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10); | |
| 736 depthSecond = (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10); | |
| 737 depthInc = (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10); | |
| 738 | |
| 739 for(ptrDecoInfo=DECOINFO_STRUCT_MAX_STOPS-1; ptrDecoInfo>0; ptrDecoInfo--) | |
| 740 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; | |
| 741 | |
| 742 if(ptrDecoInfo == 0) | |
| 743 { | |
| 744 depthDecoNext = depthLast; | |
| 745 } | |
| 746 else | |
| 747 depthDecoNext = depthSecond + (( ptrDecoInfo - 1 )* depthInc); | |
| 748 } | |
| 749 | |
| 750 nextDepthPoint = depthDecoNext; | |
| 751 if(actualDepthPoint > nextDepthPoint) | |
| 752 { | |
| 753 // flip signs! It's going up | |
| 754 timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; | |
| 755 actualDepthPoint = nextDepthPoint; // that is where we are | |
| 756 } | |
| 757 timeSummary += timeThis; | |
| 758 outputSummary->timeToFirstStop = (uint16_t)timeSummary; | |
| 759 outputSummary->depthMeterFirstStop = actualDepthPoint; | |
| 760 | |
| 761 if(decoInfoInput->output_time_to_surface_seconds) | |
| 762 { | |
| 763 outputSummary->timeToSurface = outputSummary->timeAtBottom + (decoInfoInput->output_time_to_surface_seconds / 60); | |
| 764 } | |
| 765 else | |
| 766 { | |
| 767 outputSummary->timeToSurface = outputSummary->timeToFirstStop; | |
| 768 } | |
| 769 } | |
| 770 | |
| 771 | |
| 772 /** | |
| 773 ****************************************************************************** | |
| 774 * @brief simulation_gas_consumption | |
| 775 ****************************************************************************** | |
| 776 * @note called by openEdit_PlanResult() in tMenuEditPlanner.c | |
| 777 * @note the ascend and descend time is taken from pDiveState->lifeData.ascent_rate_meter_per_min and const float sim_descent_rate_meter_per_min | |
| 778 * @param outputConsumptionList list from 1 to 5 for gas 1 to 5 | |
| 779 * @param depth_meter for descend | |
| 780 * @param dive_time_minutes for descend and bottom time | |
| 781 * @param the calculated deco list | |
| 782 * @param gasConsumTravelInput: how many l/min for all but deco stops | |
| 783 * @param gasConsumDecoInput: how many l/min for deco stops only | |
| 784 * @return void | |
| 785 */ | |
| 786 | |
| 787 void simulation_gas_consumption(uint16_t *outputConsumptionList, uint16_t depth_meter, uint16_t dive_time_minutes, SDecoinfo *decoInfoInput, uint8_t gasConsumTravelInput, uint8_t gasConsumDecoInput, const uint8_t *gasChangeListDepthGas20x2) | |
| 788 { | |
| 789 uint8_t ptrDecoInfo = 0; | |
| 790 uint8_t ptrChangeList = 0; | |
| 791 uint8_t actualConsumGasId = 0; | |
| 792 uint8_t nextGasChangeMeter = 0; | |
| 793 uint16_t actualDepthPoint = 0; | |
| 794 uint16_t nextDepthPoint = 0; | |
| 795 uint16_t inBetweenDepthPoint = 0; | |
| 796 float timeThis = 0; | |
| 797 float consumThis = 0; | |
| 798 float timeSummary = 0; | |
| 799 float outputConsumptionTempFloat[6]; | |
| 800 float sim_descent_rate_meter_per_min_local = 10; | |
| 801 float sim_ascent_rate_meter_per_min_local = 10; | |
| 802 | |
| 803 SDiveState * pDiveState = &stateSim; | |
| 804 | |
| 805 uint8_t depthDecoNext = 0; | |
| 806 uint8_t depthLast = 0; | |
| 807 uint8_t depthSecond = 0; | |
| 808 uint8_t depthInc = 0; | |
| 809 | |
| 810 for(int i = 1; i < 6; i++) | |
| 811 outputConsumptionTempFloat[i] = 0; | |
| 812 | |
| 813 if(gasChangeListDepthGas20x2) | |
| 814 { | |
| 815 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 816 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 817 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 818 } | |
| 819 else | |
| 820 { | |
| 821 actualConsumGasId = pDiveState->lifeData.actualGas.GasIdInSettings; | |
| 822 nextGasChangeMeter = 0; | |
| 823 } | |
| 824 | |
| 825 if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) | |
| 826 { | |
| 827 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
| 828 sim_ascent_rate_meter_per_min_local = pDiveState->diveSettings.ascentRate_meterperminute; | |
| 829 } | |
| 830 else | |
| 831 { | |
| 832 sim_descent_rate_meter_per_min_local = sim_descent_rate_meter_per_min; // const float | |
| 833 sim_ascent_rate_meter_per_min_local = 10;// fix in vpm_calc_deco(); | |
| 834 } | |
| 835 | |
| 836 // while((nextGasChangeMeter < depth_meter) && (actualDepthPoint < depth_meter)) | |
| 837 while(actualDepthPoint < depth_meter) | |
| 838 { | |
| 839 if(nextGasChangeMeter && (nextGasChangeMeter < depth_meter) && (gasChangeListDepthGas20x2[ptrChangeList] != 255)) // list has 255,255 for turn from travel to deco | |
| 840 { | |
| 841 nextDepthPoint = nextGasChangeMeter; | |
| 842 } | |
| 843 else | |
| 844 { | |
| 845 nextDepthPoint = depth_meter; | |
| 846 } | |
| 847 | |
| 848 if(actualConsumGasId > 5) // safety first | |
| 849 actualConsumGasId = 0; | |
| 850 | |
| 851 timeThis = ((float)(nextDepthPoint - actualDepthPoint)) / sim_descent_rate_meter_per_min_local; | |
| 852 if(actualDepthPoint) // not if on surface | |
| 853 { | |
| 854 consumThis = ((float)gasConsumTravelInput) * sGChelper_bar(actualDepthPoint) * timeThis; | |
| 855 } | |
| 856 consumThis += ((float)gasConsumTravelInput) * sGChelper_bar(nextDepthPoint -actualDepthPoint) * timeThis / 2; | |
| 857 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
| 858 timeSummary += timeThis; | |
| 859 | |
| 860 actualDepthPoint = nextDepthPoint; | |
| 861 | |
| 862 if(actualDepthPoint != depth_meter) | |
| 863 { | |
| 864 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 865 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 866 } | |
| 867 } | |
| 868 | |
| 869 // bottom Time | |
| 870 timeThis = ((float)dive_time_minutes) - timeSummary; | |
| 871 | |
| 872 if(timeThis > 0) | |
| 873 { | |
| 874 consumThis = ((float)gasConsumTravelInput) * sGChelper_bar(depth_meter) * timeThis; | |
| 875 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
| 876 } | |
| 877 | |
| 878 // ascend with deco stops prepare | |
| 879 if(gasChangeListDepthGas20x2) | |
| 880 { | |
| 881 ptrChangeList++;// gasChangeListDepthGas20x2[ptrChangeList++]; // should be the 255 | |
| 882 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 883 } | |
| 884 else | |
| 885 { | |
| 886 nextGasChangeMeter = 0; | |
| 887 } | |
| 888 | |
| 889 | |
| 890 if(!decoInfoInput->output_stop_length_seconds[0]) // NDL dive | |
| 891 { | |
| 892 depthLast = 0; | |
| 893 ptrDecoInfo = 0; | |
| 894 } | |
| 895 else | |
| 896 { | |
| 897 // prepare deco stop list | |
| 898 depthLast = (uint8_t)(stateUsed->diveSettings.last_stop_depth_bar * 10); | |
| 899 depthSecond = (uint8_t)(stateUsed->diveSettings.input_second_to_last_stop_depth_bar * 10); | |
| 900 depthInc = (uint8_t)(stateUsed->diveSettings.input_next_stop_increment_depth_bar * 10); | |
| 901 | |
| 902 for(ptrDecoInfo=DECOINFO_STRUCT_MAX_STOPS-1; ptrDecoInfo>0; ptrDecoInfo--) | |
| 903 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; | |
| 904 } | |
| 905 | |
| 906 actualDepthPoint = depth_meter; // that is where we are | |
| 907 | |
| 908 // ascend with deco stops | |
| 909 while(actualDepthPoint) | |
| 910 { | |
| 911 if(ptrDecoInfo == 0) | |
| 912 { | |
| 913 depthDecoNext = depthLast; | |
| 914 } | |
| 915 else | |
| 916 depthDecoNext = depthSecond + (( ptrDecoInfo - 1 )* depthInc); | |
| 917 | |
| 918 if(nextGasChangeMeter && (nextGasChangeMeter > depthDecoNext)) | |
| 919 { | |
| 920 nextDepthPoint = nextGasChangeMeter; | |
| 921 } | |
| 922 else | |
| 923 { | |
| 924 nextDepthPoint = depthDecoNext; | |
| 925 } | |
| 926 | |
| 927 if(actualConsumGasId > 5) // safety first | |
| 928 actualConsumGasId = 0; | |
| 929 | |
| 930 if(actualDepthPoint > nextDepthPoint) | |
| 931 { | |
| 932 // flip signs! It's going up | |
| 933 timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; | |
| 934 inBetweenDepthPoint = nextDepthPoint + ((actualDepthPoint - nextDepthPoint)/2); | |
| 935 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(inBetweenDepthPoint) * timeThis; | |
| 936 /* | |
| 937 if(nextDepthPoint) | |
| 938 { | |
| 939 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(nextDepthPoint) * timeThis; | |
| 940 } | |
| 941 else | |
| 942 { | |
| 943 consumThis = 0; | |
| 944 } | |
| 945 consumThis += ((float)gasConsumDecoInput) * sGChelper_bar(actualDepthPoint - nextDepthPoint) * timeThis / 2; | |
| 946 */ | |
| 947 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
| 948 } | |
| 949 | |
| 950 if(nextGasChangeMeter && (nextDepthPoint == nextGasChangeMeter)) | |
| 951 { | |
| 952 actualConsumGasId = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 953 nextGasChangeMeter = gasChangeListDepthGas20x2[ptrChangeList++]; | |
| 954 } | |
| 955 | |
| 956 if(actualConsumGasId > 5) // safety first | |
| 957 actualConsumGasId = 0; | |
| 958 | |
| 959 if(nextDepthPoint && (nextDepthPoint == depthDecoNext)) | |
| 960 { | |
| 961 if(decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) | |
| 962 { | |
| 963 timeThis = ((float)(decoInfoInput->output_stop_length_seconds[ptrDecoInfo])) / 60.0f; | |
| 964 consumThis = ((float)gasConsumDecoInput) * sGChelper_bar(nextDepthPoint) * timeThis; | |
| 965 outputConsumptionTempFloat[actualConsumGasId] += consumThis; | |
| 966 } | |
| 967 if(ptrDecoInfo != 0) | |
| 968 { | |
| 969 ptrDecoInfo--; | |
| 970 } | |
| 971 else | |
| 972 { | |
| 973 depthLast = 0; | |
| 974 } | |
| 975 } | |
| 976 actualDepthPoint = nextDepthPoint; | |
| 977 } | |
| 978 | |
| 979 // copy and return | |
| 980 for(int i = 1; i < 6; i++) | |
| 981 outputConsumptionList[i] = (uint16_t)(outputConsumptionTempFloat[i]); | |
| 982 } | |
| 983 | 806 |
| 984 /** | 807 /** |
| 985 ****************************************************************************** | 808 ****************************************************************************** |
| 986 * @brief Simulator control during simulated dive | 809 * @brief Simulator control during simulated dive |
| 987 ****************************************************************************** | 810 ****************************************************************************** |
