Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r316f8773970f94c9b1996a03f2235050afb514da -r24b2fe72608344e67ef37234085d15ad5e4fcc37 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 316f8773970f94c9b1996a03f2235050afb514da) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 24b2fe72608344e67ef37234085d15ad5e4fcc37) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file ModeTreatment.c +* @file ModeTreatment.c * -* @author (last) Sean Nash -* @date (last) 12-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 12-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -27,6 +27,7 @@ #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "Rinseback.h" +#include "RTC.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -55,11 +56,15 @@ #define PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ( 10 * SEC_PER_MIN ) ///< Prevent UF volume change if treatment within this much time from end of treatment (in seconds). /// Interval (ms/task time) at which the treatment time data is published on the CAN bus. -static const U32 TREATMENT_TIME_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +#define TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which the treatment state data is published on the CAN bus. -static const U32 TREATMENT_STATE_DATA_PUB_INTERVAL = ( 250 / TASK_GENERAL_INTERVAL ); +#define TREATMENT_STATE_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which updated, valid treatment setting ranges are published on the CAN bus. -static const U32 TREATMENT_SETTINGS_RANGES_PUB_INTERVAL = ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); +#define TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) +/// Interval (ms) at which the treatment periodic data is published on the CAN bus. +static const U32 TREATMENT_PERIODIC_DATA_PUB_INTERVAL = ( 30 * SEC_PER_MIN * MS_PER_SECOND ); +/// Interval (ms) at which the treatment periodic data is logged. +static const U32 TREATMENT_PERIODIC_DATA_LOG_INTERVAL = ( MS_PER_SECOND ); #define CALC_ELAPSED_TREAT_TIME_IN_SECS() ( treatmentTimeMS / MS_PER_SECOND ) ///< Macro to calculate the elapsed treatment time in seconds. /// Macro to calculate the elapsed treatment time in minutes. @@ -75,9 +80,7 @@ static BOOL rinsebackDone; ///< Flag indicates whether a rinseback has been completed. Set FALSE at start of blood prime. Set TRUE at init and end of rinseback. static BOOL treatmentCompleted; ///< Flag indicates whether the treatment has completed. -static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in minutes). -static U32 presBloodFlowRate; ///< Prescribed blood flow rate (in mL/min). -static U32 presDialysateFlowRate; ///< Prescribed dialysate flow rate (in mL/min). +static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in seconds). static F32 presMaxUFVolumeML; ///< Prescribed ultrafiltration volume (in mL). static F32 presUFRate; ///< Prescribed ultrafiltration rate (in mL/min). @@ -86,6 +89,12 @@ static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment time data broadcast timer counter used to schedule when to transmit data. static U32 treatmentStateBroadcastTimerCtr; ///< Treatment state data broadcast timer counter used to schedule when to transmit data. static U32 treatmentParamsRangesBroadcastTimerCtr; ///< Treatment parameter ranges broadcast timer counter used to schedule when to transmit updated ranges. +/// Interval (in task intervals) at which to publish alarm status to CAN bus. +static OVERRIDE_U32_T treatmentTimePublishInterval = { TREATMENT_TIME_DATA_PUB_INTERVAL, TREATMENT_TIME_DATA_PUB_INTERVAL, TREATMENT_TIME_DATA_PUB_INTERVAL, 0 }; +/// Interval (in task intervals) at which to publish alarm status to CAN bus. +static OVERRIDE_U32_T treatmentStatePublishInterval = { TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, 0 }; +/// Interval (in task intervals) at which to publish alarm status to CAN bus. +static OVERRIDE_U32_T treatmentParamRangesPublishInterval = { TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, 0 }; static BOOL resumeTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment resume. static BOOL initiateRinsebackAlarmResponseRequest; ///< Flag indicates user has requested rinseback. @@ -101,11 +110,30 @@ static F32 pendingUFRateChange; ///< An ultrafiltration rate change (mL/min) is pending user confirmation. static U32 pendingTreatmentTimeChange; ///< A treatment time change (min) is pending user confirmation. +static U32 lastTreatmentPeriodicDataPublishTimeStamp; ///< Last treatment 30 minutes periodic data publish time stamp. +static U32 lastTreatmentPeriodicDataCollectTimeStamp; ///< Last treatment periodic data collect time stamp. +static F32 lastUltraFiltrationVolume_mL; ///< Last 30 minutes ultra filtration volume in mL. +static F32 bloodFlowRateSum_mL_min; ///< Blood flow rate sum logged every second. +static F32 dialysateFlowRateSum_mL_min; ///< Dialysate flow rate sum logged every second. +static F32 arterialPressureSum_mmHg; ///< Arterial pressure sum logged every second. +static F32 venousPressureSum_mmHg; ///< Venous pressure sum logged every second. + +static F32 treatmentBloodFlowRateTotal_mL_min; ///< Blood flow rate total per treatment logged every second. +static F32 treatmentDialysateFlowRateTotal_mL_min; ///< Dialysate flow rate total per treatment logged every second. +static F32 treatmentDialysateTempTotal_degree_C; ///< Dialysate temperature total per treatment logged every second. +static F32 treatmentArterialPressureTotal_mmHg; ///< Arterial pressure total per treatment logged every second. +static F32 treatmentVenousPressureTotal_mmHg; ///< Venous pressure total per treatment logged every second. +static BOOL sendLastTreatmentPeriodicData; ///< Flag determines if HD needs to send the last treatment periodic data. + +static U32 treatmentStartTimeStamp; ///< Treatment start timestampt for logging purpose. +static U32 treatmentEndTimeStamp; ///< Treatment end timestampt for logging purpose. + // ********** private function prototypes ********** static void resetSignalFlags( void ); static void resetAlarmSignalFlags( void ); static void broadcastTreatmentSettingsRanges( void ); +static void broadcastTreatmentPeriodicData(); static TREATMENT_STATE_T handleTreatmentStartState( void ); static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ); static TREATMENT_STATE_T handleTreatmentDialysisState( void ); @@ -136,8 +164,6 @@ treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode presTreatmentTimeSecs = 0; - presBloodFlowRate = 0; - presDialysateFlowRate = 0; presMaxUFVolumeML = 0.0; presUFRate = 0.0; @@ -148,6 +174,23 @@ pendingUFVolumeChange = 0.0; pendingUFRateChange = 0.0; pendingTreatmentTimeChange = 0; + + lastTreatmentPeriodicDataPublishTimeStamp = 0; + lastTreatmentPeriodicDataCollectTimeStamp = 0; + lastUltraFiltrationVolume_mL = 0.0; + bloodFlowRateSum_mL_min = 0.0; + dialysateFlowRateSum_mL_min = 0.0; + arterialPressureSum_mmHg = 0.0; + venousPressureSum_mmHg = 0.0; + treatmentBloodFlowRateTotal_mL_min = 0.0; + treatmentDialysateFlowRateTotal_mL_min = 0.0; + treatmentDialysateTempTotal_degree_C = 0.0; + treatmentArterialPressureTotal_mmHg = 0.0; + treatmentVenousPressureTotal_mmHg = 0.0; + sendLastTreatmentPeriodicData = FALSE; + + treatmentStartTimeStamp = getRTCTimestamp(); + treatmentEndTimeStamp = 0; } /*********************************************************************//** @@ -185,9 +228,9 @@ * The transitionToTreatmentMode function prepares for transition to treatment mode. * @details Inputs: none * @details Outputs: - * @return none + * @return initial state *************************************************************************/ -void transitionToTreatmentMode( void ) +U32 transitionToTreatmentMode( void ) { // Initialize treatment mode each time we transition to it initTreatmentMode(); @@ -199,6 +242,8 @@ initRinseback(); initTreatmentRecirc(); initTreatmentEnd(); + + return currentTreatmentState; } /*********************************************************************//** @@ -243,6 +288,19 @@ /*********************************************************************//** * @brief + * The getActualTreatmentTimeSecs function determines the actual treatment + * duration in seconds. + * @details Inputs: treatmentTimeMS + * @details Outputs: none + * @return The actual treatment duration in seconds. + *************************************************************************/ +U32 getActualTreatmentTimeSecs( void ) +{ + return ( treatmentTimeMS / MS_PER_SECOND ); +} + +/*********************************************************************//** + * @brief * The getRinsebackCompleted function determines whether a rinseback has been * completed (indicating blood-side circuit should be primarily saline). * @details Inputs: rinsebackDone @@ -301,6 +359,137 @@ /*********************************************************************//** * @brief + * The getTreatmentAvgBloodFlowRate function returns the average blood flow + * rate collected through out the treatment. + * @details Inputs: treatmentTimeMS, treatmentBloodFlowRateTotal_mL_min + * @details Outputs: none + * @return the average blood flow rate + *************************************************************************/ +F32 getTreatmentAvgBloodFlowRate( void ) +{ + U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); + F32 result = 0.0; + + if ( numberOfDataPoint > 0 ) + { + result = ( treatmentBloodFlowRateTotal_mL_min / numberOfDataPoint ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentAvgDialysateFlowRate function returns the average dialysate + * flow rate collected through out the treatment. + * @details Inputs: treatmentTimeMS, treatmentDialysateFlowRateTotal_mL_min + * @details Outputs: none + * @return the average dialysate flow rate + *************************************************************************/ +F32 getTreatmentAvgDialysateFlowRate( void ) +{ + U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); + F32 result = 0.0; + + if ( numberOfDataPoint > 0 ) + { + result = ( treatmentDialysateFlowRateTotal_mL_min / numberOfDataPoint ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentAvgDialysateTemp function returns the average dialysate + * temperature collected through out the treatment. + * @details Inputs: treatmentTimeMS, treatmentDialysateTempTotal_degree_C + * @details Outputs: none + * @return the average dialysate temperature + *************************************************************************/ +F32 getTreatmentAvgDialysateTemp( void ) +{ + U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); + F32 result = 0.0; + + if ( numberOfDataPoint > 0 ) + { + result = ( treatmentDialysateTempTotal_degree_C / numberOfDataPoint ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentAvgArterialPressure function returns the average arterial + * pressure collected through out the treatment. + * @details Inputs: treatmentTimeMS, treatmentArterialPressureTotal_mmHg + * @details Outputs: none + * @return the average arterial pressure + *************************************************************************/ +F32 getTreatmentAvgArterialPressure( void ) +{ + U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); + F32 result = 0.0; + + if ( numberOfDataPoint > 0 ) + { + result = ( treatmentArterialPressureTotal_mmHg / numberOfDataPoint ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentAvgVenousPressure function returns the average venous + * pressure collected through out the treatment. + * @details Inputs: treatmentTimeMS, treatmentVenousPressureTotal_mmHg + * @details Outputs: none + * @return the average venous pressure + *************************************************************************/ +F32 getTreatmentAvgVenousPressure( void ) +{ + U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); + F32 result = 0.0; + + if ( numberOfDataPoint > 0 ) + { + result = ( treatmentVenousPressureTotal_mmHg / numberOfDataPoint ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentStartTimeStamp function returns the treatment start + * time stamp. + * @details Inputs: treatmentStartTimeStamp + * @details Outputs: none + * @return the treatment start time stamp + *************************************************************************/ +U32 getTreatmentStartTimeStamp( void ) +{ + return treatmentStartTimeStamp; +} + +/*********************************************************************//** + * @brief + * The getTreatmentEndTimeStamp function returns the treatment end + * time stamp. + * @details Inputs: treatmentEndTimeStamp + * @details Outputs: none + * @return the treatment end time stamp + *************************************************************************/ +U32 getTreatmentEndTimeStamp( void ) +{ + return treatmentEndTimeStamp; +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToTreatmentMode function executes the given alarm action * as appropriate while in Treatment Mode. * @details Inputs: none @@ -419,6 +608,11 @@ activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); } + if ( currentTreatmentState != TREATMENT_END_STATE ) + { + checkDialysateTemperature(); + } + // Treatment mode state machine switch ( currentTreatmentState ) { @@ -463,6 +657,7 @@ // Broadcast treatment data broadcastTreatmentTimeAndState(); broadcastTreatmentSettingsRanges(); + broadcastTreatmentPeriodicData(); // Manage air trap control execAirTrapMonitorTreatment(); @@ -488,8 +683,6 @@ lastTreatmentTimeStamp = getMSTimerCount(); 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 ); @@ -527,7 +720,8 @@ { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } @@ -562,6 +756,8 @@ if ( CALC_ELAPSED_TREAT_TIME_IN_SECS() >= presTreatmentTimeSecs ) { treatmentCompleted = TRUE; + sendLastTreatmentPeriodicData = TRUE; + treatmentEndTimeStamp = getRTCTimestamp(); stopDialysis(); transitionToTreatmentEnd(); SET_ALARM_WITH_1_U32_DATA( ALARM_ID_END_OF_TREATMENT_WARNING, presTreatmentTimeSecs ); @@ -622,6 +818,7 @@ // If user requests treatment end, end treatment else if ( TRUE == endTreatmentAlarmResponseRequest ) { + sendLastTreatmentPeriodicData = TRUE; requestNewOperationMode( MODE_POST ); } // Otherwise execute state machine for treatment stop sub-mode @@ -646,10 +843,10 @@ { TREATMENT_STATE_T result = TREATMENT_RINSEBACK_STATE; - // Execute treatment re-circ sub-mode + // Execute treatment rinseback sub-mode execRinseback(); - // Handle signals from treatment end sub-mode + // Handle signals from rinseback sub-mode if ( TRUE == rinsebackToRecircRequest ) { transitionToTreatmentRecirc(); @@ -683,7 +880,7 @@ // Execute treatment re-circ sub-mode execTreatmentRecirc(); - // Handle signals from treatment end sub-mode + // Handle signals from treatment re-circ sub-mode if ( TRUE == rinsebackToStoppedRequest ) { transitionToTreatmentStop(); @@ -719,6 +916,11 @@ { signalTreatmentEndAlarmEndTxUserAction(); } + // Handle alarm response from user to resume slow blood flow while waiting for rinseback request + else if ( TRUE == resumeTreatmentAlarmResponseRequest ) + { + signalTreatmentEndAlarmResumeUserAction(); + } // Execute treatment end sub-mode execTreatmentEnd(); @@ -758,7 +960,7 @@ ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= MIN_TREATMENT_TIME_MINUTES ) ) { F32 uFVolume; - U32 dialVolume = presDialysateFlowRate * treatmentTime; // In mL + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL // Always adjust UF volume to accommodate treatment time change (not UF rate) uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); @@ -767,9 +969,10 @@ ( uFVolume <= MAX_UF_VOLUME_ML ) ) { result = TRUE; + sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), treatmentTime ); presMaxUFVolumeML = uFVolume; presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); } else { @@ -847,9 +1050,9 @@ { 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 = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * 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 ) && @@ -897,7 +1100,7 @@ { if ( MODE_TREA != currMode ) { - rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || ( currentTreatmentState >= TREATMENT_END_STATE ) ) @@ -941,6 +1144,7 @@ DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); + sendTreatmentLogEventData( UF_VOLUME_CHANGE_EVENT, presMaxUFVolumeML, pendingUFVolumeChange ); result = TRUE; presMaxUFVolumeML = pendingUFVolumeChange; @@ -953,7 +1157,8 @@ { presUFRate = pendingUFRateChange; } - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); // If UF paused, resume with new settings if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && @@ -1006,19 +1211,22 @@ U32 dialVolume = dialRate * ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); // In mL // Validate new rates - if ( ( bloodRate >= MIN_BLOOD_FLOW_RATE ) && ( bloodRate <= MAX_BLOOD_FLOW_RATE ) && + if ( ( bloodRate >= MIN_SET_BLOOD_FLOW_RATE ) && ( bloodRate <= MAX_SET_BLOOD_FLOW_RATE ) && ( dialRate >= MIN_DIAL_IN_FLOW_RATE ) && ( dialRate <= MAX_DIAL_IN_FLOW_RATE ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; + sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); + sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); // Set to new rates - presBloodFlowRate = bloodRate; - presDialysateFlowRate = dialRate; - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); + setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); } else { - if ( ( bloodRate < MIN_BLOOD_FLOW_RATE ) || ( bloodRate > MAX_BLOOD_FLOW_RATE ) ) + if ( ( bloodRate < MIN_SET_BLOOD_FLOW_RATE ) || ( bloodRate > MAX_SET_BLOOD_FLOW_RATE ) ) { rejectReason = REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE; } @@ -1036,7 +1244,8 @@ { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } - sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, presBloodFlowRate, presDialysateFlowRate ); + sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), + getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ); // Send new ranges for settings broadcastTreatmentSettingsRanges(); @@ -1114,10 +1323,32 @@ // If changes accepted, set new pressure limits if ( TRUE == result ) { + S32 const artLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + S32 const artHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + S32 const venLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + S32 const venHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + setTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT, data->artLowLimit ); setTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT, data->artHighLimit ); setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT, data->venLowLimit ); setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT, data->venHighLimit ); + + if ( abs( artLowLimit - data->artLowLimit ) > 0 ) + { + sendTreatmentLogEventData( ARTERIAL_PRESSURE_LOWER_LIMIT_CHANGE_EVENT, (F32)artLowLimit, (F32)data->artLowLimit ); + } + if ( abs( artHighLimit - data->artHighLimit ) > 0 ) + { + sendTreatmentLogEventData( ARTERIAL_PRESSURE_UPPER_LIMIT_CHANGE_EVENT, (F32)artHighLimit, (F32)data->artHighLimit ); + } + if ( abs( venLowLimit - data->venLowLimit ) > 0 ) + { + sendTreatmentLogEventData( VENOUS_PRESSURE_LOWER_LIMIT_CHANGE_EVENT, (F32)venLowLimit, (F32)data->venLowLimit ); + } + if ( abs( venHighLimit - data->venHighLimit ) > 0 ) + { + sendTreatmentLogEventData( VENOUS_PRESSURE_UPPER_LIMIT_CHANGE_EVENT, (F32)venHighLimit, (F32)data->venHighLimit ); + } } // Read back limits for transmit to UI. @@ -1146,22 +1377,21 @@ // Update treatment time stats and broadcast - end treatment if time elapsedTreatmentTimeInSecs = CALC_ELAPSED_TREAT_TIME_IN_SECS(); // Broadcast treatment time data at interval - if ( ++treatmentTimeBroadcastTimerCtr >= TREATMENT_TIME_DATA_PUB_INTERVAL ) + if ( ++treatmentTimeBroadcastTimerCtr >= getU32OverrideValue( &treatmentTimePublishInterval ) ) { + TREATMENT_TIME_DATA_T data = { 0, 0, 0 }; + if ( isTreatmentCompleted() != TRUE ) { - U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; - - broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, timeRemaining ); + data.treatmentTimePrescribedinSec = presTreatmentTimeSecs; + data.treatmentTimeElapsedinSec = elapsedTreatmentTimeInSecs; + data.treatmentTimeRemaininginSec = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; } - else // If treatment is completed, send zeroes to UI - { - broadcastTreatmentTime( 0, 0, 0 ); - } + broadcastData( MSG_ID_TREATMENT_TIME, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_TIME_DATA_T ) ); treatmentTimeBroadcastTimerCtr = 0; } // Broadcast treatment state data at interval - if ( ++treatmentStateBroadcastTimerCtr >= TREATMENT_STATE_DATA_PUB_INTERVAL ) + if ( ++treatmentStateBroadcastTimerCtr >= getU32OverrideValue( &treatmentStatePublishInterval ) ) { TREATMENT_STATE_DATA_T payload; @@ -1171,11 +1401,12 @@ payload.txStopState = getCurrentTreatmentStopState(); payload.bldPrimeState = getCurrentBloodPrimeState(); payload.rinsebackState = getCurrentRinsebackState(); - payload.txStopState = getCurrentTreatmentRecircState(); + payload.txRecircState = getCurrentTreatmentRecircState(); payload.txEndState = getCurrentTreatmentEndState(); payload.heparinState = getHeparinState(); + payload.dialysisState = getDialysisState(); - broadcastTreatmentState( payload ); + broadcastData( MSG_ID_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TREATMENT_STATE_DATA_T ) ); treatmentStateBroadcastTimerCtr = 0; } } @@ -1192,7 +1423,7 @@ *************************************************************************/ static void broadcastTreatmentSettingsRanges( void ) { - if ( ++treatmentParamsRangesBroadcastTimerCtr >= TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ) + if ( ++treatmentParamsRangesBroadcastTimerCtr >= getU32OverrideValue( &treatmentParamRangesPublishInterval ) ) { // Compute minimum treatment duration U32 presTime = ( presTreatmentTimeSecs / SEC_PER_MIN ); @@ -1201,7 +1432,7 @@ // Compute maximum treatment duration (from both UF and dialysate volume perspectives) U32 maxTimeRem = ( MAX_UF_VOLUME_ML - (U32)getUltrafiltrationReferenceVolume() ) / ( presUFRate > 0.0 ? (U32)presUFRate : 1 ); U32 maxTime1 = minTime + maxTimeRem; - U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / presDialysateFlowRate; + U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); U32 maxTime = MAX( maxTime1, maxTime2 ); // Compute minimum UF volume F32 minUFVol = getUltrafiltrationReferenceVolume() + presUFRate; @@ -1224,7 +1455,60 @@ } } +/*********************************************************************//** + * @brief + * The broadcastTreatmentPeriodicData function computes and broadcasts + * periodic treatment data during treatment. + * @details Inputs: treatmentPeriodDataBroadcastTimerCtr + * @details Outputs: collected and sent average treatment data over 30 minutes + * @return none + *************************************************************************/ +static void broadcastTreatmentPeriodicData( void ) +{ + U32 const timeElapsedSinceLastCollect_ms = calcTimeBetween( lastTreatmentPeriodicDataCollectTimeStamp, treatmentTimeMS ); + U32 const timeElapsedSinceLastPublish_ms = calcTimeBetween( lastTreatmentPeriodicDataPublishTimeStamp, treatmentTimeMS ); + if ( timeElapsedSinceLastCollect_ms >= TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) + { + F32 const arterialPres = getFilteredArterialPressure(); + F32 const venousPres = getFilteredVenousPressure(); + + lastTreatmentPeriodicDataCollectTimeStamp = treatmentTimeMS; + bloodFlowRateSum_mL_min += getMeasuredBloodFlowRate(); + dialysateFlowRateSum_mL_min += getMeasuredDialInFlowRate(); + arterialPressureSum_mmHg += arterialPres; + venousPressureSum_mmHg += venousPres; + + treatmentBloodFlowRateTotal_mL_min += getMeasuredBloodFlowRate(); + treatmentDialysateFlowRateTotal_mL_min += getMeasuredDialInFlowRate(); + treatmentDialysateTempTotal_degree_C += getDialysateTemperature(); + treatmentArterialPressureTotal_mmHg += arterialPres; + treatmentVenousPressureTotal_mmHg += venousPres; + } + + if ( ( timeElapsedSinceLastPublish_ms >= TREATMENT_PERIODIC_DATA_PUB_INTERVAL ) || ( TRUE == sendLastTreatmentPeriodicData ) ) + { + TREATMENT_LOG_DATA_PERIODIC_T periodTreatmentData; + U32 const numberOfDataPoint = timeElapsedSinceLastPublish_ms / TREATMENT_PERIODIC_DATA_LOG_INTERVAL; + + periodTreatmentData.avgUFRate = ( getUltrafiltrationVolumeCollected() - lastUltraFiltrationVolume_mL ) / ( numberOfDataPoint / SEC_PER_MIN ); + periodTreatmentData.avgBloodFlowRate = bloodFlowRateSum_mL_min / numberOfDataPoint; + periodTreatmentData.avgDialysateFlowRate = dialysateFlowRateSum_mL_min / numberOfDataPoint; + periodTreatmentData.avgArterialPressure = arterialPressureSum_mmHg / numberOfDataPoint; + periodTreatmentData.avgVenousPressure = venousPressureSum_mmHg / numberOfDataPoint; + + sendLastTreatmentPeriodicData = FALSE; + lastTreatmentPeriodicDataPublishTimeStamp = treatmentTimeMS; + lastUltraFiltrationVolume_mL = getUltrafiltrationVolumeCollected(); + bloodFlowRateSum_mL_min = 0.0; + dialysateFlowRateSum_mL_min = 0.0; + arterialPressureSum_mmHg = 0.0; + venousPressureSum_mmHg = 0.0; + sendTreatmentPeriodicDataToUI( &periodTreatmentData ); + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -1255,4 +1539,145 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetTreatmentTimePublishIntervalOverride function sets the override of the + * treatment time data publication interval. + * @details Inputs: none + * @details Outputs: treatmentTimePublishInterval + * @param ms milliseconds between treatment time broadcasts + * @return TRUE if override set successful, FALSE if not + *************************************************************************/ +BOOL testSetTreatmentTimePublishIntervalOverride( U32 ms ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = ms / TASK_GENERAL_INTERVAL; + + result = TRUE; + treatmentTimePublishInterval.ovData = intvl; + treatmentTimePublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetTreatmentTimePublishIntervalOverride function resets the override of the + * treatment time data publication interval. + * @details Inputs: none + * @details Outputs: treatmentTimePublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetTreatmentTimePublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + treatmentTimePublishInterval.override = OVERRIDE_RESET; + treatmentTimePublishInterval.ovData = treatmentTimePublishInterval.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetTreatmentStatePublishIntervalOverride function sets the override of the + * treatment state data publication interval. + * @details Inputs: none + * @details Outputs: treatmentStatePublishInterval + * @param ms milliseconds between treatment state broadcasts + * @return TRUE if override set successful, FALSE if not + *************************************************************************/ +BOOL testSetTreatmentStatePublishIntervalOverride( U32 ms ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = ms / TASK_GENERAL_INTERVAL; + + result = TRUE; + treatmentStatePublishInterval.ovData = intvl; + treatmentStatePublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetTreatmentStatePublishIntervalOverride function resets the override of the + * treatment state data publication interval. + * @details Inputs: none + * @details Outputs: treatmentStatePublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetTreatmentStatePublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + treatmentStatePublishInterval.override = OVERRIDE_RESET; + treatmentStatePublishInterval.ovData = treatmentStatePublishInterval.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetTreatmentParamRangesPublishIntervalOverride function sets the override of the + * treatment param ranges data publication interval. + * @details Inputs: none + * @details Outputs: treatmentParamRangesPublishInterval + * @param ms milliseconds between treatment param range broadcasts + * @return TRUE if override set successful, FALSE if not + *************************************************************************/ +BOOL testSetTreatmentParamRangesPublishIntervalOverride( U32 ms ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = ms / TASK_GENERAL_INTERVAL; + + result = TRUE; + treatmentParamRangesPublishInterval.ovData = intvl; + treatmentParamRangesPublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetTreatmentParamRangesPublishIntervalOverride function resets the override of the + * treatment param ranges data publication interval. + * @details Inputs: none + * @details Outputs: treatmentParamRangesPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetTreatmentParamRangesPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + treatmentParamRangesPublishInterval.override = OVERRIDE_RESET; + treatmentParamRangesPublishInterval.ovData = treatmentParamRangesPublishInterval.ovInitData; + } + + return result; +} + /**@}*/