Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -53,7 +53,6 @@ #define MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE 0.016F ///< Max duty cycle change when ramping down. #define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.90F ///< Controller will error if PWM duty cycle > 90%, so set max to 90%. #define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.10F ///< Controller will error if PWM duty cycle < 10%, so set min to 10%. -#define MIN_DG_DIAL_FLOW_RATE 10.0F ///< Minimum DG Dialysate Flow Rate (mL/Min) #define DIP_CONTROL_INTERVAL_SEC 4 ///< Dialysate inlet pump control interval (in seconds). /// Interval (ms/task time) at which the dialIn pump is controlled. @@ -85,8 +84,8 @@ /// Persist time (task intervals) motor speed error condition. static const U32 DIP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); /// Rotor speed persist time test needs a minimum number of rotations or time. -static const U32 DIP_ROTOR_ERROR_PERSIST_ROTATION_MIN = 10; -static const U32 DIP_ROTOR_ERROR_PERSIST_TIME_MIN = (10 * MS_PER_SECOND); +static const U32 DIP_ROTOR_ERROR_PERSIST_ROTATION_MIN = 20; +static const U32 DIP_ROTOR_ERROR_PERSIST_TIME_MIN = (20 * MS_PER_SECOND); /// Persist time (task intervals) pump direction error condition. static const U32 DIP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); /// Time threshold to trigger an alarm if Dialysate flow data has not arrived within 3 seconds Index: firmware/App/Controllers/DialInFlow.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -14,27 +14,28 @@ * @date (original) 16-Dec-2019 * ***************************************************************************/ - -#ifndef __DIALYSATE_IN_FLOW_H__ -#define __DIALYSATE_IN_FLOW_H__ - -#include "HDCommon.h" - -/** - * @defgroup DialysateInletFlow DialysateInletFlow - * @brief Dialysate Inlet Pump & Dialysate Flow controller/monitor module. - * Monitors the dialysate flow rate and controls the dialysate inlet pump. - * - * @addtogroup DialysateInletFlow - * @{ - */ - -// ********** public definitions ********** - -#define MAX_DIAL_IN_FLOW_RATE 600 ///< Maximum dialysate inlet flow rate (in mL/min). -#define MIN_DIAL_IN_FLOW_RATE 100 ///< Minimum dialysate inlet flow rate (in mL/min). + +#ifndef __DIALYSATE_IN_FLOW_H__ +#define __DIALYSATE_IN_FLOW_H__ + +#include "HDCommon.h" + +/** + * @defgroup DialysateInletFlow DialysateInletFlow + * @brief Dialysate Inlet Pump & Dialysate Flow controller/monitor module. + * Monitors the dialysate flow rate and controls the dialysate inlet pump. + * + * @addtogroup DialysateInletFlow + * @{ + */ + +// ********** public definitions ********** + +#define MAX_DIAL_IN_FLOW_RATE 600 ///< Maximum dialysate inlet flow rate (in mL/min). +#define MIN_DIAL_IN_FLOW_RATE 100 ///< Minimum dialysate inlet flow rate (in mL/min). #define DIALYSATE_FLOW_RATE_FOR_RECIRC 250 ///< Dialysate recirculation flow rate (in mL/min). - +#define MIN_DG_DIAL_FLOW_RATE 10.0F ///< Minimum DG Dialysate Flow Rate (mL/Min) + /// Payload record structure for a dialysate inlet pump data message. typedef struct { @@ -50,50 +51,50 @@ U32 rotorHall; ///< Rotor hall in counts. } DIALIN_PUMP_STATUS_PAYLOAD_T; -// ********** public function prototypes ********** - -void initDialInFlow( void ); -void execDialInFlowMonitor( void ); -void execDialInFlowController( void ); - -BOOL setDialInPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir, PUMP_CONTROL_MODE_T mode ); +// ********** public function prototypes ********** + +void initDialInFlow( void ); +void execDialInFlowMonitor( void ); +void execDialInFlowController( void ); + +BOOL setDialInPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir, PUMP_CONTROL_MODE_T mode ); BOOL setDialInPumpTargetRPM( U32 rpm, MOTOR_DIR_T dir ); -void signalDialInPumpHardStop( void ); +void signalDialInPumpHardStop( void ); void signalDialInPumpRotorHallSensor( void ); -BOOL homeDialInPump( void ); +BOOL homeDialInPump( void ); BOOL isDialInPumpRunning( void ); BOOL isDialInPumpRampComplete( void ); void resetDialInPumpRotorCount( void ); - -SELF_TEST_STATUS_T execDialInFlowTest( void ); - -S32 getTargetDialInFlowRate( void ); + +SELF_TEST_STATUS_T execDialInFlowTest( void ); + +S32 getTargetDialInFlowRate( void ); F32 getMeasuredDialInFlowRate( void ); -F32 getMeasuredDialInPumpRotorSpeed( void ); -F32 getMeasuredDialInPumpSpeed( void ); -F32 getMeasuredDialInPumpMCSpeed( void ); +F32 getMeasuredDialInPumpRotorSpeed( void ); +F32 getMeasuredDialInPumpSpeed( void ); +F32 getMeasuredDialInPumpMCSpeed( void ); F32 getMeasuredDialInPumpMCCurrent( void ); F32 getDialInPumpPWMDutyCyclePct( BOOL init ); U32 getDialInPumpRotorCount( void ); U32 getPumpRotorErrorPersistTime( F32 mtr_speed, F32 gear_ratio ); - -BOOL testSetDialInFlowDataPublishIntervalOverride( U32 value ); -BOOL testResetDialInFlowDataPublishIntervalOverride( void ); -BOOL testSetTargetDialInFlowRateOverride( S32 value, U32 ctrlMode ); -BOOL testSetMeasuredDialInFlowRateOverride( F32 value ); -BOOL testResetMeasuredDialInFlowRateOverride( void ); -BOOL testSetMeasuredDialInPumpRotorSpeedOverride( F32 value ); -BOOL testResetMeasuredDialInPumpRotorSpeedOverride( void ); -BOOL testSetMeasuredDialInPumpSpeedOverride( F32 value ); -BOOL testResetMeasuredDialInPumpSpeedOverride( void ); -BOOL testSetMeasuredDialInPumpMCSpeedOverride( F32 value ); -BOOL testResetMeasuredDialInPumpMCSpeedOverride( void ); -BOOL testSetMeasuredDialInPumpMCCurrentOverride( F32 value ); + +BOOL testSetDialInFlowDataPublishIntervalOverride( U32 value ); +BOOL testResetDialInFlowDataPublishIntervalOverride( void ); +BOOL testSetTargetDialInFlowRateOverride( S32 value, U32 ctrlMode ); +BOOL testSetMeasuredDialInFlowRateOverride( F32 value ); +BOOL testResetMeasuredDialInFlowRateOverride( void ); +BOOL testSetMeasuredDialInPumpRotorSpeedOverride( F32 value ); +BOOL testResetMeasuredDialInPumpRotorSpeedOverride( void ); +BOOL testSetMeasuredDialInPumpSpeedOverride( F32 value ); +BOOL testResetMeasuredDialInPumpSpeedOverride( void ); +BOOL testSetMeasuredDialInPumpMCSpeedOverride( F32 value ); +BOOL testResetMeasuredDialInPumpMCSpeedOverride( void ); +BOOL testSetMeasuredDialInPumpMCCurrentOverride( F32 value ); BOOL testResetMeasuredDialInPumpMCCurrentOverride( void ); BOOL testSetDialInPumpTargetDutyCycle( F32 value ); BOOL testSetDialysateInPumpRotorCountOverride( U32 value ); -BOOL testResetDialysateInPumpRotorCountOverride( void ); - -/**@}*/ - -#endif +BOOL testResetDialysateInPumpRotorCountOverride( void ); + +/**@}*/ + +#endif Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -29,6 +29,7 @@ #include "OperationModes.h" #include "PresOccl.h" #include "Reservoirs.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -44,12 +45,6 @@ #define MAX_UF_VOLUME_ACCURACY_ERROR_ML 100.0F ///< Maximum ultrafiltration volume accuracy error in mL over the entire treatment. #define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 20.0F ///< Reservoir load cell drift difference allowed -/// Saline bolus data broadcast interval (ms/task time) count. -static const U32 SALINE_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - -#define MAX_SALINE_VOLUME_DELIVERED 800 ///< Maximum saline volume delivered for a treatment. -#define SALINE_BOLUS_RATE_ML_MIN 300 ///< Fixed rate for saline bolus delivery. - #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. // 3.07 + 12.28 has been received from the mechanical team and extra volume as margin has been added for safety @@ -86,9 +81,8 @@ BLOOD_LEAK_ZEROING_STATE_T bloodLeakZeroingState; ///< Blood leak zeroing state. } BLOOD_LEAK_ZEROING_T ; -static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. -static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. -static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. +static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. +static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. static F32 refUFVolume; ///< Current reference volume for ultrafiltration (Where should we be w/r/t ultrafiltration). static F32 measUFVolume; ///< Current total measured volume for ultrafiltration (Where are we w/r/t ultrafiltration). static F32 resStartVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir start volume for ultrafiltration (i.e. where did we start with each reservoir). @@ -98,7 +92,7 @@ static F32 resCurrVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir current volume. static F32 resLastVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Previous reading of reservoir volume. static F32 measUFVolumeFromPriorReservoirs; ///< Current total ultrafiltration volume from previous reservoirs in current treatment. -static F32 lcLastSteadyWeight[NUM_OF_RESERVOIR_STEADY_CYCLES][NUM_OF_LOAD_CELLS]; ///< Load Cell Last Steady Weight for drift test Start/Final cycle +static F32 lcLastSteadyWeight[ NUM_OF_RESERVOIR_STEADY_CYCLES ][ NUM_OF_LOAD_CELLS ]; ///< Load Cell Last Steady Weight for drift test Start/Final cycle static U32 uFTimeMS; ///< Current elapsed ultrafiltration time (in ms). Used for calculating UF reference volume. static U32 lastUFTimeStamp; ///< HD timer value when we last took stock of ultrafiltration time (so we can determine how much time has elapsed since). @@ -108,13 +102,7 @@ static F32 setUFVolumeML; ///< Currently set total ultrafiltration volume for treatment (from prescription). static F32 setUFRate; ///< Currently set ultrafiltration rate (from prescription). -static U32 salineBolusBroadcastTimerCtr; ///< Saline bolus data broadcast timer counter used to schedule when to transmit data. -static BOOL salineBolusStartRequested; ///< Flag indicates a saline bolus start has been requested by user. -static BOOL salineBolusAbortRequested; ///< Flag indicates a salien bolus abort has been requested by user. static BOOL autoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. -static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). -static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). -static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. static BLOOD_LEAK_ZEROING_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // ********** private function prototypes ********** @@ -126,11 +114,6 @@ static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ); -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ); -static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); - static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ); static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushReservoir2DPiState( void ); static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushDPi2BLDState( void ); @@ -141,7 +124,6 @@ static void checkUFControl( void ); static void updateUFVolumes( void ); -static void publishSalineBolusData( void ); static void checkLoadCellsStablePrimaryBackupDriftOutOfRange( DG_RESERVOIR_ID_T reservoirID, RESERVOIR_STEADY_CYCLE_T cycle ); /*********************************************************************//** @@ -159,7 +141,6 @@ currentDialysisState = DIALYSIS_UF_STATE; currentUFState = UF_RUNNING_STATE; - currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; lastUFTimeStamp = getMSTimerCount(); uFTimeMS = 0; @@ -178,14 +159,12 @@ setUFRate = 0.0; resetDialOutRateOffset(); - salineBolusBroadcastTimerCtr = 0; - totalSalineVolumeDelivered_mL = 0.0; autoResumeUF = FALSE; for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_START][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; - lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_FINAL][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; + lcLastSteadyWeight[ RESERVOIR_STEADY_CYCLE_START ][ i ] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; + lcLastSteadyWeight[ RESERVOIR_STEADY_CYCLE_FINAL ][ i ] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; } for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) @@ -202,27 +181,16 @@ /*********************************************************************//** * @brief - * The resetSalineBolus function initializes the saline bolus variables - * at start of treatment or after stopping a bolus (e.g. alarm). Total - * saline bolus volume delivered will not be affected by this function. + * The resetUF function resets the ultrafiltration state and status. * @details Inputs: autoResumeUF - * @details Outputs: salineBolusStartRequested, salineBolusAbortRequested, - * bolusSalineVolumeDelivered_mL, currentSalineBolusState, autoResumeUF, - * currentUFState, currentDialysisState + * @details Outputs: autoResumeUF, currentUFState, currentDialysisState * @return none *************************************************************************/ -void resetSalineBolus( void ) +void resetUF( void ) { - salineBolusStartRequested = FALSE; - salineBolusAbortRequested = FALSE; - bolusSalineVolumeDelivered_mL = 0.0; - if ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) - { - currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; - } if ( TRUE == autoResumeUF ) { - autoResumeUF = FALSE; + autoResumeUF = FALSE; currentUFState = UF_RUNNING_STATE; } currentDialysisState = DIALYSIS_UF_STATE; @@ -418,91 +386,6 @@ /*********************************************************************//** * @brief - * The signalStartSalineBolus function handles user request to initiate a - * saline bolus. - * @details Inputs: set bolus volume, current mode/sub-mode, bolus state - * @details Outputs: salineBolusStartRequested, response sent - * @return none - *************************************************************************/ -void signalStartSalineBolus( void ) -{ - BOOL accept = FALSE; - REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; - U32 salineBolusVolume = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - HD_OP_MODE_T currOpMode = getCurrentOperationMode(); - TREATMENT_STATE_T currTreatSubMode = getTreatmentState(); - - // Must be in treatment mode, dialysis sub-mode, saline bolus in idle state in order to start a saline bolus - if ( currOpMode != MODE_TREA ) - { - rejReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; - } - else if ( currTreatSubMode != TREATMENT_DIALYSIS_STATE ) - { - rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; - } - else if ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; - } - else if ( DIALYSIS_SALINE_BOLUS_STATE == currentDialysisState ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; - } - else - { - accept = TRUE; - salineBolusStartRequested = TRUE; - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - } - - // Send response - sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); -} - -/*********************************************************************//** - * @brief - * The signalAbortSalineBolus function handles user request to abort a - * saline bolus. - * @details Inputs: set bolus volume, current mode/sub-mode, bolus state - * @details Outputs: salineBolusAbortRequested, response sent - * @return none - *************************************************************************/ -void signalAbortSalineBolus( void ) -{ - BOOL accept = FALSE; - REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; - U32 salineBolusVolume = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - HD_OP_MODE_T currOpMode = getCurrentOperationMode(); - TREATMENT_STATE_T currTreatSubMode = getTreatmentState(); - SALINE_BOLUS_STATE_T currSalineBolusState = getSalineBolusState(); - - // Must be in treatment mode, dialysis sub-mode, saline bolus in delivery state in order to abort a saline bolus - if ( currOpMode != MODE_TREA ) - { - rejReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; - } - else if ( currTreatSubMode != TREATMENT_DIALYSIS_STATE ) - { - rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; - } - else if ( currSalineBolusState != SALINE_BOLUS_STATE_IN_PROGRESS ) - { - rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_NOT_IN_PROGRESS; - } - else - { - accept = TRUE; - salineBolusAbortRequested = TRUE; - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - } - - // Send response - sendSalineBolusResponse( accept, rejReason, salineBolusVolume ); -} - -/*********************************************************************//** - * @brief * The getDialysisState function gets the current dialysis state (sub-mode). * @details Inputs: currentDialysisState * @details Outputs: none @@ -527,18 +410,6 @@ /*********************************************************************//** * @brief - * The getSalineBolusState function gets the current saline bolus state. - * @details Inputs: currentSalineBolusState - * @details Outputs: none - * @return currentSalineBolusState - *************************************************************************/ -SALINE_BOLUS_STATE_T getSalineBolusState( void ) -{ - return currentSalineBolusState; -} - -/*********************************************************************//** - * @brief * The getBloodLeakZeroingState function gets the current blood leak zeroing * state of the state machine. * @details Inputs: bloodLeakZeroingStatus @@ -578,19 +449,6 @@ /*********************************************************************//** * @brief - * The getTotalSalineBolusVolumeDelivered function gets the current total - * saline volume delivered. - * @details Inputs: totalSalineVolumeDelivered - * @details Outputs: none - * @return totalSalineVolumeDelivered - *************************************************************************/ -F32 getTotalSalineBolusVolumeDelivered( void ) -{ - return totalSalineVolumeDelivered_mL; -} - -/*********************************************************************//** - * @brief * The pauseUF function pauses ultrafiltration. * @details Inputs: currentDialysisState, currentUFState, setUFRate * @details Outputs: currentUFState, outlet pump set point @@ -754,8 +612,9 @@ setCurrentSubState( (U32)currentDialysisState ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDialysisState ); } + // Publish saline bolus data at set interval (whether we are delivering one or not) - publishSalineBolusData(); + publishSalineBolusData( bloodLeakZeroingStatus.DPi2BLDFlushedVolML, bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML, (U32)bloodLeakZeroingStatus.zeroingRequestState ); } /*********************************************************************//** @@ -816,41 +675,31 @@ *************************************************************************/ static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ) { - DIALYSIS_STATE_T result = DIALYSIS_SALINE_BOLUS_STATE; + DIALYSIS_STATE_T result = DIALYSIS_SALINE_BOLUS_STATE; + SALINE_BOLUS_STATE_T currSalineBolusState = execSalineBolus(); - SALINE_BOLUS_STATE_T priorSubState = currentSalineBolusState; - - switch ( currentSalineBolusState ) + if ( SALINE_BOLUS_STATE_IDLE == currSalineBolusState ) { - case SALINE_BOLUS_STATE_IDLE: - currentSalineBolusState = handleSalineBolusIdleState(); - break; + result = DIALYSIS_UF_STATE; - case SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP: - currentSalineBolusState = handleSalineBolusWait4Pumps2Stop(); - break; - - case SALINE_BOLUS_STATE_IN_PROGRESS: - currentSalineBolusState = handleSalineBolusInProgressState( &result ); - break; - - case SALINE_BOLUS_STATE_MAX_DELIVERED: - currentSalineBolusState = handleSalineBolusMaxDeliveredState( &result ); - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_SALINE_BOLUS_STATE, currentSalineBolusState ) - currentSalineBolusState = SALINE_BOLUS_STATE_MAX_DELIVERED; - break; + if ( FALSE == isAlarmActive( ALARM_ID_HD_EMPTY_SALINE_BAG ) ) + { + // Resume UF if appropriate + if ( TRUE == autoResumeUF ) + { + autoResumeUF = FALSE; + currentUFState = UF_RUNNING_STATE; + //Set substate for event + setCurrentSubState( (U32)DIALYSIS_UF_STATE ); + setCurrent4thLevelState( (U32)currentUFState ); + sendOperationStatusEvent(); + } + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Resume dialysis + transitionToDialysis(); + } } - // MAX DELIVERED transitions different and sends the event on its own. - if ( priorSubState != currentSalineBolusState && currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) - { - setCurrent4thLevelState( (U32)currentSalineBolusState ); - SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentSalineBolusState ); - } - return result; } @@ -885,18 +734,18 @@ UF_STATE_T result = UF_PAUSED_STATE; // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) + if ( TRUE == isSalineBolusStartRequested() ) { autoResumeUF = FALSE; // Go to saline bolus state if we can - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + if ( SALINE_BOLUS_STATE_IDLE == getSalineBolusState() ) { *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - setCurrent4thLevelState( (U32)currentSalineBolusState ); + setCurrent4thLevelState( (U32)getSalineBolusState() ); } else { - salineBolusStartRequested = FALSE; + setSalineBolusStartRequestStatus( FALSE ); } } else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) @@ -947,21 +796,21 @@ } // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) + if ( TRUE == isSalineBolusStartRequested() ) { - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) + if ( SALINE_BOLUS_STATE_IDLE == getSalineBolusState() ) { // Since we were doing UF prior to saline bolus, we want to auto-resume when done autoResumeUF = TRUE; // Go to UF paused state result = UF_PAUSED_STATE; // Go to saline bolus state *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - setCurrent4thLevelState( (U32)currentSalineBolusState ); + setCurrent4thLevelState( (U32)getSalineBolusState() ); } else { - salineBolusStartRequested = FALSE; + setSalineBolusStartRequestStatus( FALSE ); } } else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) @@ -984,177 +833,6 @@ /*********************************************************************//** * @brief - * The handleSalineBolusIdleState function handles the idle state of the - * saline bolus state machine. - * @details Inputs: none - * @details Outputs: - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IDLE; - - // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) - { - salineBolusStartRequested = FALSE; - // Cmd all pumps to stop - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - stopSyringePump(); - // Begin saline bolus - result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSalineBolusWait4Pumps2Stop function handles the wait for pumps - * to stop state of the saline bolus state machine. - * @details Inputs: none - * @details Outputs: - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; - - if ( ( FALSE == isBloodPumpRunning() ) && ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) - { - // Reset bolus data before we start - bolusSalineVolumeDelivered_mL = 0.0; - bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - - // Bypass dialyzer - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - // Switch to saline bag - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - // Start blood pump at saline bolus rate - setBloodPumpTargetFlowRate( SALINE_BOLUS_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Start dialysate inlet pump at re-circ rate - setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Begin saline bolus - result = SALINE_BOLUS_STATE_IN_PROGRESS; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSalineBolusInProgressState function handles the in-progress state of the - * saline bolus state machine. - * @details Inputs: none - * @details Outputs: - * @param dialysisState next dialysis state - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IN_PROGRESS; - BOOL errorFound = FALSE; - F32 timeSinceLastVolumeUpdateMin = (F32)calcTimeSince( bolusSalineLastVolumeTimeStamp ) / (F32)( MS_PER_SECOND * SEC_PER_MIN ); - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - F32 bldFlowRate = getMeasuredBloodFlowRate(); - F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; - F32 expVolSinceLastUpdateMl = (F32)getTargetBloodFlowRate() * timeSinceLastVolumeUpdateMin; - - // Update saline bolus volumes - bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; - totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; - - // Check for empty saline bag per arterial line pressure - if ( TRUE == isSalineBagEmpty() ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_EMPTY_SALINE_BAG, getMeasuredArterialPressure() ); - errorFound = TRUE; - result = SALINE_BOLUS_STATE_IDLE; - } - - // Determine if we have reached maximum saline delivery volume - if ( ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) - { - result = SALINE_BOLUS_STATE_MAX_DELIVERED; - setCurrent4thLevelState( (U32)result ); - sendOperationStatusEvent(); - } - else - { - // Determine if bolus is complete - if ( bolusSalineVolumeDelivered_mL >= bolusTargetVolume ) - { - result = SALINE_BOLUS_STATE_IDLE; - } - // User is aborting saline bolus - else if ( TRUE == salineBolusAbortRequested ) - { - salineBolusAbortRequested = FALSE; - result = SALINE_BOLUS_STATE_IDLE; - } - } - - // Are we stopping the bolus? - if ( result != SALINE_BOLUS_STATE_IN_PROGRESS ) - { - // Hard stop blood and dialysate pumps - signalBloodPumpHardStop(); - signalDialInPumpHardStop(); - // Send last saline bolus data - salineBolusBroadcastTimerCtr = SALINE_BOLUS_DATA_PUB_INTERVAL; - publishSalineBolusData(); - sendTreatmentLogEventData( SALINE_BOLUSES_CHANGE_EVENT, bolusSalineVolumeDelivered_mL, totalSalineVolumeDelivered_mL ); - bolusSalineVolumeDelivered_mL = 0.0; - // Dialysis back to UF state - *dialysisState = DIALYSIS_UF_STATE; - // End dialyzer bypass and resume dialysis if no alarms triggered - if ( FALSE == errorFound ) - { - // Resume UF if appropriate - if ( TRUE == autoResumeUF ) - { - autoResumeUF = FALSE; - currentUFState = UF_RUNNING_STATE; - //Set substate for event - setCurrentSubState( (U32)DIALYSIS_UF_STATE ); - setCurrent4thLevelState( (U32)currentUFState ); - sendOperationStatusEvent(); - } - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); - // Resume dialysis - transitionToDialysis(); - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSalineBolusMaxDeliveredState function handles the max saline delivered - * state of the saline bolus state machine. This is a terminal state. - * @details Inputs: none - * @details Outputs: - * @param dialysisState next dialysis state - * @return next saline bolus state - *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ) -{ - SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_MAX_DELIVERED; - - // This is a terminal state for a given treatment - no more saline may be delivered to patient - // If we get here, pop back to UF - *dialysisState = DIALYSIS_UF_STATE; - - return result; -} - -/*********************************************************************//** - * @brief * The handleBloodLeakZeroingIdleState function handles the blood leak zeroing * idle state. In this state the actuators and parameters are set to run * the blood leak zeroing state machine. @@ -1332,33 +1010,6 @@ /*********************************************************************//** * @brief - * The publishSalineBolusData function handles the max saline delivered - * state of the saline bolus state machine. This is a terminal state. - * @details Inputs: none - * @details Outputs: - * @param dialysisState next dialysis state - * @return next saline bolus state - *************************************************************************/ -static void publishSalineBolusData( void ) -{ - if ( ++salineBolusBroadcastTimerCtr >= SALINE_BOLUS_DATA_PUB_INTERVAL ) - { - SALINE_BOLUS_DATA_PAYLOAD_T data; - - data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; - data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; - data.bloodLeakZeroingDPi2BLDFlushVolumeML = bloodLeakZeroingStatus.DPi2BLDFlushedVolML; - data.bloodLeakZeroingRsrvr2DPiFlushVolumeML = bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML; - data.bloodLeakZeroingNeededAfterRsrvrSwitch = (U32)bloodLeakZeroingStatus.zeroingRequestState; - - broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); - salineBolusBroadcastTimerCtr = 0; - } -} - -/*********************************************************************//** - * @brief * The checkUFControl function checks ultrafiltration control to ensure measured * UF volume does not deviate too far from the UF reference volume (indicating * poor UF control). Index: firmware/App/Modes/Dialysis.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -36,25 +36,10 @@ // ********** public definitions ********** -#pragma pack(push,1) - -/// Payload record structure for a saline bolus data broadcast message. -typedef struct -{ - U32 tgtSalineVolumeMl; ///< Target saline volume in mL. - F32 cumSalineVolumeMl; ///< Cumulative saline volume in mL. - F32 bolSalineVolumeMl; ///< Bolus saline volume in mL. - F32 bloodLeakZeroingDPi2BLDFlushVolumeML; ///< Blood leak zeroing DPi to BLD flush volume in mL. - F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML; ///< Blood leak zeroing reservoir to DPi flush volume in mL. - U32 bloodLeakZeroingNeededAfterRsrvrSwitch; ///< Blood leak zeroing needed after reservoir switch. -} SALINE_BOLUS_DATA_PAYLOAD_T; - -#pragma pack(pop) - // ********** public function prototypes ********** void initDialysis( void ); -void resetSalineBolus( void ); +void resetUF( void ); void transitionToDialysis( void ); void execDialysis( void ); @@ -63,17 +48,12 @@ void stopDialysis( void ); void startHeparinPump( void ); -void signalStartSalineBolus( void ); -void signalAbortSalineBolus( void ); - DIALYSIS_STATE_T getDialysisState( void ); UF_STATE_T getUltrafiltrationState( void ); -SALINE_BOLUS_STATE_T getSalineBolusState( void ); BLOOD_LEAK_ZEROING_STATE_T getBloodLeakZeroingState( void ); F32 getUltrafiltrationVolumeCollected( void ); F32 getUltrafiltrationReferenceVolume( void ); -F32 getTotalSalineBolusVolumeDelivered( void ); BOOL pauseUF( void ); BOOL resumeUF( void ); Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -30,6 +30,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "RTC.h" +#include "SalineBolus.h" #include "SampleWater.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -1027,6 +1027,14 @@ clearAlarm( ALARM_ID_DG_TURN_OFF_INLET_WATER_VALVES ); clearCurrentCleaningModeStatus(); } + else + { + // If we are in the cleaning modes and the corresponding placeholder alarm is not active, reactivate it. + if ( FALSE == isAlarmActive( currentDGCleaningMode.alarmID ) ) + { + activateAlarmNoData( currentDGCleaningMode.alarmID ); + } + } return state; } @@ -1049,12 +1057,22 @@ { if ( ( TRUE == stop ) && ( GENERIC_CONFIRM_ID_NONE == disinfectCancelReqID ) ) { - disinfectCancelReqID = addConfirmationRequest( currentDGCleaningMode.stopRequestCmdID, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; + + genericConfRequest.requestID = (U32)currentDGCleaningMode.stopRequestCmdID; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + + disinfectCancelReqID = addConfirmationRequest( &genericConfRequest ); } else if ( disinfectCancelReqID != GENERIC_CONFIRM_ID_NONE ) { // Get the confirmation request. It consumes the request if completed and responds to UI. - confirm_status = getConfirmationRequestStatus( disinfectCancelReqID ); + confirm_status = getConfirmationRequestStatus( disinfectCancelReqID, 0.0F, 0.0F, 0.0F, 0.0F ); switch ( confirm_status ) { case CONFIRMATION_REQUEST_STATUS_ACCEPTED: @@ -1213,16 +1231,27 @@ } else if ( ( TRUE == currentDGCleaningMode.sampleRqstTrgrd ) && ( FALSE == isAlarmActive( ALARM_ID_DG_CHEM_DISINFECT_FLUSH_FLUSH_SAMPLE ) ) ) { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; + // Sample flush alarm has been triggered and the user has cleared the alarm by pressing Ok. The user is collecting sample. // Send the notification to the UI to prompt the pass/fail screen so the user can choose whether the sampling after flush passed or failed currentDGCleaningMode.sampleRqstTrgrd = FALSE; - currentDGCleaningMode.sampleRequestID = addConfirmationRequest( GENERIC_CONFIRM_ID_DISINFECT_CHEM_FLUSH_SAMPLE_PASS_FAIL, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_DISINFECT_CHEM_FLUSH_SAMPLE_PASS_FAIL; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + + currentDGCleaningMode.sampleRequestID = addConfirmationRequest( &genericConfRequest ); } if ( currentDGCleaningMode.sampleRequestID != GENERIC_CONFIRM_ID_NONE ) { // There is a user confirm - CONFIRMATION_REQUEST_STATUS_T status = getConfirmationRequestStatus( currentDGCleaningMode.sampleRequestID ); + CONFIRMATION_REQUEST_STATUS_T status = getConfirmationRequestStatus( currentDGCleaningMode.sampleRequestID, 0.0F, 0.0F, 0.0F, 0.0F ); U32 sampleStatus = 0; switch( status ) @@ -1267,16 +1296,27 @@ } else if ( ( TRUE == currentDGCleaningMode.sampleRqstTrgrd ) && ( FALSE == isAlarmActive( ALARM_ID_DG_RO_PERMEATE_SAMPLE_REMOVE_DIA_CAP ) ) ) { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; + // Sample flush alarm has been triggered and the user has cleared the alarm by pressing Ok. The user is collecting sample. // Send the notification to the UI to prompt the pass/fail screen so the user can choose whether the sampling after flush passed or failed currentDGCleaningMode.sampleRqstTrgrd = FALSE; - currentDGCleaningMode.sampleRequestID = addConfirmationRequest( GENERIC_CONFIRM_ID_RO_PERMEATE_SAMPLE_STOP_OR_DISPENSE, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_RO_PERMEATE_SAMPLE_STOP_OR_DISPENSE; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + + currentDGCleaningMode.sampleRequestID = addConfirmationRequest( &genericConfRequest ); } if ( currentDGCleaningMode.sampleRequestID != GENERIC_CONFIRM_ID_NONE ) { // There is a user confirm - CONFIRMATION_REQUEST_STATUS_T status = getConfirmationRequestStatus( currentDGCleaningMode.sampleRequestID ); + CONFIRMATION_REQUEST_STATUS_T status = getConfirmationRequestStatus( currentDGCleaningMode.sampleRequestID, 0.0F, 0.0F, 0.0F, 0.0F ); U32 sampleStatus = 0; switch( status ) Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -33,6 +33,7 @@ #include "Reservoirs.h" #include "Rinseback.h" #include "RTC.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -57,7 +58,9 @@ #define USER_CONFIRM_CHANGE_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Require user to confirm UF volume change within this time. #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). +#define UF_RATE_CONFIRM_MSG_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< UF rate confirm message timeout in milliseconds. + /// Interval (ms/task time) at which the treatment time data is published on the CAN bus. #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. @@ -75,6 +78,15 @@ /// Macro to calculate the remaining treatment time in seconds. #define CALC_TREAT_TIME_REMAINING_IN_SECS() ( (S32)presTreatmentTimeSecs - (S32)( treatmentTimeMS / MS_PER_SECOND ) ) +/// Treatment duration requested values +typedef struct +{ + U32 requestedTxDurationMins; ///< Requested treatment duration from the user in minutes. + F32 newUFRateMLPM; ///< New calculated UF rate in mL/Min. + BOOL isUFRateConfInProgress; ///< Boolean flag to indicate whether a new UF rate confirmation has been requested. + U32 rqstStartTimeStamp; ///< Request start time stamp. +} TREATMENT_DURATION_RQST_T; + // ********** private data ********** static TREATMENT_STATE_T currentTreatmentState; ///< Current state (sub-mode) of treatment mode. @@ -133,6 +145,8 @@ static U32 treatmentStartTimeStamp; ///< Treatment start timestampt for logging purpose. static U32 treatmentEndTimeStamp; ///< Treatment end timestampt for logging purpose. +static TREATMENT_DURATION_RQST_T txDurationRequest; ///< Treatment duration request structure. + // ********** private function prototypes ********** static void broadcastTreatmentSettingsRanges( void ); @@ -199,6 +213,10 @@ treatmentStartTimeStamp = getRTCTimestamp(); treatmentEndTimeStamp = 0; + txDurationRequest.requestedTxDurationMins = 0; + txDurationRequest.newUFRateMLPM = 0.0F; + txDurationRequest.isUFRateConfInProgress = FALSE; + // reset dialysate temperature alarm persistences prior to starting a treatment. resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ); resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ); @@ -221,6 +239,7 @@ // Initialize treatment mode each time we transition to it initTreatmentMode(); initReservoirs(); + initSalineBolus(); // Initialize treatment sub-modes each time we transition to treatment mode initBloodPrime(); initDialysis(); @@ -1048,6 +1067,7 @@ BOOL verifyTreatmentDurationSettingChange( U32 treatmentTime ) { BOOL result = FALSE; + BOOL isResp2UINeeded = TRUE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); @@ -1056,38 +1076,72 @@ ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_END_STATE ) && ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= getMinTreatmentTimeInMinutes() ) ) { - // Always adjust UF volume to accommodate treatment time change (not UF rate) - F32 uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); - F32 uFVolumeL = uFVolume / ML_PER_LITER; - U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL + // Always keep the UF volume the same and change the UF rate upon changing the treatment time + presMaxUFVolumeML = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; + + // New UF rate is how much UF is left to be done / remaining treatment time + F32 measUFVolML = getTotalMeasuredUFVolumeInMl(); + F32 newUFDiffML = ( ( presMaxUFVolumeML - measUFVolML ) < 0.0F ? 0.0F : ( presMaxUFVolumeML - measUFVolML ) ); + F32 newTxTimeS = (F32)treatmentTime * (F32)SEC_PER_MIN; + F32 elapsedTxTimeS = (F32)treatmentTimeMS / (F32)MS_PER_SECOND; + F32 timeDiffMin = (newTxTimeS - elapsedTxTimeS) / (F32)SEC_PER_MIN; + F32 newUFRateMLPM = newUFDiffML / timeDiffMin; + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL + + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_UF_RATE_TX_DUR, newUFDiffML, newUFRateMLPM ) + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_UF_RATE_TIME_TX_DUR, elapsedTxTimeS, timeDiffMin ) + // The minimum treatment time is either in the range of the institutional record or the 1-minute treatment config has been requested which is an exception BOOL isMinTxTimeValid = ( ( treatmentTime >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ) ? TRUE : FALSE ); BOOL isTxTimeValid = ( ( TRUE == isMinTxTimeValid ) && ( treatmentTime <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) ? TRUE : FALSE ); - BOOL isMinUFVolValid = ( ( uFVolumeL >= getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) || ( uFVolumeL <= 0.0F ) ? TRUE : FALSE ); - BOOL isUFVolValid = ( ( TRUE == isMinUFVolValid ) && ( uFVolumeL <= getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) ? TRUE : FALSE ); + // Only the upper range UF rate is checked here. Per the check above if the UF diff is < 0, it is set to zero so the minimum UF rate is 0 and cannot be negative + BOOL isUFRateValid = ( newUFRateMLPM <= MAX_UF_RATE_ML_MIN ? TRUE : FALSE ); - if ( ( TRUE == isTxTimeValid ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && ( TRUE == isUFVolValid ) ) + if ( ( TRUE == isTxTimeValid ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && ( TRUE == isUFRateValid ) ) { result = TRUE; - sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), treatmentTime ); - presMaxUFVolumeML = uFVolume; - presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; - setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); - setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, ( presTreatmentTimeSecs / SEC_PER_MIN ) ); - setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); - signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + + if ( presMaxUFVolumeML > 0.0F ) + { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; + + // Don't send the treatment duration change response to UI because we have UF volume so the UF rate changes and it needs the approval of the user + // If the UF volume in the treatment is 0 then send the response back to UI + isResp2UINeeded = FALSE; + + // Store the proposed treatment duration and the calculated new UF rate until the user approves it + txDurationRequest.requestedTxDurationMins = treatmentTime; + txDurationRequest.newUFRateMLPM = newUFRateMLPM; + txDurationRequest.isUFRateConfInProgress = TRUE; + txDurationRequest.rqstStartTimeStamp = getMSTimerCount(); + + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_UF_RATE_CHANGE_IN_TX_DURATION_CHANGE; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = txDurationRequest.newUFRateMLPM ; // TODO convert to L/hr for UI + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + + addConfirmationRequest( &genericConfRequest ); + } + else + { + // Update the treatment time since there is not UF rate change that needs approval + presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; + } } else { if ( FALSE == isTxTimeValid ) { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } - else if ( FALSE == isUFVolValid ) + else if ( FALSE == isUFRateValid ) { - rejectReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; + rejectReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; } else { @@ -1101,8 +1155,7 @@ { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } - else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || - ( currentTreatmentState >= TREATMENT_END_STATE ) ) + else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || ( currentTreatmentState >= TREATMENT_END_STATE ) ) { rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } @@ -1115,8 +1168,13 @@ rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; } } - // Send response to request - sendChangeTreatmentDurationResponse( result, rejectReason, presTreatmentTimeSecs / SEC_PER_MIN, presMaxUFVolumeML ); + + if ( TRUE == isResp2UINeeded ) + { + // Send response to request only if there is a rejection + sendChangeTreatmentDurationResponse( result, rejectReason, presTreatmentTimeSecs / SEC_PER_MIN, presMaxUFVolumeML ); + } + // Send new ranges for settings treatmentParamsRangesBroadcastTimerCtr = getU32OverrideValue( &treatmentParamRangesPublishInterval ); broadcastTreatmentSettingsRanges(); @@ -1519,6 +1577,59 @@ /*********************************************************************//** * @brief + * The handleUFRateConfirmationMessageFromUI function handles the UF rate + * message received from UI. It checks whether the accept or reject needs + * to be handled. + * @details Inputs: txDurationRequest + * @details Outputs: presTreatmentTimeSecs, presUFRate, txDurationRequest, + * presMaxUFVolumeML + * @return none + *************************************************************************/ +void handleUFRateConfirmationMessageFromUI( void ) +{ + BOOL result = FALSE; + CONFIRMATION_REQUEST_STATUS_T status = getConfirmationRequestStatus( GENERIC_CONFIRM_ID_UF_RATE_CHANGE_IN_TX_DURATION_CHANGE, + txDurationRequest.newUFRateMLPM, 0.0F, 0.0F, 0.0F ); + + if ( TRUE == txDurationRequest.isUFRateConfInProgress ) + { + if ( ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == status ) || ( CONFIRMATION_REQUEST_STATUS_REJECTED == status ) ) + { + if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == status ) + { + result = TRUE; + sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), txDurationRequest.requestedTxDurationMins ); + presTreatmentTimeSecs = txDurationRequest.requestedTxDurationMins * SEC_PER_MIN; + presUFRate = txDurationRequest.newUFRateMLPM; + setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); + setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, ( presTreatmentTimeSecs / SEC_PER_MIN ) ); + setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + } + + // Regardless of accept or reject there is no reject reason. + sendChangeTreatmentDurationResponse( result, 0, ( presTreatmentTimeSecs / SEC_PER_MIN ), presMaxUFVolumeML ); + // Send new ranges for settings + treatmentParamsRangesBroadcastTimerCtr = getU32OverrideValue( &treatmentParamRangesPublishInterval ); + broadcastTreatmentSettingsRanges(); + // Send time/state data immediately for UI update + broadcastTreatmentTimeAndState(); + + // Done with treatment duration changes whether they were accepted or rejected. + txDurationRequest.newUFRateMLPM = 0.0F; + txDurationRequest.requestedTxDurationMins = 0; + txDurationRequest.isUFRateConfInProgress = FALSE; + } + } + + if ( TRUE == didTimeout( txDurationRequest.rqstStartTimeStamp, UF_RATE_CONFIRM_MSG_TIMEOUT_MS ) ) + { + setConfirmationRequestStatus( GENERIC_CONFIRM_ID_UF_RATE_CHANGE_IN_TX_DURATION_CHANGE, CONFIRMATION_REQUEST_STATUS_TIMEOUT ); + } +} + +/*********************************************************************//** + * @brief * The broadcastTreatmentSettingsRanges function computes and broadcasts * updated treatment parameter ranges that the user may change during treatment. * It is assumed that prescription settings have already been set prior to calling Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -137,6 +137,8 @@ BOOL verifyBloodAndDialysateRateSettingsChange( U32 bloodRate, U32 dialRate ); BOOL verifyPressureLimitsChange( PRESSURE_LIMIT_CHANGE_REQUEST_T *data ); +void handleUFRateConfirmationMessageFromUI( void ); + BOOL testSetTreatmentTimeRemainingOverride( U32 value ); BOOL testSetTreatmentTimePublishIntervalOverride( U32 ms ); BOOL testResetTreatmentTimePublishIntervalOverride( void ); Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -142,6 +142,10 @@ U32 priorSubState = currentSubState; U32 prior4thLevelState = current4thLevelState; + // Check for the UF rate confirmation message from UI and if it has been received, process it. + // This function is called here to make sure the UF rate screen is always serviced so it does not get hung up + handleUFRateConfirmationMessageFromUI(); + // Any new mode requests? newMode = arbitrateModeRequest(); // Will return current mode if no pending requests @@ -445,13 +449,20 @@ * @param requestID ID of confirmation being requested * @return Status of given confirmation *************************************************************************/ -CONFIRMATION_REQUEST_STATUS_T getConfirmationRequestStatus( GENERIC_CONFIRM_ID_T requestID ) +CONFIRMATION_REQUEST_STATUS_T getConfirmationRequestStatus( GENERIC_CONFIRM_ID_T requestID, F32 payload1, F32 payload2, F32 payload3, F32 payload4 ) { BOOL pending = FALSE; U32 pendingIndex = 0; CONFIRMATION_REQUEST_STATUS_T status = CONFIRMATION_REQUEST_STATUS_PENDING; U32 i; + GENERIC_CONFIRMATION_REQUEST_T genConfRqst; + genConfRqst.rejectReason = 0; + genConfRqst.genericPayload1 = payload1; + genConfRqst.genericPayload2 = payload2; + genConfRqst.genericPayload3 = payload3; + genConfRqst.genericPayload4 = payload3; + for ( i = 0; i < MAX_PENDING_CONFIRM_REQUESTS; i++ ) { if ( confirmRequests[ i ].requestID == requestID ) @@ -462,18 +473,24 @@ // Send UI clear if ( CONFIRMATION_REQUEST_STATUS_TIMEOUT == status ) { - sendConfirmationRequest( confirmRequests[ i ].requestID, GENERIC_CONFIRM_CMD_TIMEOUT_CLOSE, 0 ); + genConfRqst.requestID = (U32)confirmRequests[ i ].requestID; + genConfRqst.requestType = (U32)GENERIC_CONFIRM_CMD_TIMEOUT_CLOSE; + + sendConfirmationRequest( &genConfRqst ); } else { - sendConfirmationRequest( confirmRequests[ i ].requestID, GENERIC_CONFIRM_CMD_ACCEPT_CLOSE, 0 ); + genConfRqst.requestID = (U32)confirmRequests[ i ].requestID; + genConfRqst.requestType = (U32)GENERIC_CONFIRM_CMD_ACCEPT_CLOSE; + + sendConfirmationRequest( &genConfRqst ); } // Clear the confirmation request, it is done and consumed - confirmRequests[ i ].requestID = GENERIC_CONFIRM_ID_NONE; + confirmRequests[ i ].requestID = GENERIC_CONFIRM_ID_NONE; confirmRequests[ i ].requestType = GENERIC_CONFIRM_CMD_REQUEST_OPEN; - confirmRequests[ i ].timeStamp = 0; - confirmRequests[ i ].status = CONFIRMATION_REQUEST_STATUS_UNUSED; + confirmRequests[ i ].timeStamp = 0; + confirmRequests[ i ].status = CONFIRMATION_REQUEST_STATUS_UNUSED; } } else if ( CONFIRMATION_REQUEST_STATUS_PENDING == confirmRequests[ i ].status ) @@ -496,8 +513,11 @@ if ( ( CONFIRMATION_REQUEST_STATUS_PENDING != status ) && ( TRUE == pending ) ) { + genConfRqst.requestID = (U32)confirmRequests[ i ].requestID; + genConfRqst.requestType = (U32)confirmRequests[ pendingIndex ].requestType; + // Last confirmation cleared, pending request must be resent to UI - sendConfirmationRequest( confirmRequests[ pendingIndex ].requestID, confirmRequests[ pendingIndex ].requestType, 0 ); + sendConfirmationRequest( &genConfRqst ); } return status; @@ -531,12 +551,10 @@ * The addConfirmationRequest function sends a confirmation request to UI * @details Inputs: confirmRequests[] * @details Outputs: confirmRequests[] new added. - * @param requestID ID of confirmation being requested - * @param requestType Type of confirmation being requested (open, close, reject) - * @param rejectReason Reason for reject if type is reject + * @param request pointer to generic confirmation message request structure * @return request ID - will be non-zero if added *************************************************************************/ -GENERIC_CONFIRM_ID_T addConfirmationRequest( GENERIC_CONFIRM_ID_T requestID, GENERIC_CONFIRM_COMMAND_T requestType, U32 rejectReason ) +GENERIC_CONFIRM_ID_T addConfirmationRequest( GENERIC_CONFIRMATION_REQUEST_T *request ) { U32 i; BOOL confirmAlreadyPending = FALSE; @@ -545,7 +563,7 @@ // Check to make sure specified confirmation is not already pending for ( i = 0; i < MAX_PENDING_CONFIRM_REQUESTS; i++ ) { - if ( ( confirmRequests[ i ].requestID == requestID ) && + if ( ( confirmRequests[ i ].requestID == request->requestID ) && ( confirmRequests[ i ].status != CONFIRMATION_REQUEST_STATUS_UNUSED ) ) { confirmAlreadyPending = TRUE; @@ -556,17 +574,30 @@ // If not already pending, add confirmation to list of pending confirmations and send to UI to be displayed if ( confirmAlreadyPending != TRUE ) { + GENERIC_CONFIRMATION_REQUEST_T genConfRqst; + + genConfRqst.rejectReason = request->rejectReason; + genConfRqst.genericPayload1 = request->genericPayload1; + genConfRqst.genericPayload2 = request->genericPayload2; + genConfRqst.genericPayload3 = request->genericPayload3; + genConfRqst.genericPayload4 = request->genericPayload4; + for ( i = 0; i < MAX_PENDING_CONFIRM_REQUESTS; i++ ) { if ( CONFIRMATION_REQUEST_STATUS_UNUSED == confirmRequests[ i ].status ) { // Save the confirmation request info - confirmRequests[ i ].requestID = requestID; - confirmRequests[ i ].requestType = requestType; - confirmRequests[ i ].timeStamp = getMSTimerCount(); - confirmRequests[ i ].status = CONFIRMATION_REQUEST_STATUS_PENDING; - newID = requestID; - sendConfirmationRequest( requestID, requestType, rejectReason ); + confirmRequests[ i ].requestID = (GENERIC_CONFIRM_ID_T)request->requestID; + confirmRequests[ i ].requestType = (GENERIC_CONFIRM_COMMAND_T)request->requestType; + confirmRequests[ i ].timeStamp = getMSTimerCount(); + confirmRequests[ i ].status = CONFIRMATION_REQUEST_STATUS_PENDING; + newID = (GENERIC_CONFIRM_ID_T)request->requestID; + + // Get ready for the generic confirmation request + genConfRqst.requestID = request->requestID; + genConfRqst.requestType = request->requestType; + + sendConfirmationRequest( &genConfRqst ); break; } } Index: firmware/App/Modes/OperationModes.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/OperationModes.h (.../OperationModes.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/OperationModes.h (.../OperationModes.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -40,6 +40,18 @@ U32 subMode; ///< Current sub-mode of current operating mode } OP_MODE_PAYLOAD_T; +/// Payload structure for generic confirmation request +typedef struct +{ + U32 requestID; ///< Generic request ID. + U32 requestType; ///< Generic request type. + U32 rejectReason; ///< Reject reason. + F32 genericPayload1; ///< Generic payload 1. + F32 genericPayload2; ///< Generic payload 2. + F32 genericPayload3; ///< Generic payload 3. + F32 genericPayload4; ///< Generic payload 4. +} GENERIC_CONFIRMATION_REQUEST_T; + // ********** public function prototypes ********** void initOperationModes( void ); // Initialize this module @@ -49,9 +61,12 @@ HD_OP_MODE_T getPreviousOperationMode( void ); // Get the previous operation mode U32 getCurrentSubMode( void ); // Get the current sub-mode void initiateAlarmAction( ALARM_ACTION_T action ); // Initiate an alarm or alarm recovery action according to current op mode -CONFIRMATION_REQUEST_STATUS_T getConfirmationRequestStatus( GENERIC_CONFIRM_ID_T requestID ); // Get the current confirmation request status +CONFIRMATION_REQUEST_STATUS_T getConfirmationRequestStatus( GENERIC_CONFIRM_ID_T requestID, F32 payload1, + F32 payload2, F32 payload3, F32 payload4 ); // Get the current confirmation request status void setConfirmationRequestStatus( GENERIC_CONFIRM_ID_T requestID, CONFIRMATION_REQUEST_STATUS_T status ); // Set the confirmation request status -GENERIC_CONFIRM_ID_T addConfirmationRequest( GENERIC_CONFIRM_ID_T requestID, GENERIC_CONFIRM_COMMAND_T requestType, U32 rejectReason ); // Add a new confirmation request + +GENERIC_CONFIRM_ID_T addConfirmationRequest( GENERIC_CONFIRMATION_REQUEST_T *request ); // Add a new confirmation request + void setCurrentSubState( U32 subState ); // Set the current substate. void setCurrent4thLevelState( U32 state ); // Set the current 4th level state. void sendOperationStatusEvent( void ); // Constructs and sends operation status event Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -65,6 +65,7 @@ #define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. #define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. #define PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG 50.0F ///< +/- offset from start pressure that defines a range to keep PBo in during dialysate dialyzer prime state. +#define MIN_VENOUS_PRESSURE_DIALSYATE_LINE_OCCLUSION_MMHG -15.0F ///< Minimum measured venous pressure indicates possible clamping/occlusion during dialysate priming. #define DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN 1 ///< DPo rate step to maintain pressure during dialysate dialyzer prime state. #define VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum venous pressure reading (in mmHg) for bubble clear. @@ -143,6 +144,10 @@ static F32 minimumReservoirVolume; ///< Minimum reservoir volume in mL. static U32 steadyVolumeCount; ///< Use to keep track the number of dVolume/dt < Threshold static BOOL bubbleClearEnded; ///< Bubble clear ended boolean signal. +#if 0 +// Disabled for release 21. Will be reinstated in release 22. +static BOOL primeDialysateOcclusionDetected; ///< flag used when dialysate occlusion alarm set +#endif // ********** private function prototypes ********** @@ -181,6 +186,10 @@ primePauseStartTime = 0; primeStatusBroadcastTimerCounter = 0; bubbleClearEnded = FALSE; +#if 0 +// Disabled for release 21. Will be reinstated in release 22. + primeDialysateOcclusionDetected = FALSE; +#endif } /*********************************************************************//** @@ -818,6 +827,11 @@ if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { F32 venPres = getFilteredVenousPressure(); +#if 0 + // Disabled for release 21. Will be reinstated in release 22. + F32 measuredDialInFlow = getDGRawDialysateFlowRateLMin() * ML_PER_LITER; + BOOL lowFlow = ( measuredDialInFlow < MIN_DG_DIAL_FLOW_RATE ? TRUE : FALSE ); +#endif if ( venPres > ( primeDialysateDialyzerStartVenPres + PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) { @@ -829,6 +843,23 @@ primeDialysateDialyzerDPoRate -= DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } +#if 0 + // Disabled for release 21. Will be reinstated in release 22. + // if dialysate line is clamped for some reasons, raise an alarm based on the measured venous pressure and raw flow rate. + if ( ( venPres <= MIN_VENOUS_PRESSURE_DIALSYATE_LINE_OCCLUSION_MMHG ) && ( TRUE == lowFlow ) ) + { + // This is alarm 273. ALARM_ID_HD_PRIME_DIALYSATE_LINE_OCCLUSION + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_PRIME_DIALYSATE_LINE_OCCLUSION, venPres, measuredDialInFlow ); + primeDialysateOcclusionDetected = TRUE; + } + else if ( TRUE == primeDialysateOcclusionDetected ) + { + // after clearance of occlusion, start the blood side priming due to any air bubbles collected prior. + state = HD_PRIME_SALINE_SETUP_STATE; + primeDialysateOcclusionDetected = FALSE; + } +#endif + steadyVolumeSamplingStartTime = getMSTimerCount(); } Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -39,12 +39,11 @@ // ********** private definitions ********** #define DEFAULT_RINSEBACK_VOLUME_ML 300.0F ///< Default rinseback volume (in mL). -#define MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML 300.0F ///< Maximum total additional rinseback volume allowed : all additionals (in mL). #define TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML 50.0F ///< Target rinseback volume for an additional volume request (in mL). #define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. #define DEFAULT_RINSEBACK_FLOW_RATE_ML_MIN 250 ///< Default rinseback flow rate (in mL/min). #define MIN_RINSEBACK_FLOW_RATE_ML_MIN 100 ///< Minimum rinseback flow rate (in mL/min). -#define MAX_RINSEBACK_FLOW_RATE_ML_MIN 300 ///< Maximum rinseback flow rate (in mL/min). +#define MAX_RINSEBACK_FLOW_RATE_ML_MIN 500 ///< Maximum rinseback flow rate (in mL/min). #define DEFAULT_FILL_RESERVOIR_TO_VOLUME_ML 1500 ///< default Fill reservoir to this volume (in mL). /// Interval at which rinseback progress is to be published to UI. @@ -602,9 +601,8 @@ targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; } - // Has additional rinseback completed or max additional volume reached - else if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || - ( totalAdditionalRinsebackVolume_mL >= MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML ) ) + // Has additional rinseback completed + else if ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) { result = RINSEBACK_STOP_STATE; } @@ -687,6 +685,7 @@ *************************************************************************/ void signalRinsebackUserAction( REQUESTED_RINSEBACK_USER_ACTIONS_T action ) { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; @@ -728,8 +727,16 @@ break; case REQUESTED_USER_ACTION_RINSEBACK_END_TREATMENT: + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_TREATMENT_END; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI - addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + addConfirmationRequest( &genericConfRequest ); accepted = TRUE; break; @@ -950,15 +957,7 @@ if ( RINSEBACK_STOP_STATE == rinsebackState ) { - if ( totalAdditionalRinsebackVolume_mL < MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML ) - { - result = TRUE; - additionalRinsebackRequested = TRUE; - } - else - { - *rejReason = REQUEST_REJECT_REASON_ADDL_RINSEBACK_MAX_VOLUME_REACHED; - } + additionalRinsebackRequested = TRUE; } else { Index: firmware/App/Modes/TreatmentRecirc.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -351,6 +351,7 @@ *************************************************************************/ void signalTreatmentRecircUserAction( REQUESTED_TREATMENT_RECIRC_USER_ACTIONS_T action ) { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; @@ -372,8 +373,16 @@ break; case REQUESTED_USER_ACTION_TX_RECIRC_END_TREATMENT: + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_TREATMENT_END; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI - addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + addConfirmationRequest( &genericConfRequest ); accepted = TRUE; break; Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -23,6 +23,7 @@ #include "DialOutFlow.h" #include "ModeTreatment.h" #include "OperationModes.h" +#include "SalineBolus.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TreatmentStop.h" @@ -58,6 +59,7 @@ static TREATMENT_STOP_STATE_T handleTreatmentStopDialysateRecircState( void ); static TREATMENT_STOP_STATE_T handleTreatmentStopBloodRecircState( void ); static TREATMENT_STOP_STATE_T handleTreatmentStopRecoverBloodDetectState( void ); +static TREATMENT_STOP_STATE_T handleTreatmentStopDeliverSalineBolusState( void ); static void handleTreatmentStopBloodSittingTimer( void ); static void publishTreatmentStopData( void ); @@ -279,6 +281,10 @@ currentTxStopState = handleTreatmentStopRecoverBloodDetectState(); break; + case TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE: + currentTxStopState = handleTreatmentStopDeliverSalineBolusState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_TREATMENT_STOP_INVALID_STATE, currentTxStopState ); break; @@ -291,6 +297,8 @@ } // Broadcast treatment stop status publishTreatmentStopData(); + // Just pass the blood leak related as 0 since only saline bolus data needs to be published + publishSalineBolusData( 0.0, 0.0, 0 ); } /*********************************************************************//** @@ -317,6 +325,17 @@ result = TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE; } } + else if ( ( TRUE == isSalineBolusStartRequested() ) || ( getSalineBolusState() != SALINE_BOLUS_STATE_IDLE ) ) + { + // No need for setup function since the saline bolus exec function starts from Idle and sets the actuators + result = TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE; + + if ( SALINE_BOLUS_STATE_IDLE == (U32)getSalineBolusState() ) + { + // Send the first 4th level state here only when we are in idle + setCurrent4thLevelState( (U32)getSalineBolusState() ); + } + } else { // Both unblocked and not in recirculate both state @@ -383,7 +402,7 @@ handleTreatmentStopBloodSittingTimer(); - result = handleTreatmentStopAlarmsAndSignals(result); + result = handleTreatmentStopAlarmsAndSignals( result ); return result; } @@ -400,7 +419,7 @@ { TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; - result = handleTreatmentStopAlarmsAndSignals(result); + result = handleTreatmentStopAlarmsAndSignals( result ); return result; } @@ -449,6 +468,25 @@ /*********************************************************************//** * @brief + * The handleTreatmentStopDeliverSalineBolusState function handles the + * delivery of saline bolus state in treatment stop. + * @details Inputs: none + * @details Outputs: none + * @return next treatment stop state + *************************************************************************/ +static TREATMENT_STOP_STATE_T handleTreatmentStopDeliverSalineBolusState( void ) +{ + TREATMENT_STOP_STATE_T result = TREATMENT_STOP_DELIVER_SALINE_BOLUS_STATE; + + execSalineBolus(); + + result = handleTreatmentStopAlarmsAndSignals( result ); + + return result; +} + +/*********************************************************************//** + * @brief * The handleTreatmentStopBloodSittingTimer function handles the no re-circ * blood timer. It should only be called when Blood is NOT circulating. * Increments and checks for warning and alarm timeouts. Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -14,58 +14,58 @@ * @date (original) 07-Nov-2019 * ***************************************************************************/ - -#include "mibspi.h" - + +#include "mibspi.h" + #define __ALARM_MGMT_C__ #include "AlarmLamp.h" #include "CPLD.h" #include "FPGA.h" -#include "InternalADC.h" +#include "InternalADC.h" #include "OperationModes.h" #include "SafetyShutdown.h" -#include "SystemCommMessages.h" -#include "TaskGeneral.h" -#include "Timers.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "Timers.h" -/** - * @addtogroup AlarmManagement - * @{ - */ - -// ********** private definitions ********** +/** + * @addtogroup AlarmManagement + * @{ + */ -/// Interval to control lamp and audio and to publish alarm status data. -#define ALARM_STATUS_PUBLISH_INTERVAL ( ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) +// ********** private definitions ********** + +/// Interval to control lamp and audio and to publish alarm status data. +#define ALARM_STATUS_PUBLISH_INTERVAL ( ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which the alarm information is published on the CAN bus. #define ALARM_INFO_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) Alarms are blocked after the return of AC power. #define ALARM_BLOCKED_COUNT_AFTER_AC_RETURN ( 10*MS_PER_SECOND / TASK_GENERAL_INTERVAL ) - -#define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. - + +#define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. + #define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. #define LOWEST_ALARM_SUB_RANK 999 ///< Lowest alarm sub-rank that can be set. #define ALARM_NOT_BLOCKED 0 ///< Alarm blocked timer value that indicates no alarm block -#define MIN_TIME_BETWEEN_ALARM_ACTIONS_MS MS_PER_SECOND ///< Minimum time between user alarm actions (in ms). - +#define MIN_TIME_BETWEEN_ALARM_ACTIONS_MS MS_PER_SECOND ///< Minimum time between user alarm actions (in ms). + // *** This declaration will cause a compiler error if ALARM_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmTableSizeAssertion[ ( ( sizeof( ALARM_TABLE ) / sizeof( ALARM_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; // *** This declaration will cause a compiler error if ALARM_RANK_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmRankTableSizeAssertion[ ( ( sizeof( ALARM_RANK_TABLE ) / sizeof( ALARM_RANK_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; -/// A blank alarm data record for alarms that do not include alarm data when triggered. -const ALARM_DATA_T BLANK_ALARM_DATA = { ALARM_DATA_TYPE_NONE, 0 }; - -/// Pin SPI3-CS0 - re-purposed as output GPIO for backup alarm audio enable. -#define BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK 0x00000001 -// Backup alarm audio enable/disable macros -#define SET_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 |= BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to enable backup alarm audio. +/// A blank alarm data record for alarms that do not include alarm data when triggered. +const ALARM_DATA_T BLANK_ALARM_DATA = { ALARM_DATA_TYPE_NONE, 0 }; + +/// Pin SPI3-CS0 - re-purposed as output GPIO for backup alarm audio enable. +#define BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK 0x00000001 +// Backup alarm audio enable/disable macros +#define SET_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 |= BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to enable backup alarm audio. #define CLR_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 &= ~BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to disable backup alarm audio. #define ALARM_AUDIO_TEST_TONE 4 ///< Alarm audio state for continuous test tone. @@ -82,7 +82,7 @@ U32 subRank; ///< Sub-rank of this alarm S32 timeSinceTriggeredMS; ///< Time (in ms) since this alarm was triggered } ALARM_PRIORITY_RANKS_T; - + /// Enumeration of alarm audio self-test states. typedef enum Alarm_Audio_Self_Test_States { @@ -110,17 +110,17 @@ { 4, 2 } }; -// ********** private data ********** - -static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm +// ********** private data ********** + +static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm static BOOL alarmIsDetected[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm condition (detected or cleared) -static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< Table - when alarm became active for each alarm (if active) or zero (if inactive) +static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< Table - when alarm became active for each alarm (if active) or zero (if inactive) static U32 alarmStatusPublicationTimerCounter = 0; ///< Used to schedule alarm status publication to CAN bus. -static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. +static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. static U32 audioTestStartTime; ///< Start time of audio alarm current self-test. static U32 alarmsBlockedTimer = 0; ///< Countdown timer used to temporarily block new alarms from being initiated static U32 lastUserAlarmActionReceivedTime = 0; ///< Time of last alarm action by user received from the UI (ms timestamp). - + /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T alarmStatusPublishInterval = { ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, 0 }; @@ -136,7 +136,7 @@ static OVERRIDE_F32_T alarmBackupAudioCurrent = { 0.0, 0.0, 0.0, 0 }; ///< Alarm backup audio current measured at ADC. -static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. +static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. static ALARM_PRIORITY_RANKS_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; ///< FIFO - first activated or highest sub-rank alarm in each alarm priority category. static BOOL alarmUserRecoveryActionEnabled[ NUMBER_OF_ALARM_USER_ACTIONS ]; ///< Alarm user recovery actions enabled flags. @@ -149,105 +149,105 @@ static BOOL resumeBlockedByAlarmProperty; ///< Flag indicates whether treatment resumption is currently blocked by alarm property. static BOOL alarmNoRetrigger; ///< Flag indicates whether some alarms should be prevented from re-triggering after being cleared by rinseback or end-tx options -// ********** private function prototypes ********** - -static void activateAlarm( ALARM_ID_T alarm ); +// ********** private function prototypes ********** -static void monitorAlarms( void ); -static void updateAlarmsState( void ); -static void setAlarmLamp( void ); +static void activateAlarm( ALARM_ID_T alarm ); + +static void monitorAlarms( void ); +static void updateAlarmsState( void ); +static void setAlarmLamp( void ); static void setAlarmAudio( void ); -static void updateAlarmsSilenceStatus( void ); -static void updateAlarmsFlags( void ); +static void updateAlarmsSilenceStatus( void ); +static void updateAlarmsFlags( void ); -static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); -static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); - +static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); +static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); + static U32 getAlarmStartTime( ALARM_ID_T alarmID ); static void publishAlarmInfo( void ); - -/*********************************************************************//** - * @brief - * The initAlarmMgmt function initializes the AlarmMgmt module. - * @details Inputs: none - * @details Outputs: AlarmMgmt module initialized. - * @return none - *************************************************************************/ -void initAlarmMgmt( void ) -{ - ALARM_PRIORITY_T p; + +/*********************************************************************//** + * @brief + * The initAlarmMgmt function initializes the AlarmMgmt module. + * @details Inputs: none + * @details Outputs: AlarmMgmt module initialized. + * @return none + *************************************************************************/ +void initAlarmMgmt( void ) +{ + ALARM_PRIORITY_T p; ALARM_ID_T a; ALARM_BUTTON_BLOCKER_T b; - - // Disable backup audio - CLR_BACKUP_AUDIO_ENABLE(); - - // Initialize alarm states and start time stamps - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) - { + + // Disable backup audio + CLR_BACKUP_AUDIO_ENABLE(); + + // Initialize alarm states and start time stamps + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { alarmIsActive[ a ] = FALSE; - alarmIsDetected[ a ] = FALSE;; - alarmStartedAt[ a ].data = 0; - alarmStartedAt[ a ].ovData = 0; - alarmStartedAt[ a ].ovInitData = 0; - alarmStartedAt[ a ].override = OVERRIDE_RESET; - } - // Initialize alarm FIFOs - for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) - { + alarmIsDetected[ a ] = FALSE;; + alarmStartedAt[ a ].data = 0; + alarmStartedAt[ a ].ovData = 0; + alarmStartedAt[ a ].ovInitData = 0; + alarmStartedAt[ a ].override = OVERRIDE_RESET; + } + // Initialize alarm FIFOs + for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) + { alarmPriorityFIFO[ p ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ p ].subRank = LOWEST_ALARM_SUB_RANK; - alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; + alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; } // Initialize alarm button blocker flags for ( b = (ALARM_BUTTON_BLOCKER_T)0; b < NUM_OF_ALARM_BUTTON_BLOCKERS; b++ ) { alarmButtonBlockers[ b ] = FALSE; - } - // Initialize composite alarm state - alarmStatus.alarmsState = ALARM_PRIORITY_NONE; - alarmStatus.alarmsSilenced = FALSE; - alarmStatus.alarmsSilenceStart = 0; + } + // Initialize composite alarm state + alarmStatus.alarmsState = ALARM_PRIORITY_NONE; + alarmStatus.alarmsSilenced = FALSE; + alarmStatus.alarmsSilenceStart = 0; alarmStatus.alarmsSilenceExpiresIn = 0; alarmStatus.alarmsEscalatesIn = 0; - alarmStatus.alarmsToEscalate = FALSE; + alarmStatus.alarmsToEscalate = FALSE; alarmStatus.alarmTop = ALARM_ID_NO_ALARM; - alarmStatus.topAlarmConditionDetected = FALSE; - alarmStatus.systemFault = FALSE; + alarmStatus.topAlarmConditionDetected = FALSE; + alarmStatus.systemFault = FALSE; alarmStatus.stop = FALSE; - alarmStatus.lampOn = FALSE; - alarmStatus.noClear = FALSE; - alarmStatus.noResume = FALSE; - alarmStatus.noRinseback = FALSE; + alarmStatus.lampOn = FALSE; + alarmStatus.noClear = FALSE; + alarmStatus.noResume = FALSE; + alarmStatus.noRinseback = FALSE; alarmStatus.noEndTreatment = FALSE; alarmStatus.noBloodRecirc = FALSE; - alarmStatus.noDialRecirc = FALSE; + alarmStatus.noDialRecirc = FALSE; alarmStatus.ok = FALSE; alarmsBlockedTimer = 0; lastUserAlarmActionReceivedTime = 0; alarmAudioTestToneRequested = FALSE; resumeBlockedByAlarmProperty = FALSE; alarmNoRetrigger = FALSE; - alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; -} - -/*********************************************************************//** - * @brief - * The execAlarmMgmt function executes the alarm management functions to be - * done periodically. The composite alarm state is updated, alarm lamp and - * audio patterns are updated, and status is sent out to the rest of the system. - * @details Inputs: none - * @details Outputs: none - * @return none - *************************************************************************/ -void execAlarmMgmt( void ) + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; +} + +/*********************************************************************//** + * @brief + * The execAlarmMgmt function executes the alarm management functions to be + * done periodically. The composite alarm state is updated, alarm lamp and + * audio patterns are updated, and status is sent out to the rest of the system. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +void execAlarmMgmt( void ) { monitorAlarms(); - updateAlarmsState(); - updateAlarmsFlags(); - updateAlarmsSilenceStatus(); + updateAlarmsState(); + updateAlarmsFlags(); + updateAlarmsSilenceStatus(); // Publish alarm status and information at interval publishAlarmInfo(); @@ -256,7 +256,7 @@ { alarmsBlockedTimer--; } -} +} /*********************************************************************//** * @brief @@ -271,9 +271,9 @@ // Verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { - // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm + // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm if ( ( FALSE == alarmIsActive[ alarm ] ) || - ( ( FALSE == alarmIsDetected[ alarm ] ) && ( FALSE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) ) ) + ( ( FALSE == alarmIsDetected[ alarm ] ) && ( FALSE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) ) ) { // If alarms are silenced and this new alarm is of higher or same priority, end silence due to new alarm if ( ( ALARM_TABLE[ alarm ].alarmPriority > ALARM_TABLE[ alarmStatus.alarmTop ].alarmPriority ) || @@ -286,18 +286,18 @@ if ( ALARM_ID_NO_ALARM == alarmStatus.alarmTop ) { alarmStatus.alarmTop = alarm; - } + } // If alarm stops, set that status immediately (don't wait for status update function) if ( TRUE == ALARM_TABLE[ alarm ].alarmStops ) { alarmStatus.stop = TRUE; } - // If alarm is a fault (and not in service mode), request transition to fault mode - if ( ( TRUE == ALARM_TABLE[ alarm ].alarmIsFault ) && ( getCurrentOperationMode() != MODE_SERV ) ) - { - requestNewOperationMode( MODE_FAUL ); - } - // Activate alarm + // If alarm is a fault (and not in service mode), request transition to fault mode + if ( ( TRUE == ALARM_TABLE[ alarm ].alarmIsFault ) && ( getCurrentOperationMode() != MODE_SERV ) ) + { + requestNewOperationMode( MODE_FAUL ); + } + // Activate alarm alarmIsActive[ alarm ] = TRUE; alarmStartedAt[ alarm ].data = getMSTimerCount(); alarmIsDetected[ alarm ] = TRUE; @@ -311,61 +311,61 @@ if ( TRUE == ALARM_TABLE[ alarm ].alarmStops ) { initiateAlarmAction( ALARM_ACTION_STOP ); - } - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) + } + } } -} - -/*********************************************************************//** - * @brief - * The activateAlarmNoData function activates a given alarm. Also, an alarm - * message is broadcast to the rest of the system. This function will - * include given data in the broadcast message for logging. - * @details Inputs: none - * @details Outputs: alarm triggered message sent, alarm activated - * @param alarm ID of alarm to activate - * @return none - *************************************************************************/ -void activateAlarmNoData( ALARM_ID_T alarm ) + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) + } +} + +/*********************************************************************//** + * @brief + * The activateAlarmNoData function activates a given alarm. Also, an alarm + * message is broadcast to the rest of the system. This function will + * include given data in the broadcast message for logging. + * @details Inputs: none + * @details Outputs: alarm triggered message sent, alarm activated + * @param alarm ID of alarm to activate + * @return none + *************************************************************************/ +void activateAlarmNoData( ALARM_ID_T alarm ) { - activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); -} - -/*********************************************************************//** - * @brief - * The activateAlarm1Data function activates a given alarm. Also, an alarm - * message is broadcast to the rest of the system. This function will - * include given data in the broadcast message for logging. - * @details Inputs: none - * @details Outputs: alarm triggered message sent, alarm activated - * @param alarm ID of alarm to activate - * @param alarmData supporting data to include in alarm msg - * @return none - *************************************************************************/ -void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) -{ + activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); +} + +/*********************************************************************//** + * @brief + * The activateAlarm1Data function activates a given alarm. Also, an alarm + * message is broadcast to the rest of the system. This function will + * include given data in the broadcast message for logging. + * @details Inputs: none + * @details Outputs: alarm triggered message sent, alarm activated + * @param alarm ID of alarm to activate + * @param alarmData supporting data to include in alarm msg + * @return none + *************************************************************************/ +void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) +{ activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA, FALSE ); -} - -/*********************************************************************//** - * @brief - * The activateAlarm2Data function activates a given alarm. Also, an alarm - * message is broadcast to the rest of the system. This function will - * include two given data in the broadcast message for logging. - * @details Inputs: alarmsBlockedTimer, determines blocked alarm conditions - * @details Outputs: alarm triggered message sent, alarm activated - * @param alarm ID of alarm to activate - * @param alarmData1 supporting data to include in alarm msg +} + +/*********************************************************************//** + * @brief + * The activateAlarm2Data function activates a given alarm. Also, an alarm + * message is broadcast to the rest of the system. This function will + * include two given data in the broadcast message for logging. + * @details Inputs: alarmsBlockedTimer, determines blocked alarm conditions + * @details Outputs: alarm triggered message sent, alarm activated + * @param alarm ID of alarm to activate + * @param alarmData1 supporting data to include in alarm msg * @param alarmData2 supporting data to include in alarm msg - * @param outside flag indicates whether alarm is originating from outside HD f/w - * @return none - *************************************************************************/ -void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) -{ + * @param outside flag indicates whether alarm is originating from outside HD f/w + * @return none + *************************************************************************/ +void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) +{ // Block if new alarms are occur during loss of AC power if ( ( TRUE == getCPLDACPowerLossDetected() ) ) { @@ -424,7 +424,7 @@ else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) - } + } } /*********************************************************************//** @@ -454,42 +454,42 @@ } } -/*********************************************************************//** - * @brief - * The clearAlarm function clears a given alarm if it is recoverable. Also - * an alarm message is broadcast to the rest of the system. - * @details Inputs: none +/*********************************************************************//** + * @brief + * The clearAlarm function clears a given alarm if it is recoverable. Also + * an alarm message is broadcast to the rest of the system. + * @details Inputs: none * @details Outputs: AlarmStatusTable[], alarmIsActive[], alarmStartedAt[], - * alarmIsDetected[] - * @param alarm ID of alarm to clear - * @return none - *************************************************************************/ -void clearAlarm( ALARM_ID_T alarm ) -{ - // Verify given alarm - if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) - { - // Verify alarm can be cleared - if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) - { - // Clear alarm and broadcast alarm clear if not already cleared - if ( TRUE == alarmIsActive[ alarm ] ) + * alarmIsDetected[] + * @param alarm ID of alarm to clear + * @return none + *************************************************************************/ +void clearAlarm( ALARM_ID_T alarm ) +{ + // Verify given alarm + if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) + { + // Verify alarm can be cleared + if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) + { + // Clear alarm and broadcast alarm clear if not already cleared + if ( TRUE == alarmIsActive[ alarm ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32) alarm; - + broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); alarmIsActive[ alarm ] = FALSE; clearAlarmCondition( alarm ); - alarmStartedAt[ alarm ].data = 0; - } - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) - } + alarmStartedAt[ alarm ].data = 0; + } + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) + } } /*********************************************************************//** @@ -514,8 +514,8 @@ BOOL getNoRetriggerFlag( void ) { return alarmNoRetrigger; -} - +} + /*********************************************************************//** * @brief * The setAlarmUserActionEnabled function enables/disables specific alarm @@ -624,6 +624,7 @@ // Ignore alarm action if invalid or too soon after last one (essentially a debounce in case user double tapped a button) if ( ( TRUE == alarmActionIsValid ) && ( calcTimeSince( lastUserAlarmActionReceivedTime ) >= MIN_TIME_BETWEEN_ALARM_ACTIONS_MS ) ) { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; BOOL allRecAlarmsCleared = TRUE; // Clear recoverable alarms on user action @@ -665,8 +666,16 @@ break; case ALARM_USER_ACTION_END_TREATMENT: + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_TREATMENT_END; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI - addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + addConfirmationRequest( &genericConfRequest ); break; case ALARM_USER_ACTION_ACK: @@ -686,17 +695,17 @@ lastUserAlarmActionReceivedTime = getMSTimerCount(); } -/*********************************************************************//** - * @brief - * The isAlarmActive function determines whether a given alarm is currently - * active. - * @details Inputs: alarmIsActive[] - * @details Outputs: none - * @param alarm ID of alarm to check - * @return TRUE if given alarm is active, FALSE if not - *************************************************************************/ -BOOL isAlarmActive( ALARM_ID_T alarm ) -{ +/*********************************************************************//** + * @brief + * The isAlarmActive function determines whether a given alarm is currently + * active. + * @details Inputs: alarmIsActive[] + * @details Outputs: none + * @param alarm ID of alarm to check + * @return TRUE if given alarm is active, FALSE if not + *************************************************************************/ +BOOL isAlarmActive( ALARM_ID_T alarm ) +{ BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) @@ -706,9 +715,9 @@ else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, (U32)alarm ); - } - - return result; + } + + return result; } /*********************************************************************//** @@ -782,6 +791,19 @@ /*********************************************************************//** * @brief + * The isRinseBackBlocked function determines whether any currently + * active alarm is blocking rinseback. + * @details Inputs: alarmStatus + * @details Outputs: none + * @return TRUE if any active alarm prevents rinseback, FALSE if not + *************************************************************************/ +BOOL isRinseBackBlocked( void ) +{ + return alarmStatus.noRinseback; +} + +/*********************************************************************//** + * @brief * The doesAlarmStatusIndicateEndTxOnly function determines whether any currently * active alarm has ( stop && noRes && /noET ) property, that is end treatment is * the only choice from full stop. @@ -837,7 +859,7 @@ ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ) { return alarmStatus.alarmsState; -} +} /*********************************************************************//** * @brief @@ -956,15 +978,15 @@ } } } - -/*********************************************************************//** - * @brief - * The getAlarmStartTime function gets the active state of a given alarm. - * @details Inputs: alarmStartedAt[] - * @details Outputs: none - * @param alarmID ID of alarm to check - * @return The start time stamp of given alarm ID - *************************************************************************/ + +/*********************************************************************//** + * @brief + * The getAlarmStartTime function gets the active state of a given alarm. + * @details Inputs: alarmStartedAt[] + * @details Outputs: none + * @param alarmID ID of alarm to check + * @return The start time stamp of given alarm ID + *************************************************************************/ static U32 getAlarmStartTime( ALARM_ID_T alarmID ) { U32 result = 0; @@ -1004,7 +1026,7 @@ alarmBackupAudioCurrent.data = getFPGABackupAlarmAudioCurrent(); // Check for user confirmation of end treatment alarm response - if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == getConfirmationRequestStatus( GENERIC_CONFIRM_ID_TREATMENT_END ) ) + if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == getConfirmationRequestStatus( GENERIC_CONFIRM_ID_TREATMENT_END, 0.0F, 0.0F, 0.0F, 0.0F ) ) { // To avoid raising repeated alarm before reaching end treatment setVenousBubbleDetectionEnabled( FALSE ); @@ -1014,34 +1036,34 @@ // TODO - Check current vs. expected audio output } - -/*********************************************************************//** - * @brief - * The updateAlarmsState function updates the alarms state and alarm to - * display. - * @details Inputs: alarmStatusTable[] - * @details Outputs: alarmPriorityFIFO[], alarmStatus - * @return none - *************************************************************************/ -static void updateAlarmsState( void ) -{ - ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE, p; - ALARM_ID_T a; + +/*********************************************************************//** + * @brief + * The updateAlarmsState function updates the alarms state and alarm to + * display. + * @details Inputs: alarmStatusTable[] + * @details Outputs: alarmPriorityFIFO[], alarmStatus + * @return none + *************************************************************************/ +static void updateAlarmsState( void ) +{ + ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE, p; + ALARM_ID_T a; BOOL faultsActive = FALSE; - BOOL dialysateRecircBlocked = FALSE; + BOOL dialysateRecircBlocked = FALSE; BOOL bloodRecircBlocked = FALSE; // Reset priority FIFOs so we can re-determine them below for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) { resetAlarmPriorityFIFO( p ); } - - // Update FIFOs and sub-ranks per active alarms table - for alarm ranking purposes to determine "top" alarm - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) - { - if ( TRUE == alarmIsActive[ a ] ) - { + + // Update FIFOs and sub-ranks per active alarms table - for alarm ranking purposes to determine "top" alarm + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == alarmIsActive[ a ] ) + { ALARM_PRIORITY_T almPriority = ALARM_TABLE[ a ].alarmPriority; U32 subRank = ALARM_TABLE[ a ].alarmSubRank; U32 msSinceTriggered = calcTimeSince( getAlarmStartTime( a ) ); @@ -1067,81 +1089,81 @@ alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = (S32)msSinceTriggered; } } - // Track highest priority alarm found so far of all priority categories + // Track highest priority alarm found so far of all priority categories highestPriority = MAX( almPriority, highestPriority ); - // Track whether any active faults have been found so far - if ( TRUE == ALARM_TABLE[ a ].alarmIsFault ) - { - faultsActive = TRUE; + // Track whether any active faults have been found so far + if ( TRUE == ALARM_TABLE[ a ].alarmIsFault ) + { + faultsActive = TRUE; } // Track whether any active alarms prevent dialysate re-circulation so far if ( TRUE == ALARM_TABLE[ a ].alarmNoDialysateRecirc ) { dialysateRecircBlocked = TRUE; - } + } // Track whether any active alarms prevent blood re-circulation so far if ( TRUE == ALARM_TABLE[ a ].alarmNoBloodRecirc ) { bloodRecircBlocked = TRUE; } - } - } - - // Update alarm to display per highest priority FIFO - alarmStatus.alarmsState = highestPriority; + } + } + + // Update alarm to display per highest priority FIFO + alarmStatus.alarmsState = highestPriority; alarmStatus.alarmTop = alarmPriorityFIFO[ highestPriority ].alarmID; - alarmStatus.topAlarmConditionDetected = alarmIsDetected[ alarmStatus.alarmTop ]; + alarmStatus.topAlarmConditionDetected = alarmIsDetected[ alarmStatus.alarmTop ]; alarmStatus.systemFault = faultsActive; alarmStatus.noBloodRecirc = bloodRecircBlocked; - alarmStatus.noDialRecirc = dialysateRecircBlocked; -} - -/*********************************************************************//** - * @brief + alarmStatus.noDialRecirc = dialysateRecircBlocked; +} + +/*********************************************************************//** + * @brief * The setAlarmLamp function sets the alarm lamp pattern according to the - * current state of alarms. - * @details Inputs: none - * @details Outputs: Alarm lamp patter set according to current alarms status. - * @return none - *************************************************************************/ -static void setAlarmLamp( void ) + * current state of alarms. + * @details Inputs: none + * @details Outputs: Alarm lamp patter set according to current alarms status. + * @return none + *************************************************************************/ +static void setAlarmLamp( void ) { - // Set alarm lamp pattern to appropriate pattern for current alarm state - if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) - { - switch ( alarmStatus.alarmsState ) - { - case ALARM_PRIORITY_NONE: - requestAlarmLampPattern( LAMP_PATTERN_OK ); - break; - - case ALARM_PRIORITY_LOW: - requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); - break; - - case ALARM_PRIORITY_MEDIUM: - requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); - break; - - case ALARM_PRIORITY_HIGH: - if ( TRUE == ALARM_TABLE[ alarmStatus.alarmTop ].alarmIsFault ) - { - requestAlarmLampPattern( LAMP_PATTERN_FAULT ); - } - else - { - requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); - } - break; - - default: - requestAlarmLampPattern( LAMP_PATTERN_FAULT ); - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) - break; + // Set alarm lamp pattern to appropriate pattern for current alarm state + if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) + { + switch ( alarmStatus.alarmsState ) + { + case ALARM_PRIORITY_NONE: + requestAlarmLampPattern( LAMP_PATTERN_OK ); + break; + + case ALARM_PRIORITY_LOW: + requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); + break; + + case ALARM_PRIORITY_MEDIUM: + requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); + break; + + case ALARM_PRIORITY_HIGH: + if ( TRUE == ALARM_TABLE[ alarmStatus.alarmTop ].alarmIsFault ) + { + requestAlarmLampPattern( LAMP_PATTERN_FAULT ); + } + else + { + requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); + } + break; + + default: + requestAlarmLampPattern( LAMP_PATTERN_FAULT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) + break; } } - // Execute alarm lamp controller + // Execute alarm lamp controller execAlarmLamp(); // Set lamp on flag to match current state of alarm lamp @@ -1152,9 +1174,9 @@ else { alarmStatus.lampOn = FALSE; - } -} - + } +} + /*********************************************************************//** * @brief * The setAlarmAudio function sets the alarm audio pattern according to @@ -1211,64 +1233,64 @@ } } -/*********************************************************************//** - * @brief - * The updateAlarmsSilenceStatus function updates the alarms silence state. - * @details Inputs: alarmStatus - * @details Outputs: alarmStatus - * @return none - *************************************************************************/ -static void updateAlarmsSilenceStatus( void ) -{ - // If alarms not silenced, reset alarms silence related properties - if ( TRUE != alarmStatus.alarmsSilenced ) - { - alarmStatus.alarmsSilenceExpiresIn = 0; - alarmStatus.alarmsSilenceStart = 0; - } - else - { - U32 timeSinceAlarmSilenceStart = calcTimeSince( alarmStatus.alarmsSilenceStart ) / MS_PER_SECOND; - - if ( timeSinceAlarmSilenceStart >= ALARM_SILENCE_EXPIRES_IN_SECS ) - { - alarmStatus.alarmsSilenceExpiresIn = 0; - } - else - { - alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; - } - // If alarms silence expires, end it - if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) - { - alarmStatus.alarmsSilenced = FALSE; - } - } -} +/*********************************************************************//** + * @brief + * The updateAlarmsSilenceStatus function updates the alarms silence state. + * @details Inputs: alarmStatus + * @details Outputs: alarmStatus + * @return none + *************************************************************************/ +static void updateAlarmsSilenceStatus( void ) +{ + // If alarms not silenced, reset alarms silence related properties + if ( TRUE != alarmStatus.alarmsSilenced ) + { + alarmStatus.alarmsSilenceExpiresIn = 0; + alarmStatus.alarmsSilenceStart = 0; + } + else + { + U32 timeSinceAlarmSilenceStart = calcTimeSince( alarmStatus.alarmsSilenceStart ) / MS_PER_SECOND; -/*********************************************************************//** - * @brief - * The updateAlarmsFlags function updates the alarms flags of the alarms - * status record. - * @details Inputs: alarmStatus, alarmIsActive, ALARM_TABLE, alarmButtonBlockers - * @details Outputs: alarmStatus, alarmUserRecoveryActionEnabled, - * @return none - *************************************************************************/ -static void updateAlarmsFlags( void ) -{ - BOOL systemFault = FALSE; - BOOL stop = FALSE; - BOOL noClear = FALSE; + if ( timeSinceAlarmSilenceStart >= ALARM_SILENCE_EXPIRES_IN_SECS ) + { + alarmStatus.alarmsSilenceExpiresIn = 0; + } + else + { + alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; + } + // If alarms silence expires, end it + if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) + { + alarmStatus.alarmsSilenced = FALSE; + } + } +} + +/*********************************************************************//** + * @brief + * The updateAlarmsFlags function updates the alarms flags of the alarms + * status record. + * @details Inputs: alarmStatus, alarmIsActive, ALARM_TABLE, alarmButtonBlockers + * @details Outputs: alarmStatus, alarmUserRecoveryActionEnabled, + * @return none + *************************************************************************/ +static void updateAlarmsFlags( void ) +{ + BOOL systemFault = FALSE; + BOOL stop = FALSE; + BOOL noClear = FALSE; BOOL noResume = FALSE; - BOOL noResumePerAlarmPropertyOnly = alarmNoRetrigger; // cannot resume if no re-trigger flag is set - BOOL noRinseback = FALSE; + BOOL noResumePerAlarmPropertyOnly = alarmNoRetrigger; // cannot resume if no re-trigger flag is set + BOOL noRinseback = FALSE; BOOL noEndTreatment = FALSE; - BOOL endTxOnlyAlarmActive = FALSE; + BOOL endTxOnlyAlarmActive = FALSE; BOOL usrAckReq = FALSE; BOOL noMinimize = TRUE; HD_OP_MODE_T currentMode = getCurrentOperationMode(); - ALARM_ID_T a; - + ALARM_ID_T a; + // Set user alarm recovery actions allowed by state flags alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RESUME ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ? FALSE : TRUE ); alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RINSEBACK ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ? FALSE : TRUE ); @@ -1278,38 +1300,38 @@ alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] = FALSE; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] = FALSE; - // Determine alarm flags - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) - { - if ( TRUE == alarmIsActive[ a ] ) - { - systemFault = ( TRUE == ALARM_TABLE[ a ].alarmIsFault ? TRUE : systemFault ); - stop = ( TRUE == ALARM_TABLE[ a ].alarmStops ? TRUE : stop ); + // Determine alarm flags + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == alarmIsActive[ a ] ) + { + systemFault = ( TRUE == ALARM_TABLE[ a ].alarmIsFault ? TRUE : systemFault ); + stop = ( TRUE == ALARM_TABLE[ a ].alarmStops ? TRUE : stop ); noClear = ( TRUE == ALARM_TABLE[ a ].alarmNoClear ? TRUE : noClear ); noResumePerAlarmPropertyOnly = ( ALARM_TABLE[ a ].alarmNoResume ? TRUE : noResumePerAlarmPropertyOnly ); // Set user alarm recovery actions allowed flags alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RESUME ] |= ALARM_TABLE[ a ].alarmNoResume; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] |= ALARM_TABLE[ a ].alarmNoRinseback; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] |= ALARM_TABLE[ a ].alarmNoEndTreatment; if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ) - { + { noResume = ( TRUE == ALARM_TABLE[ a ].alarmNoResume ? TRUE : noResume ); } else { noResume = TRUE; - } + } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ) { noRinseback = ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ? TRUE : noRinseback ); } else { noRinseback = TRUE; - } + } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_END_TREATMENT ] ) { - noEndTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoEndTreatment ? TRUE : noEndTreatment ); + noEndTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoEndTreatment ? TRUE : noEndTreatment ); } else { @@ -1321,8 +1343,8 @@ ( FALSE == ALARM_TABLE[ a ].alarmNoEndTreatment ) ) { endTxOnlyAlarmActive = TRUE; - } - } // If alarm active + } + } // If alarm active } // Alarm table loop // If top alarm condition not cleared, block resume @@ -1358,24 +1380,23 @@ noEndTreatment = TRUE; } - // If in Treatment-Stop state or Fault/Service/Standby Mode, allow user to minimize the alarm window - if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) || - ( ( MODE_TREA == currentMode ) && ( TREATMENT_STOP_STATE == getTreatmentState() ) ) ) + // If in Treatment/Fault/Service/Standby Mode, allow user to minimize the alarm window + if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) || ( MODE_TREA == currentMode ) ) { noMinimize = FALSE; } - // Set updated alarm flags - alarmStatus.systemFault = systemFault; - alarmStatus.stop = stop; - alarmStatus.noClear = noClear; - alarmStatus.noResume = noResume; - alarmStatus.noRinseback = noRinseback; - alarmStatus.noEndTreatment = noEndTreatment; - alarmStatus.ok = usrAckReq; + // Set updated alarm flags + alarmStatus.systemFault = systemFault; + alarmStatus.stop = stop; + alarmStatus.noClear = noClear; + alarmStatus.noResume = noResume; + alarmStatus.noRinseback = noRinseback; + alarmStatus.noEndTreatment = noEndTreatment; + alarmStatus.ok = usrAckReq; alarmStatus.noMinimize = noMinimize; alarmStatus.noReTrigger = alarmNoRetrigger; - resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; + resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; } /*********************************************************************//** @@ -1426,7 +1447,8 @@ } } // check special cases where we do not want to clear this alarm - otherwise, clear it - if ( ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT == a ) && ( TRUE == alarmIsDetected[ a ] ) && ( mode != MODE_POST ) && + if ( ( ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT == a ) || ( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT == a ) ) && + ( TRUE == alarmIsDetected[ a ] ) && ( mode != MODE_POST ) && ( action != ALARM_USER_ACTION_RINSEBACK ) && ( action != ALARM_USER_ACTION_END_TREATMENT ) ) { // do not clear this alarm if condition not cleared first (unless treatment is over) @@ -1446,31 +1468,31 @@ } return result; -} - -/*********************************************************************//** - * @brief - * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm - * priority. - * @details Inputs: none - * @details Outputs: alarmPriorityFIFO[] - * @param priority priority of FIFO to reset - * @return none - *************************************************************************/ -static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) -{ - // Verify priority - if ( priority < NUM_OF_ALARM_PRIORITIES ) - { +} + +/*********************************************************************//** + * @brief + * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm + * priority. + * @details Inputs: none + * @details Outputs: alarmPriorityFIFO[] + * @param priority priority of FIFO to reset + * @return none + *************************************************************************/ +static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) +{ + // Verify priority + if ( priority < NUM_OF_ALARM_PRIORITIES ) + { alarmPriorityFIFO[ priority ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ priority ].subRank = LOWEST_ALARM_SUB_RANK; - alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = -1; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) - } -} + alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = -1; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) + } +} /*********************************************************************//** * @brief @@ -1688,132 +1710,132 @@ { alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } - - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ - - -/*********************************************************************//** - * @brief - * The testSetAlarmStateOverride function overrides the state of the - * alarm active state for a given alarm with the alarm management with - * a given active state. - * @details Inputs: none - * @details Outputs: alarm activated or cleared - * @param alarmID ID of alarm to activate or clear - * @param value override state for the given alarm ID (1=activate, 0=clear) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetAlarmStateOverride( U32 alarmID, U32 state ) -{ - BOOL result = FALSE; - - if ( alarmID < NUM_OF_ALARM_IDS ) - { + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetAlarmStateOverride function overrides the state of the + * alarm active state for a given alarm with the alarm management with + * a given active state. + * @details Inputs: none + * @details Outputs: alarm activated or cleared + * @param alarmID ID of alarm to activate or clear + * @param value override state for the given alarm ID (1=activate, 0=clear) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetAlarmStateOverride( U32 alarmID, U32 state ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { // Verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - if ( TRUE == state ) - { - activateAlarmNoData( (ALARM_ID_T)alarmID ); - } - else - { - clearAlarm( (ALARM_ID_T)alarmID ); - } - result = TRUE; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetAlarmStateOverride function resets the override of the - * state of the active state for a given alarm with the alarm management. - * @details Inputs: none - * @details Outputs: alarm cleared - * @param alarmID ID of alarm to clear - * @return TRUE if alarm clear successful, FALSE if not - *************************************************************************/ -BOOL testResetAlarmStateOverride( U32 alarmID ) -{ - BOOL result = FALSE; - - if ( alarmID < NUM_OF_ALARM_IDS ) - { + if ( TRUE == isTestingActivated() ) + { + if ( TRUE == state ) + { + activateAlarmNoData( (ALARM_ID_T)alarmID ); + } + else + { + clearAlarm( (ALARM_ID_T)alarmID ); + } + result = TRUE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetAlarmStateOverride function resets the override of the + * state of the active state for a given alarm with the alarm management. + * @details Inputs: none + * @details Outputs: alarm cleared + * @param alarmID ID of alarm to clear + * @return TRUE if alarm clear successful, FALSE if not + *************************************************************************/ +BOOL testResetAlarmStateOverride( U32 alarmID ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { // Verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - clearAlarm( (ALARM_ID_T)alarmID ); - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetAlarmStartOverride function overrides the start time - * for a given alarm with the alarm management with a given start time. - * @details Inputs: none - * @details Outputs: alarmStartedAt[] - * @param alarmID ID of alarm to override start time for - * @param value override time since start (in ms) for the given alarm ID - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ) -{ - BOOL result = FALSE; - - if ( alarmID < NUM_OF_ALARM_IDS ) - { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + clearAlarm( (ALARM_ID_T)alarmID ); + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetAlarmStartOverride function overrides the start time + * for a given alarm with the alarm management with a given start time. + * @details Inputs: none + * @details Outputs: alarmStartedAt[] + * @param alarmID ID of alarm to override start time for + * @param value override time since start (in ms) for the given alarm ID + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { // Verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - U32 tim = getMSTimerCount(); - - if ( tim > value ) - { - result = TRUE; - alarmStartedAt[ alarmID ].ovData = ( tim - value ); - alarmStartedAt[ alarmID ].override = OVERRIDE_KEY; - } - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetAlarmStartOverride function resets the override of the - * start time for a given alarm with the alarm management. - * @details Inputs: none - * @details Outputs: alarmStartedAt[] - * @param alarmID ID of alarm to reset override of start time for - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetAlarmStartOverride( U32 alarmID ) -{ - BOOL result = FALSE; - - if ( alarmID < NUM_OF_ALARM_IDS ) - { + if ( TRUE == isTestingActivated() ) + { + U32 tim = getMSTimerCount(); + + if ( tim > value ) + { + result = TRUE; + alarmStartedAt[ alarmID ].ovData = ( tim - value ); + alarmStartedAt[ alarmID ].override = OVERRIDE_KEY; + } + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetAlarmStartOverride function resets the override of the + * start time for a given alarm with the alarm management. + * @details Inputs: none + * @details Outputs: alarmStartedAt[] + * @param alarmID ID of alarm to reset override of start time for + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetAlarmStartOverride( U32 alarmID ) +{ + BOOL result = FALSE; + + if ( alarmID < NUM_OF_ALARM_IDS ) + { // Verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - alarmStartedAt[ alarmID ].override = OVERRIDE_RESET; - alarmStartedAt[ alarmID ].ovData = alarmStartedAt[ alarmID ].ovInitData; - } - } - - return result; + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + alarmStartedAt[ alarmID ].override = OVERRIDE_RESET; + alarmStartedAt[ alarmID ].ovData = alarmStartedAt[ alarmID ].ovInitData; + } + } + + return result; } /*********************************************************************//** @@ -2140,6 +2162,6 @@ } return result; -} +} /**@}*/ Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -14,28 +14,28 @@ * @date (original) 07-Nov-2019 * ***************************************************************************/ - -#ifndef __ALARM_MGMT_H__ -#define __ALARM_MGMT_H__ - -#include "HDCommon.h" - -/** - * @defgroup AlarmManagement AlarmManagement - * @brief Alarm Management service module. Provides general alarm management - * functionality including support functions for triggering and clearing - * specific alarms. - * - * @addtogroup AlarmManagement - * @{ - */ - -// ********** public definitions ********** - + +#ifndef __ALARM_MGMT_H__ +#define __ALARM_MGMT_H__ + +#include "HDCommon.h" + +/** + * @defgroup AlarmManagement AlarmManagement + * @brief Alarm Management service module. Provides general alarm management + * functionality including support functions for triggering and clearing + * specific alarms. + * + * @addtogroup AlarmManagement + * @{ + */ + +// ********** public definitions ********** + #include "AlarmDefs.h" -#include "AlarmMgmtSWFaults.h" +#include "AlarmMgmtSWFaults.h" -/// Interval (in ms) at which alarm lamp and audio control will be executed. +/// Interval (in ms) at which alarm lamp and audio control will be executed. #define ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS 250 #define MAX_ALARM_VOLUME_LEVEL 5 ///< Maximum alarm audio level. @@ -54,72 +54,72 @@ NUMBER_OF_ALARM_ACTIONS ///< Number of alarm actions } ALARM_ACTION_T; -#pragma pack(push, 4) -/// Record structure for detailing the properties of the current composite alarm status. -typedef struct -{ - ALARM_PRIORITY_T alarmsState; ///< Current alarm priority level - BOOL alarmsSilenced; ///< Alarms are currently silenced? - U32 alarmsSilenceStart; ///< Time stamp for when alarms were silenced (ms) +#pragma pack(push, 4) +/// Record structure for detailing the properties of the current composite alarm status. +typedef struct +{ + ALARM_PRIORITY_T alarmsState; ///< Current alarm priority level + BOOL alarmsSilenced; ///< Alarms are currently silenced? + U32 alarmsSilenceStart; ///< Time stamp for when alarms were silenced (ms) U32 alarmsSilenceExpiresIn; ///< Time until alarm silence expires (seconds) - BOOL alarmsToEscalate; ///< Are any active alarms due to escalate (should UI show count down timer?) - U32 alarmsEscalatesIn; ///< Time until alarm will escalate (seconds) + BOOL alarmsToEscalate; ///< Are any active alarms due to escalate (should UI show count down timer?) + U32 alarmsEscalatesIn; ///< Time until alarm will escalate (seconds) ALARM_ID_T alarmTop; ///< ID of current top alarm that will drive lamp/audio and UI should be displaying right now - BOOL topAlarmConditionDetected; ///< Condition for top alarm is still being detected - BOOL systemFault; ///< A system fault is active? - BOOL stop; ///< We should be in controlled stop right now - BOOL noClear; ///< No recovery will be possible - BOOL noResume; ///< Treatment may not be resumed at this time - BOOL noRinseback; ///< Rinseback may not be initiated at this time - BOOL noEndTreatment; ///< Ending the treatment is not an option at this time + BOOL topAlarmConditionDetected; ///< Condition for top alarm is still being detected + BOOL systemFault; ///< A system fault is active? + BOOL stop; ///< We should be in controlled stop right now + BOOL noClear; ///< No recovery will be possible + BOOL noResume; ///< Treatment may not be resumed at this time + BOOL noRinseback; ///< Rinseback may not be initiated at this time + BOOL noEndTreatment; ///< Ending the treatment is not an option at this time BOOL noBloodRecirc; ///< No blood re-circulation allowed at this time - BOOL noDialRecirc; ///< No dialysate re-circulation allowed at this time + BOOL noDialRecirc; ///< No dialysate re-circulation allowed at this time BOOL ok; ///< Display OK button instead of other options BOOL noMinimize; ///< Prevent user from minimizing the alarm window BOOL lampOn; ///< The alarm lamp is on BOOL noReTrigger; ///< Alarm flag to block re-trigger is set -} COMP_ALARM_STATUS_T; - -/// Record structure for unsigned integer alarm data. -typedef struct -{ - U32 data; ///< Alarm data of unsigned integer type. -} ALARM_DATA_U32_T; - -/// Record structure for signed integer alarm data. -typedef struct -{ - S32 data; ///< Alarm data of signed integer type. -} ALARM_DATA_S32_T; - -/// Record structure for floating point alarm data. -typedef struct -{ - F32 data; ///< Alarm data of floating point type. -} ALARM_DATA_F32_T; - -/// Record structure for boolean alarm data. -typedef struct -{ - BOOL data; ///< Alarm data of boolean type. -} ALARM_DATA_BOOL_T; - -/// Record structure for alarm data of any supported type. -typedef union -{ - ALARM_DATA_U32_T uInt; ///< Alarm data of unsigned integer type. - ALARM_DATA_S32_T sInt; ///< Alarm data of signed integer type. - ALARM_DATA_F32_T flt; ///< Alarm data of floating point type. - ALARM_DATA_BOOL_T bln; ///< Alarm data of boolean type. -} ALARM_DATAS_T; - -/// Record structure for alarm data including the data type to aid in interpretation. -typedef struct -{ - ALARM_DATA_TYPES_T dataType; ///< The type of alarm data provided. - ALARM_DATAS_T data; ///< The alarm data of specified type. -} ALARM_DATA_T; +} COMP_ALARM_STATUS_T; +/// Record structure for unsigned integer alarm data. +typedef struct +{ + U32 data; ///< Alarm data of unsigned integer type. +} ALARM_DATA_U32_T; + +/// Record structure for signed integer alarm data. +typedef struct +{ + S32 data; ///< Alarm data of signed integer type. +} ALARM_DATA_S32_T; + +/// Record structure for floating point alarm data. +typedef struct +{ + F32 data; ///< Alarm data of floating point type. +} ALARM_DATA_F32_T; + +/// Record structure for boolean alarm data. +typedef struct +{ + BOOL data; ///< Alarm data of boolean type. +} ALARM_DATA_BOOL_T; + +/// Record structure for alarm data of any supported type. +typedef union +{ + ALARM_DATA_U32_T uInt; ///< Alarm data of unsigned integer type. + ALARM_DATA_S32_T sInt; ///< Alarm data of signed integer type. + ALARM_DATA_F32_T flt; ///< Alarm data of floating point type. + ALARM_DATA_BOOL_T bln; ///< Alarm data of boolean type. +} ALARM_DATAS_T; + +/// Record structure for alarm data including the data type to aid in interpretation. +typedef struct +{ + ALARM_DATA_TYPES_T dataType; ///< The type of alarm data provided. + ALARM_DATAS_T data; ///< The alarm data of specified type. +} ALARM_DATA_T; + /// Payload record structure for the alarm triggered message. typedef struct { @@ -180,7 +180,7 @@ typedef struct { U32 alarmID; ///< Alarm ID. -} ALARM_ID_DATA_PUBLISH_T; +} ALARM_ID_DATA_PUBLISH_T; /// Alarm list request response payload record structure. typedef struct @@ -190,46 +190,47 @@ U32 activeAlarmList[ MAX_ALARM_LIST_SIZE ]; ///< Active Alarm List array. } ACTIVE_ALARM_LIST_RESPONSE_PAYLOAD_T; -// ********** public function prototypes ********** - -void initAlarmMgmt( void ); -void execAlarmMgmt( void ); - -void activateAlarmNoData( ALARM_ID_T alarm ); -void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ); -void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ); +// ********** public function prototypes ********** + +void initAlarmMgmt( void ); +void execAlarmMgmt( void ); + +void activateAlarmNoData( ALARM_ID_T alarm ); +void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ); +void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ); void clearAlarm( ALARM_ID_T alarm ); void clearAlarmCondition( ALARM_ID_T alarm ); void clearNoRetriggerFlag( void ); BOOL getNoRetriggerFlag( void ); -void setAlarmUserActionEnabled( ALARM_USER_ACTION_T action, BOOL enabled ); +void setAlarmUserActionEnabled( ALARM_USER_ACTION_T action, BOOL enabled ); void signalAlarmSilence( ALARM_SILENCE_CMD_T cmd ); void signalAlarmUserActionInitiated( ALARM_USER_ACTION_T action ); BOOL isAlarmActive( ALARM_ID_T alarm ); BOOL isAlarmConditionDetected( ALARM_ID_T alarm ); BOOL isAnyAlarmActive( void ); BOOL isBloodRecircBlocked( void ); BOOL isDialysateRecircBlocked( void ); +BOOL isRinseBackBlocked( void ); BOOL doesAlarmStatusIndicateStop( void ); BOOL doesAlarmIndicateNoResume( void ); BOOL doesAlarmStatusIndicateEndTxOnly( void ); -ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ); +ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ); BOOL isAlarmRecoverable( ALARM_ID_T alarm ); void setAlarmAudioVolume( U32 volumeLevel ); void handleActiveAlarmListRequest( void ); -void handleResendActiveAlarmsRequest( void ); +void handleResendActiveAlarmsRequest( void ); U32 getAlarmAudioVolume( void ); F32 getAlarmAudioPrimaryHighGainCurrent( void ); F32 getAlarmAudioPrimaryLowGainCurrent( void ); F32 getAlarmAudioBackupCurrent( void ); SELF_TEST_STATUS_T execAlarmAudioSelfTest( void ); void resetAlarmAudioPOSTState( void ); - -BOOL testSetAlarmStateOverride( U32 alarmID, BOOL value ); -BOOL testResetAlarmStateOverride( U32 alarmID ); -BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ); + +BOOL testSetAlarmStateOverride( U32 alarmID, BOOL value ); +BOOL testResetAlarmStateOverride( U32 alarmID ); +BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ); BOOL testResetAlarmStartOverride( U32 alarmID ); BOOL testClearAllAlarms( U32 key ); BOOL testSetAlarmStatusPublishIntervalOverride( U32 ms ); @@ -243,8 +244,8 @@ BOOL testSetPrimaryAlarmAudioCurrentLGOverride( F32 mA ); BOOL testResetPrimaryAlarmAudioCurrentLGOverride( void ); BOOL testSetBackupAlarmAudioCurrentOverride( F32 mA ); -BOOL testResetBackupAlarmAudioCurrentOverride( void ); - +BOOL testResetBackupAlarmAudioCurrentOverride( void ); + /**@}*/ -#endif +#endif Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -33,8 +33,9 @@ #include "OperationModes.h" #include "Reservoirs.h" #include "RTC.h" -#include "SampleWater.h" #include "SafetyShutdown.h" +#include "SalineBolus.h" +#include "SampleWater.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "Temperatures.h" @@ -3488,8 +3489,7 @@ payloadPtr += sizeof(U32); memcpy( &status, payloadPtr, sizeof(U32) ); - if ( ( CONFIRMATION_REQUEST_STATUS_REJECTED == status ) || - ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == status ) ) + if ( ( CONFIRMATION_REQUEST_STATUS_REJECTED == status ) || ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == status ) ) { setConfirmationRequestStatus( (GENERIC_CONFIRM_ID_T)request_id, (CONFIRMATION_REQUEST_STATUS_T)status ); } @@ -3503,29 +3503,21 @@ * The sendConfirmationRequest function sends a confirmation request to UI * @details Inputs: none * @details Outputs: none - * @param requestID ID of confirmation being requested - * @param requestType Type of confirmation being requested - * @param rejectReason Reason Reason for reject if type is reject + * @param request ID pointer to generic message request structure * @return none *************************************************************************/ -void sendConfirmationRequest( GENERIC_CONFIRM_ID_T requestID, GENERIC_CONFIRM_COMMAND_T requestType, U32 rejectReason ) +void sendConfirmationRequest( GENERIC_CONFIRMATION_REQUEST_T *request ) { MESSAGE_T msg; U08 *payloadPtr = msg.payload; - U32 temp_request = requestID; // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_HD_UI_CONFIRMATION_REQUEST; // The payload length is U32 Request ID, U32 Type, U32 Reject Reason - msg.hdr.payloadLen = 3 * sizeof( U32 ); + msg.hdr.payloadLen = sizeof( GENERIC_CONFIRMATION_REQUEST_T ); - memcpy( payloadPtr, &temp_request, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - temp_request = requestType; - memcpy( payloadPtr, &temp_request, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &rejectReason, sizeof( U32 ) ); + memcpy( payloadPtr, request, sizeof( GENERIC_CONFIRMATION_REQUEST_T ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r13a064292b5a36a85593f53eabae268ae2bf4bc6 -r8639aa012127798aeb8fd719dd7f93b83275f944 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 13a064292b5a36a85593f53eabae268ae2bf4bc6) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 8639aa012127798aeb8fd719dd7f93b83275f944) @@ -523,7 +523,7 @@ void handleUIConfirmationResponse( MESSAGE_T *message ); // MSG_ID_HD_REQUEST_UI_CONFIRMATION -void sendConfirmationRequest( GENERIC_CONFIRM_ID_T request_id, GENERIC_CONFIRM_COMMAND_T request_type, U32 reject_reason ); +void sendConfirmationRequest( GENERIC_CONFIRMATION_REQUEST_T *request ); // MSG_ID_HD_REQUEST_DG_ALARMS BOOL sendRequestForDGResendAlarms( void );