Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rd2f3df2002ecc87795b8bdeefda63c4805d78146 -r30f049651877229042e3f8700c8596e5b9a1e0f4 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision d2f3df2002ecc87795b8bdeefda63c4805d78146) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 30f049651877229042e3f8700c8596e5b9a1e0f4) @@ -32,10 +32,6 @@ #include "TreatmentStop.h" #include "Utilities.h" #include "Valves.h" -#ifdef RM46_EVAL_BOARD_TARGET - #include "Timers.h" - static U32 start; -#endif /** * @addtogroup HDTreatmentMode @@ -108,7 +104,7 @@ treatmentTimeMS = 0; lastTreatmentTimeStamp = 0; treatmentTimeBroadcastTimerCtr = 0; - treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // so we send ranges immediately + treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately presTreatmentTimeSecs = 0; presBloodFlowRate = 0; @@ -133,16 +129,17 @@ *************************************************************************/ void transitionToTreatmentMode( void ) { - // initialize treatment mode each time we transition to it + // Initialize treatment mode each time we transition to it initTreatmentMode(); initTreatmentReservoirMgmt(); - // initialize treatment sub-modes each time we transition to treatment mode + // Initialize treatment sub-modes each time we transition to treatment mode initDialysis(); initTreatmentStop(); -#ifdef RM46_EVAL_BOARD_TARGET - // TODO - temporary test code for eval board - start = getMSTimerCount(); -#endif + + // Set user alarm recovery actions allowed in this mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); } /*********************************************************************//** @@ -181,22 +178,101 @@ /*********************************************************************//** * @brief + * The signalAlarmActionToTreatmentMode function executes the given alarm action + * as appropriate while in Treatment Mode. + * @details Inputs: none + * @details Outputs: given alarm action executed + * @param action ID of alarm action to execute + * @return none + *************************************************************************/ +void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ) +{ + switch( action ) + { + case ALARM_ACTION_STOP: + switch ( currentTreatmentState ) + { + case TREATMENT_START_STATE: + case TREATMENT_DIALYSIS_STATE: + stopDialysis(); + transitionToTreatmentStop(); + currentTreatmentState = TREATMENT_STOP_STATE; + break; + + case TREATMENT_RINSEBACK_STATE: + // TODO - implement + break; + + case TREATMENT_RECIRC_STATE: + // TODO - implement + break; + + default: + // Ignore + break; + } + break; + + case ALARM_ACTION_RESUME: + switch ( currentTreatmentState ) + { + case TREATMENT_STOP_STATE: + lastTreatmentTimeStamp = getMSTimerCount(); + startDialysis(); + transitionToDialysis(); + currentTreatmentState = TREATMENT_DIALYSIS_STATE; + break; + + case TREATMENT_RINSEBACK_PAUSE_STATE: + // TODO - implement + break; + + case TREATMENT_RECIRC_PAUSE_STATE: + // TODO - implement + break; + + default: + // Ignore + break; + } + break; + + case ALARM_ACTION_RINSEBACK: + // TODO - implement + break; + + case ALARM_ACTION_END_TREATMENT: + // TODO - temporary code - implement + currentTreatmentState = TREATMENT_END_STATE; + break; + + case ALARM_ACTION_ACK: + // Nothing to be done here + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_ALARM_ACTION, (U32)action ) + break; + } +} + +/*********************************************************************//** + * @brief * The execTreatmentMode function executes the Treatment Mode state machine. * @details Inputs: currentTreatmentState * @details Outputs: currentTreatmentState * @return current state (sub-mode) *************************************************************************/ U32 execTreatmentMode( void ) { -#ifdef DISABLE_UI_TREATMENT_WORKFLOW BOOL stop = isStopButtonPressed(); if ( TRUE == stop ) { - requestNewOperationMode( MODE_POST ); + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); } -#endif - // treatment mode state machine + + // Treatment mode state machine switch ( currentTreatmentState ) { case TREATMENT_START_STATE: @@ -250,20 +326,13 @@ currentTreatmentState = TREATMENT_END_STATE; break; } - // broadcast treatment data + // Broadcast treatment data broadcastTreatmentTimeAndState(); broadcastTreatmentSettingsRanges(); - // call various execs for treatment mode + // Call various execs for treatment mode execTreatmentReservoirMgmt(); execAirTrapMonitorTreatment(); -#ifdef RM46_EVAL_BOARD_TARGET - // TODO - temporary test code for eval board - move to next mode after 5 min - if ( TRUE == didTimeout( start, 300000U ) ) - { - requestNewOperationMode( MODE_POST ); - } -#endif return currentTreatmentState; } @@ -280,26 +349,17 @@ { TREATMENT_STATE_T result = TREATMENT_DIALYSIS_STATE; - // initialize treatment time + // Initialize treatment time treatmentTimeMS = 0; lastTreatmentTimeStamp = getMSTimerCount(); -#ifndef DISABLE_UI_TREATMENT_WORKFLOW presTreatmentTimeSecs = SEC_PER_MIN * getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); presBloodFlowRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); presDialysateFlowRate = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); presMaxUFVolumeML = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; presUFRate = presMaxUFVolumeML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); -#else - // TODO - test code - presTreatmentTimeSecs = 14400; - presBloodFlowRate = 300; - presDialysateFlowRate = 300; - presMaxUFVolumeML = 2400.0; - presUFRate = 0.0; -#endif - // kick dialysis sub-mode off + // Kick dialysis sub-mode off setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); startDialysis(); @@ -321,19 +381,19 @@ U32 newTime = getMSTimerCount(); U32 msSinceLast = calcTimeBetween( lastTreatmentTimeStamp, newTime ); - // update treatment time (unless delivering a saline bolus) + // Update treatment time (unless delivering a saline bolus) if ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) { treatmentTimeMS += msSinceLast; } lastTreatmentTimeStamp = newTime; - // end treatment if treatment duration has been reached + // End treatment if treatment duration has been reached if ( CALC_ELAPSED_TREAT_TIME_IN_SECS() >= presTreatmentTimeSecs ) { result = TREATMENT_END_STATE; } - // otherwise, execute state machine for treatment dialysis sub-mode + // Otherwise, execute state machine for treatment dialysis sub-mode else { execDialysis(); @@ -370,14 +430,14 @@ { TREATMENT_STATE_T result = TREATMENT_STOP_STATE; - // if user requests treatment end, end treatment + // If user requests treatment end, end treatment if ( TRUE == pendingUserEndTreatmentRequest ) { result = TREATMENT_END_STATE; } else { - // execute state machine for treatment stop sub-mode + // Execute state machine for treatment stop sub-mode execTreatmentStop(); } @@ -416,15 +476,15 @@ REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); - // check if we are in an appropriate treatment state for settings adjustment + // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_DIALYSIS_END_STATE ) && ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= MIN_TREATMENT_TIME_MINUTES ) ) { F32 uFVolume; - U32 dialVolume = presDialysateFlowRate * treatmentTime; // in mL + U32 dialVolume = presDialysateFlowRate * treatmentTime; // In mL - // always adjust UF volume to accommodate treatment time change (not UF rate) + // Always adjust UF volume to accommodate treatment time change (not UF rate) uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationVolumeCollected(); if ( ( treatmentTime <= MAX_TREATMENT_TIME_MINUTES ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && @@ -471,11 +531,11 @@ rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; } } - // send response to request + // Send response to request sendChangeTreatmentDurationResponse( result, rejectReason, presTreatmentTimeSecs / SEC_PER_MIN, presMaxUFVolumeML ); - // send new ranges for settings + // Send new ranges for settings broadcastTreatmentSettingsRanges(); - // send time/state data immediately for UI update + // Send time/state data immediately for UI update broadcastTreatmentTimeAndState(); return result; @@ -498,22 +558,22 @@ F32 rateDiff = 0.0; HD_OP_MODE_T currMode = getCurrentOperationMode(); - // reset pending UF/time settings changes to current values in case request is rejected + // Reset pending UF/time settings changes to current values in case request is rejected pendingUFVolumeChange = presMaxUFVolumeML; pendingUFRateChange = presUFRate; pendingTreatmentTimeChange = presTreatmentTimeSecs / SEC_PER_MIN; - // check if we are in an appropriate treatment state for settings adjustment + // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_DIALYSIS_END_STATE ) && ( uFVolume <= MAX_UF_VOLUME_ML ) && ( CALC_TREAT_TIME_REMAINING_IN_SECS() >= PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ) ) { DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); - F32 uFRate = uFVolume / ((F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN); // what UF rate would be if user selected to adjust it - U32 trtTime = (S32)( uFVolume / presUFRate ) + 1; // what the treatment duration would be if user selected to adjust it - U32 dialVolume = presDialysateFlowRate * trtTime; // what dialysate volume would be if user selected to adjust time + F32 uFRate = uFVolume / ((F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN); // What UF rate would be if user selected to adjust it + U32 trtTime = (S32)( uFVolume / presUFRate ) + 1; // What the treatment duration would be if user selected to adjust it + U32 dialVolume = presDialysateFlowRate * trtTime; // What dialysate volume would be if user selected to adjust time // UF should already be paused but let's make sure. if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && @@ -523,10 +583,10 @@ pauseUF(); } - // start t/o timer - user must confirm UF changes within 1 minute from now + // Start t/o timer - user must confirm UF changes within 1 minute from now pendingParamChangesTimer = getMSTimerCount(); - // verify UF rate change would be valid (leave zero if not valid - UI will disable option) + // Verify UF rate change would be valid (leave zero if not valid - UI will disable option) if ( uFRate <= (F32)MAX_UF_RATE_ML_MIN ) { result = TRUE; @@ -538,7 +598,7 @@ { pendingUFRateChange = 0.0; } - // verify treatment duration change would be valid (leave zero if not valid - UI will disable option) + // Verify treatment duration change would be valid (leave zero if not valid - UI will disable option) if ( ( trtTime <= MAX_TREATMENT_TIME_MINUTES ) && ( trtTime >= MIN_TREATMENT_TIME_MINUTES ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { @@ -551,7 +611,7 @@ { pendingTreatmentTimeChange = 0; } - // if neither option works, reject for UF rate + // If neither option works, reject for UF rate if ( FALSE == result ) { rejectReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; @@ -577,7 +637,7 @@ rejectReason = REQUEST_REJECT_REASON_TREATMENT_TOO_CLOSE_TO_FINISHED; } } - // respond to UF settings change request + // Respond to UF settings change request sendChangeUFSettingsResponse( result, rejectReason, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff, presUFRate ); return result; @@ -599,7 +659,7 @@ REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); - // user confirmed UF settings change(s)? + // User confirmed UF settings change(s)? if ( ( MODE_TREA == currMode ) && ( FALSE == didTimeout( pendingParamChangesTimer, USER_CONFIRM_CHANGE_TIMEOUT_MS ) ) ) { DIALYSIS_STATE_T currDialysisState = getDialysisState(); @@ -608,18 +668,18 @@ result = TRUE; presMaxUFVolumeML = pendingUFVolumeChange; - // which setting does user want to adjust to accommodate the UF volume change? (treatment time or UF rate) + // Which setting does user want to adjust to accommodate the UF volume change? (treatment time or UF rate) if ( UF_ADJ_TREATMENT_TIME == adjustment ) { presTreatmentTimeSecs = pendingTreatmentTimeChange * SEC_PER_MIN; } - else // must be adjusting UF rate then + else // Must be adjusting UF rate then { presUFRate = pendingUFRateChange; } setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); - // if UF paused, resume with new settings + // If UF paused, resume with new settings if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && ( DIALYSIS_UF_STATE == currDialysisState ) && ( UF_PAUSED_STATE == currUFState ) ) @@ -638,11 +698,11 @@ rejectReason = REQUEST_REJECT_REASON_TIMEOUT_WAITING_FOR_USER_CONFIRM; } } - // respond to UF settings change confirmation + // Respond to UF settings change confirmation sendChangeUFSettingsOptionResponse( result, rejectReason, presMaxUFVolumeML, presTreatmentTimeSecs / SEC_PER_MIN, presUFRate ); - // send new ranges for settings + // Send new ranges for settings broadcastTreatmentSettingsRanges(); - // send time/state data immediately for UI update + // Send time/state data immediately for UI update broadcastTreatmentTimeAndState(); return result; @@ -664,18 +724,18 @@ REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); - // check if we are in treatment mode for settings change + // Check if we are in treatment mode for settings change if ( MODE_TREA == currMode ) { - U32 dialVolume = dialRate * ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); // in mL + U32 dialVolume = dialRate * ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); // In mL - // validate new rates + // Validate new rates if ( ( bloodRate >= MIN_BLOOD_FLOW_RATE ) && ( bloodRate <= MAX_BLOOD_FLOW_RATE ) && ( dialRate >= MIN_DIAL_IN_FLOW_RATE ) && ( dialRate <= MAX_DIAL_IN_FLOW_RATE ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; - // set to new rates + // Set to new rates presBloodFlowRate = bloodRate; presDialysateFlowRate = dialRate; setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); @@ -701,7 +761,7 @@ rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, presBloodFlowRate, presDialysateFlowRate ); - // send new ranges for settings + // Send new ranges for settings broadcastTreatmentSettingsRanges(); return result; @@ -729,7 +789,7 @@ proposedNewVenLowLimit.sInt = data->venLowLimit; proposedNewVenHighLimit.sInt = data->venHighLimit; - // check ranges for changed limits + // Check ranges for changed limits if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT, proposedNewArtLowLimit ) ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; @@ -751,31 +811,31 @@ result = FALSE; } - // if ranges ok, check separation between low/high limits + // If ranges ok, check separation between low/high limits if ( TRUE == result ) { S32 arterialPresLimitDelta = data->artHighLimit - data->artLowLimit; S32 venousPresLimitDelta = data->venHighLimit - data->venLowLimit; - // check arterial alarm limits dependency + // Check arterial alarm limits dependency if ( arterialPresLimitDelta < MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_ARTERIAL_PRESSURE_LOW_VS_HIGH; result = FALSE; } - // check venous alarm limits dependency + // Check venous alarm limits dependency if ( venousPresLimitDelta < MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_VENOUS_PRESSURE_LOW_VS_HIGH; result = FALSE; } } - // set overall result - are changes accepted? + // Set overall result - are changes accepted? respRecord.accepted = result; - // if changes accepted, set new pressure limits + // If changes accepted, set new pressure limits if ( TRUE == result ) { setTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT, data->artLowLimit ); @@ -784,12 +844,12 @@ setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT, data->venHighLimit ); } - // read back limits for transmit to UI. + // Read back limits for transmit to UI. respRecord.artLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); respRecord.artHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); respRecord.venLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); respRecord.venHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); - // send response + // Send response sendPressureLimitsChangeResponse( &respRecord ); return result; @@ -807,15 +867,15 @@ { U32 elapsedTreatmentTimeInSecs; - // update treatment time stats and broadcast - end treatment if time + // Update treatment time stats and broadcast - end treatment if time elapsedTreatmentTimeInSecs = treatmentTimeMS / MS_PER_SECOND; if ( elapsedTreatmentTimeInSecs >= presTreatmentTimeSecs ) { stopDialysis(); elapsedTreatmentTimeInSecs = presTreatmentTimeSecs; currentTreatmentState = TREATMENT_DIALYSIS_END_STATE; } - // broadcast treatment time and state data at interval + // Broadcast treatment time and state data at interval if ( ++treatmentTimeBroadcastTimerCtr >= TREATMENT_TIME_DATA_PUB_INTERVAL ) { U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; @@ -843,31 +903,31 @@ { if ( ++treatmentParamsRangesBroadcastTimerCtr >= TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ) { - // compute minimum treatment duration + // Compute minimum treatment duration U32 presTime = ( presTreatmentTimeSecs / SEC_PER_MIN ); U32 elapseTime = CALC_ELAPSED_TREAT_TIME_IN_MIN(); - U32 minTime = MAX( (elapseTime + 2), MIN_TREATMENT_TIME_MINUTES ); // treatment duration cannot be < 1 hour. add two minutes to cover rounding and ensure it's valid for next minute - // compute maximum treatment duration (from both UF and dialysate volume perspectives) + U32 minTime = MAX( (elapseTime + 2), MIN_TREATMENT_TIME_MINUTES ); // Treatment duration cannot be < 1 hour. add two minutes to cover rounding and ensure it's valid for next minute + // Compute maximum treatment duration (from both UF and dialysate volume perspectives) U32 maxTimeRem = ( MAX_UF_VOLUME_ML - (U32)getUltrafiltrationVolumeCollected() ) / ( presUFRate > 0.0 ? (U32)presUFRate : 1 ); U32 maxTime1 = minTime + maxTimeRem; U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / presDialysateFlowRate; U32 maxTime = MAX( maxTime1, maxTime2 ); - // compute minimum UF volume + // Compute minimum UF volume F32 minUFVol = getUltrafiltrationVolumeCollected() + presUFRate; - // compute maximum UF volume (considering from adjustment of UF rate and time perspectives) + // Compute maximum UF volume (considering from adjustment of UF rate and time perspectives) F32 maxUFVol1 = minUFVol + ( (F32)( presTime - elapseTime ) * MAX_UF_RATE_ML_MIN ); F32 maxUFVol2 = ( presUFRate > 0.0 ? minUFVol + ( (F32)( MAX_TREATMENT_TIME_MINUTES - elapseTime - 1 ) * presUFRate ) : minUFVol ); F32 maxUFVol = MAX( maxUFVol1, maxUFVol2 ); - // compute minimum dialysate flow rate + // Compute minimum dialysate flow rate U32 minDialRate = MIN_DIAL_IN_FLOW_RATE; - // compute maximum dialysate flow rate from max dialysate volume perspective + // Compute maximum dialysate flow rate from max dialysate volume perspective U32 maxDialRate = MAX_DIALYSATE_VOLUME_ML / presTime; - // now ensure maximums do not exceed the literal maximums + // Now ensure maximums do not exceed the literal maximums maxTime = MIN( maxTime, MAX_TREATMENT_TIME_MINUTES ); maxUFVol = MIN( maxUFVol, (F32)MAX_UF_VOLUME_ML ); maxDialRate = MIN( maxDialRate, MAX_DIAL_IN_FLOW_RATE ); - // send updated treatment parameter ranges to UI + // Send updated treatment parameter ranges to UI sendTreatmentParamsRangesToUI( minTime, maxTime, minUFVol, maxUFVol, minDialRate, maxDialRate ); treatmentParamsRangesBroadcastTimerCtr = 0; }