Mercurial > public > ostc4
diff Discovery/Src/simulation.c @ 981:c6c781a2e85b default
Merge into default
| author | heinrichsweikamp |
|---|---|
| date | Tue, 11 Feb 2025 18:12:00 +0100 |
| parents | 7149f372b0ba |
| children | 7891160acde3 |
line wrap: on
line diff
--- a/Discovery/Src/simulation.c Tue Aug 13 13:24:54 2024 +0200 +++ b/Discovery/Src/simulation.c Tue Feb 11 18:12:00 2025 +0100 @@ -51,7 +51,12 @@ static float sim_aim_time_minutes; static _Bool sim_heed_decostops = 1; -static const float sim_descent_rate_meter_per_min = 20; +static float sim_descent_rate_meter_per_min = 20; + +static uint16_t* pReplayData; /* pointer to source dive data */ +static uint8_t simReplayActive = 0; + +static uint16_t simScrubberTimeoutCount = 0; //Private functions @@ -83,13 +88,20 @@ */ void simulation_start(int aim_depth, uint16_t aim_time_minutes) { + uint16_t replayDataLength = 0; + uint8_t* pReplayMarker; + uint16_t max_depth = 10; + uint16_t diveMinutes = 0; + copyDiveSettingsToSim(); copyVpmRepetetiveDataToSim(); + //vpm_init(&stateSimGetPointerWrite()->vpm, stateSimGetPointerWrite()->diveSettings.vpm_conservatism, 0, 0); stateSimGetPointerWrite()->lifeData.counterSecondsShallowDepth = 0; stateSimGetPointerWrite()->mode = MODE_DIVE; if(aim_depth <= 0) aim_depth = 20; + sim_descent_rate_meter_per_min = 20; simulation_set_aim_depth(aim_depth); sim_aim_time_minutes = aim_time_minutes; timer_init(); @@ -98,7 +110,14 @@ decoLock = DECO_CALC_init_as_is_start_of_dive; stateSim.lifeData.apnea_total_max_depth_meter = 0; + + memcpy(stateSim.scrubberDataDive, settingsGetPointer()->scrubberData, sizeof(stateSim.scrubberDataDive)); memset(simSensmVOffset,0,sizeof(simSensmVOffset)); + if(getReplayOffset() != 0xFFFF) + { + simReplayActive = 1; + getReplayInfo(&pReplayData, &pReplayMarker, &replayDataLength, &max_depth, &diveMinutes); + } } /** @@ -137,7 +156,11 @@ static _Bool two_second = 0; static float lastPressure_bar = 0; - if (sim_aim_time_minutes && sim_aim_time_minutes * 60 <= pDiveState->lifeData.dive_time_seconds) { + pSettings = settingsGetPointer(); + + if ((sim_aim_time_minutes && sim_aim_time_minutes * 60 <= pDiveState->lifeData.dive_time_seconds) + && (!simReplayActive)) + { simulation_set_aim_depth(0); } @@ -146,25 +169,42 @@ if(checkOncePerSecond) { + int now = current_second(); + if( last_second == now) + return; + last_second = now; - pSettings = settingsGetPointer(); + if(!two_second) + two_second = 1; + else + { + two_second = 0; + } + for(index = 0; index < 3; index++) { - localCalibCoeff[index] = pSettings->ppo2sensors_calibCoeff[index]; - if(localCalibCoeff[index] < 0.01) + if(pDiveState->lifeData.extIf_sensor_map[index] == SENSOR_DIGO2M) + { + localCalibCoeff[index] = 0.01; + } + else { - for(index2 = 0; index2 < 3; index2++) /* no valid coeff => check other entries */ - { - if(pSettings->ppo2sensors_calibCoeff[index2] > 0.01) - { - localCalibCoeff[index] = pSettings->ppo2sensors_calibCoeff[index2]; - break; - } - if(index2 == 3) /* no coeff at all => use default */ - { - localCalibCoeff[index] = 0.02; - } - } + localCalibCoeff[index] = pSettings->ppo2sensors_calibCoeff[index]; + if(localCalibCoeff[index] < 0.01) + { + for(index2 = 0; index2 < 3; index2++) /* no valid coeff => check other entries */ + { + if(pSettings->ppo2sensors_calibCoeff[index2] > 0.01) + { + localCalibCoeff[index] = pSettings->ppo2sensors_calibCoeff[index2]; + break; + } + if(index2 == 3) /* no coeff at all => use default */ + { + localCalibCoeff[index] = 0.02; + } + } + } } } @@ -183,29 +223,48 @@ pDiveState->lifeData.bottle_bar[pDiveState->lifeData.actualGas.GasIdInSettings] = pRealState->lifeData.bottle_bar[pRealState->lifeData.actualGas.GasIdInSettings]; pDiveState->lifeData.bottle_bar_age_MilliSeconds[pDiveState->lifeData.actualGas.GasIdInSettings] = pRealState->lifeData.bottle_bar_age_MilliSeconds[pRealState->lifeData.actualGas.GasIdInSettings]; #endif - int now = current_second(); - if( last_second == now) - return; - last_second = now; - - if(!two_second) - two_second = 1; - else - { - two_second = 0; - if(lastPressure_bar >= 0) - { - //2 seconds * 30 == 1 minute, bar * 10 = meter - pDiveState->lifeData.ascent_rate_meter_per_min = (lastPressure_bar - pDiveState->lifeData.pressure_ambient_bar) * 30 * 10; - } - lastPressure_bar = pDiveState->lifeData.pressure_ambient_bar; - } } else if(pDiveState->lifeData.depth_meter <= (float)(decom_get_actual_deco_stop(pDiveState) + 0.001)) - sim_reduce_deco_time_one_second(pDiveState); + { + if(decoLock == DECO_CALC_FINSHED_vpm) + { + sim_reduce_deco_time_one_second(&stateDeco); + } + else + { + sim_reduce_deco_time_one_second(pDiveState); + } + } pDiveState->lifeData.dive_time_seconds += 1; pDiveState->lifeData.pressure_ambient_bar = sim_get_ambient_pressure(pDiveState); + if(pDiveState->lifeData.depth_meter < 1.5) + { + lastPressure_bar = 0; + pDiveState->lifeData.ascent_rate_meter_per_min = 0; + } + + if((pSettings->scrubTimerMode != SCRUB_TIMER_OFF) && (isLoopMode(pSettings->dive_mode)) && (pDiveState->mode == MODE_DIVE) && isLoopMode(pDiveState->diveSettings.diveMode)) + { + simScrubberTimeoutCount++; + if(simScrubberTimeoutCount >= 60) /* resolution is minutes */ + { + simScrubberTimeoutCount = 0; + if(pDiveState->scrubberDataDive[pSettings->scubberActiveId].TimerCur > MIN_SCRUBBER_TIME) + { + pDiveState->scrubberDataDive[pSettings->scubberActiveId].TimerCur--; + } + translateDate(stateUsed->lifeData.dateBinaryFormat, &pDiveState->scrubberDataDive[pSettings->scubberActiveId].lastDive); + } + } + + + if(lastPressure_bar > 0) + { + //1 second * 60 == 1 minute, bar * 10 = meter + pDiveState->lifeData.ascent_rate_meter_per_min = (lastPressure_bar - pDiveState->lifeData.pressure_ambient_bar) * 600.0; + } + lastPressure_bar = pDiveState->lifeData.pressure_ambient_bar; pDiveState->lifeData.sensorVoltage_mV[0] = pRealState->lifeData.sensorVoltage_mV[0] + simSensmVOffset[0]; if(pDiveState->lifeData.sensorVoltage_mV[0] < 0.0) { pDiveState->lifeData.sensorVoltage_mV[0] = 0.0; } @@ -349,6 +408,35 @@ uint8_t actual_deco_stop = decom_get_actual_deco_stop(pDiveState); float depth_meter = pDiveState->lifeData.depth_meter; float surface_pressure_bar = pDiveState->lifeData.pressure_surface_bar; + static uint8_t sampleToggle = 0; + static float sim_ascent_rate_meter_per_min_local = 0; + uint8_t sampleTime = getReplayDataResolution(); + + if(simReplayActive) /* precondition: function is called once per second, sample rate is a multiple of second */ + { + if(sampleToggle == 0) + { + sampleToggle = sampleTime - 1; + sim_aim_depth_meter = (float)(*pReplayData++/100.0); + if(sim_aim_depth_meter > depth_meter) + { + sim_descent_rate_meter_per_min = (sim_aim_depth_meter - depth_meter) * (60 / sampleTime); + } + else + { + sim_ascent_rate_meter_per_min_local = (depth_meter - sim_aim_depth_meter) * (60 / sampleTime); + } + } + else + { + sampleToggle--; + } + } + else + { + sim_ascent_rate_meter_per_min_local = pDiveState->diveSettings.ascentRate_meterperminute; + } + if(depth_meter < sim_aim_depth_meter) { depth_meter = depth_meter + sim_descent_rate_meter_per_min / 60; @@ -358,16 +446,16 @@ else if(depth_meter > sim_aim_depth_meter) { - depth_meter -= pDiveState->diveSettings.ascentRate_meterperminute / 60; + depth_meter -= sim_ascent_rate_meter_per_min_local / 60; if(depth_meter < sim_aim_depth_meter) depth_meter = sim_aim_depth_meter; if(sim_heed_decostops && depth_meter < actual_deco_stop) { - if(actual_deco_stop < (depth_meter + pDiveState->diveSettings.ascentRate_meterperminute / 60)) + if(actual_deco_stop < (depth_meter + sim_ascent_rate_meter_per_min_local / 60)) depth_meter = actual_deco_stop; else - depth_meter += pDiveState->diveSettings.ascentRate_meterperminute / 60; + depth_meter += sim_ascent_rate_meter_per_min_local / 60; } } @@ -387,31 +475,53 @@ static void sim_reduce_deco_time_one_second(SDiveState* pDiveState) { SDecoinfo* pDecoinfo; + int8_t index = 0; + + if(pDiveState->diveSettings.deco_type.ub.standard == GF_MODE) pDecoinfo = &pDiveState->decolistBuehlmann; else pDecoinfo = &pDiveState->decolistVPM; //Reduce deco time of deepest stop by one second - for(int i = DECOINFO_STRUCT_MAX_STOPS -1 ;i >= 0; i--) + for(index = DECOINFO_STRUCT_MAX_STOPS -1 ;index >= 0; index--) { - if(pDecoinfo->output_stop_length_seconds[i] > 0) + if(pDecoinfo->output_stop_length_seconds[index] > 0) { - pDecoinfo->output_stop_length_seconds[i]--; + pDecoinfo->output_stop_length_seconds[index]--; break; } } + /* update TTS */ + if(pDecoinfo->output_time_to_surface_seconds) + { + pDecoinfo->output_time_to_surface_seconds--; + } } SDecoinfo* simulation_decoplaner(uint16_t depth_meter, uint16_t intervall_time_minutes, uint16_t dive_time_minutes, uint8_t *gasChangeListDepthGas20x2) { uint8_t ptrGasChangeList = 0; // new hw 160704 - +#ifdef ENABLE_DECOCALC_OPTION + uint8_t index = 0; +#endif for (int i = 0; i < 40; i++) gasChangeListDepthGas20x2[i] = 0; SDiveState * pDiveState = &stateSim; copyDiveSettingsToSim(); + +#ifdef ENABLE_DECOCALC_OPTION + /* activate deco calculation for all deco gases */ + for(index = 0; index < 1 + (2*NUM_GASES); index++) + { + if(pDiveState->diveSettings.gas[index].note.ub.deco) + { + pDiveState->diveSettings.gas[index].note.ub.decocalc = 1; + } + } +#endif + vpm_init(&pDiveState->vpm, pDiveState->diveSettings.vpm_conservatism, 0, 0); //buehlmann_init(); //timer_init(); @@ -466,7 +576,11 @@ // ascend (deco) gases for(int i=1; i<=5;i++) { - if(pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) + if((pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) +#ifdef ENABLE_DECOCALC_OPTION + || (pDiveState->diveSettings.gas[pDiveState->diveSettings.decogaslist[i].GasIdInSettings].note.ub.decocalc == 0) +#endif + ) break; gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].change_during_ascent_depth_meter_otherwise_zero; gasChangeListDepthGas20x2[ptrGasChangeList++] = pDiveState->diveSettings.decogaslist[i].GasIdInSettings; @@ -487,6 +601,11 @@ /* this does modify the cns now 11.06.2015 */ vpm_calc(&pDiveState->lifeData,&pDiveState->diveSettings,&pDiveState->vpm,&pDiveState->decolistVPM, DECOSTOPS); pDiveState->lifeData.cns += vpm_get_CNS(); + + while(decoLock == DECO_CALC_FINSHED_vpm) + { + HAL_Delay(2); /* The deco data is copied during the timer ISR => wait till this has happened */ + } return &pDiveState->decolistVPM; } } @@ -639,24 +758,14 @@ outputSummary->timeToFirstStop = (uint16_t)timeSummary; outputSummary->depthMeterFirstStop = actualDepthPoint; - //ascent - nextDepthPoint = 0; - timeThis = 0; - if(actualDepthPoint > nextDepthPoint) // only if deco + if(decoInfoInput->output_time_to_surface_seconds) { - // ascent time - timeThis = ((float)(actualDepthPoint - nextDepthPoint)) / sim_ascent_rate_meter_per_min_local; - - // deco stop time - for(ptrDecoInfo=0;ptrDecoInfo < DECOINFO_STRUCT_MAX_STOPS; ptrDecoInfo++) - { - timeThis += decoInfoInput->output_stop_length_seconds[ptrDecoInfo] / 60; - if(!decoInfoInput->output_stop_length_seconds[ptrDecoInfo]) break; - } + outputSummary->timeToSurface = outputSummary->timeAtBottom + (decoInfoInput->output_time_to_surface_seconds / 60); } - timeSummary += timeThis; - outputSummary->timeToSurface = (uint16_t)timeSummary; - + else + { + outputSummary->timeToSurface = outputSummary->timeToFirstStop; + } }
