Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -r7a7bf19d0cf16745566956f45cef57f8eb5df445 -r8466e63f95f65a3ffb18c3af85ac99328e41167b --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 7a7bf19d0cf16745566956f45cef57f8eb5df445) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 8466e63f95f65a3ffb18c3af85ac99328e41167b) @@ -27,7 +27,10 @@ #include "OperationModes.h" #include "PresOccl.h" #include "ModePostTreat.h" +#include "ModeTreatment.h" #include "ModeTreatmentParams.h" +#include "RTC.h" +#include "SampleWater.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -41,13 +44,8 @@ // ********** private definitions ********** /// Interval (ms/task time) at which the post-treatment state data is published on the CAN bus. -#define POST_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) +#define POST_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) -#define EMPTY_RESERVOIR_VOLUME_ML 0 ///< Empty reservoir volume in ml. -#define DIP_FLUSH_FLOW_RATE_ML_MIN 150 ///< Dialysate inlet pump flow rate during flush in mL/min. - -#define LOAD_CELL_VOLUME_NOISE_TOLERANCE_GRAMS 10.0 ///< Allowed tolerance on load cell readings when empty in grams. - /// Post-Treatment drain reservoirs state machine. typedef enum Drain_States { @@ -105,6 +103,7 @@ currentDrainReservoirState = DRAIN_FIRST_RESERVOIR_START_STATE; postTreatmentPublishTimerCounter = 0; + // Reset treatment log data memset( &treatmentLogData, 0x0, sizeof( TREATMENT_LOG_DATA_PAYLOAD_T ) ); } @@ -124,7 +123,7 @@ cmdStopDGFill(); // Set user alarm recovery actions allowed in this mode - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); @@ -140,6 +139,8 @@ signalBloodPumpHardStop(); signalDialOutPumpHardStop(); signalDialInPumpHardStop(); + + collectTreatmentLogData(); } /*********************************************************************//** @@ -168,7 +169,6 @@ break; default: - currentPostTreatmentState = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_POST_TREATMENT_INVALID_STATE, currentPostTreatmentState ); break; } @@ -184,13 +184,74 @@ /*********************************************************************//** * @brief - * The handleTreatmentLogDataRequest sends treatment log data to UI upon - * UI requests. + * The collectTreatmentLogData function collects treatment data. + * @details Inputs: none + * @details Outputs: collected treatment data + * @return none + *************************************************************************/ +void collectTreatmentLogData( void ) +{ + // Reset treatment log data + memset( &treatmentLogData, 0x0, sizeof( TREATMENT_LOG_DATA_PAYLOAD_T ) ); + + treatmentLogData.bloodFlowRate_mL_min = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); + treatmentLogData.dialysateFlowRate_mL_min = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + treatmentLogData.treatmentDuration_sec = SEC_PER_MIN * getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + treatmentLogData.actualTreatmentDur_sec = getActualTreatmentTimeSecs(); + + treatmentLogData.acidConcentrate = getTreatmentParameterU32( TREATMENT_PARAM_ACID_CONCENTRATE ); + treatmentLogData.bicarbConcentrate = getTreatmentParameterU32( TREATMENT_PARAM_BICARB_CONCENTRATE ); + + treatmentLogData.dialysateTemperature_degC = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + treatmentLogData.dialyzerType = getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ); + treatmentLogData.treatmentStartDateAndTime = getTreatmentStartTimeStamp(); + treatmentLogData.treatmentEndDateAndTime = getTreatmentEndTimeStamp(); + + // There is treatment start time but treatment not completed means treatment ends early + if ( ( treatmentLogData.treatmentStartDateAndTime != 0 ) && ( FALSE == isTreatmentCompleted() ) ) + { + treatmentLogData.treatmentEndDateAndTime = getRTCTimestamp(); + } + + treatmentLogData.avgBloodFlow_mL_min = getTreatmentAvgBloodFlowRate(); + treatmentLogData.avgDialysateFlow_mL_min = getTreatmentAvgDialysateFlowRate(); + treatmentLogData.dialysateVolumeUsed_L = treatmentLogData.avgDialysateFlow_mL_min * treatmentLogData.actualTreatmentDur_sec / ( ML_PER_LITER * SEC_PER_MIN ); + treatmentLogData.avgDialysateTemperature_degC = getTreatmentAvgDialysateTemp(); + + treatmentLogData.targetUFVolume_L = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); + treatmentLogData.targetUFRate_mL_min = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER * SEC_PER_MIN / treatmentLogData.treatmentDuration_sec; + if ( treatmentLogData.actualTreatmentDur_sec > 0 ) + { + treatmentLogData.actualUFVolume_L = getUltrafiltrationVolumeCollected() / ML_PER_LITER; + treatmentLogData.actualUFRate_mL_min = getUltrafiltrationVolumeCollected() * SEC_PER_MIN / treatmentLogData.actualTreatmentDur_sec; + } + else + { + treatmentLogData.actualUFVolume_L = 0.0; + treatmentLogData.actualUFRate_mL_min = 0.0; + } + + treatmentLogData.salineBolusVolume_mL = getTotalSalineBolusVolumeDelivered(); + + treatmentLogData.heparinBolusVolume_mL = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + treatmentLogData.heparinDispenseRate_mL_hr = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + treatmentLogData.heparinPreStop_min = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); + treatmentLogData.heparinDeliveredVolume_mL = getSyringePumpVolumeDelivered(); + + treatmentLogData.avgArterialPressure_mmHg = getTreatmentAvgArterialPressure(); + treatmentLogData.avgVenousPressure_mmHg = getTreatmentAvgVenousPressure(); + + treatmentLogData.waterSampleTestResult = (U32)getSampleWaterResult(); +} + +/*********************************************************************//** + * @brief + * The sendTreatmentLogDataToUI sends treatment log data to UI. * @details Inputs: treatmentLogData * @details Outputs: Sent treatment log data to UI * @return none *************************************************************************/ -void handleTreatmentLogDataRequest( void ) +void sendTreatmentLogDataToUI( void ) { BOOL accepted = TRUE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; @@ -266,9 +327,10 @@ if ( STATE_CLOSED == getFPGADoorState() ) { -#ifndef SKIP_UI_INTERACTION - if ( TRUE == patientDisconnectionConfirmed ) +#ifdef SKIP_UI_INTERACTION + patientDisconnectionConfirmed = TRUE; #endif + if ( TRUE == patientDisconnectionConfirmed ) { patientDisconnectionConfirmed = FALSE; state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; @@ -312,9 +374,10 @@ if ( DRAIN_COMPLETE_STATE == currentDrainReservoirState ) { -#ifndef SKIP_UI_INTERACTION - if ( TRUE == disposableRemovalConfirmed ) +#ifdef SKIP_UI_INTERACTION + disposableRemovalConfirmed = TRUE; #endif + if ( TRUE == disposableRemovalConfirmed ) { disposableRemovalConfirmed = FALSE; state = HD_POST_TREATMENT_VERIFY_STATE; @@ -334,14 +397,6 @@ *************************************************************************/ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ) { -#ifndef SKIP_EMPTY_RES_CHECK - BOOL const isReservoirOneEmpty = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) ) <= LOAD_CELL_VOLUME_NOISE_TOLERANCE_GRAMS; - BOOL const isReservoirTwoEmpty = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) ) <= LOAD_CELL_VOLUME_NOISE_TOLERANCE_GRAMS; -#else - BOOL const isReservoirOneEmpty = TRUE; - BOOL const isReservoirTwoEmpty = TRUE; -#endif - #ifndef SKIP_CARTRIDGE_REMOVAL BOOL isCartridgeRemoved = isCartridgeUnloaded(); #else @@ -360,8 +415,7 @@ activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); } - if ( ( TRUE == isReservoirOneEmpty ) && ( TRUE == isReservoirTwoEmpty ) && - ( TRUE == isCartridgeRemoved ) && ( FALSE == isSyringeDetected() ) ) + if ( ( TRUE == isCartridgeRemoved ) && ( FALSE == isSyringeDetected() ) ) { cmdStopDG(); requestNewOperationMode( MODE_STAN ); @@ -432,7 +486,7 @@ } else { - cmdStartDGDrain( EMPTY_RESERVOIR_VOLUME_ML, FALSE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); } } @@ -454,7 +508,7 @@ if ( ( DG_MODE_CIRC == getDGOpMode() ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getDGSubMode() ) ) { state = DRAIN_FIRST_RESERVOIR_STATE; - cmdStartDGDrain( EMPTY_RESERVOIR_VOLUME_ML, FALSE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); } return state; @@ -512,7 +566,7 @@ if ( TRUE == hasDGCompletedReservoirSwitch() ) { state = DRAIN_SECOND_RESERVOIR_STATE; - cmdStartDGDrain( EMPTY_RESERVOIR_VOLUME_ML, FALSE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); } return state;