Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r88a641b7b0185e0bad77e21e6d438e1d7283fd28 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 88a641b7b0185e0bad77e21e6d438e1d7283fd28) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -53,7 +53,7 @@ #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.12 ///< Controller will error if PWM duty cycle < 10%, so set min to 12% /// Interval (ms/task time) at which the blood pump is controlled. -#define BP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) +static const U32 BP_CONTROL_INTERVAL = ( 10000 / TASK_GENERAL_INTERVAL ); #define BP_P_COEFFICIENT 0.00035 ///< P term for blood pump control #define BP_I_COEFFICIENT 0.00035 ///< I term for blood pump control @@ -69,13 +69,19 @@ #define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured speed and speed implied by measured flow. #define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). -#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define BP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for flow vs. motor speed error condition. -#define BP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for motor off error condition. -#define BP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) motor speed error condition. -#define BP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) rotor speed error condition. -#define BP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) pump direction error condition. -#define BP_MAX_ROTOR_SPEED_ERROR_PERSIST ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) blood pump rotor speed too fast error condition. +#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. +/// Persist time (task intervals) for flow vs. motor speed error condition. +static const U32 BP_FLOW_VS_SPEED_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) for motor off error condition. +static const U32 BP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) motor speed error condition. +static const U32 BP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) rotor speed error condition. +static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) pump direction error condition. +static const U32 BP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) blood pump rotor speed too fast error condition. +static const U32 BP_MAX_ROTOR_SPEED_ERROR_PERSIST = ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped #define BP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< Motor controller current should always exceed this when pump should be running @@ -425,7 +431,7 @@ HD_OP_MODE_T opMode = getCurrentOperationMode(); U16 bpRPM = getIntADCReading( INT_ADC_BLOOD_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_BLOOD_PUMP_MOTOR_CURRENT ); - F32 bpFlow = ( ( getFPGABloodFlow() * -1.0 ) * bloodFlowCalGain ) + bloodFlowCalOffset; // Blood flow sensor installed backwards on HD + F32 bpFlow = ( ( getFPGABloodFlow() ) * bloodFlowCalGain ) + bloodFlowCalOffset; adcBloodPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * BP_SPEED_ADC_TO_RPM_FACTOR; adcBloodPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -49,7 +49,7 @@ TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE, ///< Wait for fill to complete. TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE, ///< Wait a bit for filled reservoir to settle before getting baseline weight (volume). TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE, ///< Wait for active reservoir to be consumed and switch cmd given - then back to flush DG lines state. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Wait for inactive reservoir to settle before getting final weight (volume) before starting to drain. + TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Wait for inactive reservoir to settle before getting final weight (volume) before starting to drain. NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir mgmt. states. } TREATMENT_RESERVOIR_MGMT_STATE_T; @@ -197,6 +197,19 @@ resMgmtTimer = 0; resUseTimer = getMSTimerCount(); resUseVolumeMl = 0.0; +} + +/*********************************************************************//** + * @brief + * The dialysisResumed function initializes the reservoir re-use timer + * when dialysis is started/resumed so that dialysate usage can be tracked. + * @details Inputs: none + * @details Outputs: resUseTimer + * @return none + *************************************************************************/ +void dialysisResumed( void ) +{ + resUseTimer = getMSTimerCount(); } /*********************************************************************//** @@ -213,22 +226,22 @@ U32 dgSubMode = getDGSubMode(); U32 msSinceLastVolumeCalc = calcTimeSince( resUseTimer ); F32 flowRateMlPerMs = (F32)getTargetDialInFlowRate() / (F32)( MS_PER_SECOND * SEC_PER_MIN ); - + // Calculate volume used from active reservoir - do not accumulate if saline bolus in progress if ( SALINE_BOLUS_STATE_IN_PROGRESS != getSalineBolusState() ) { resUseVolumeMl += ( flowRateMlPerMs * msSinceLastVolumeCalc ); // TODO - should this calc be done and kept by Dialysis sub-mode? } - resUseTimer = getMSTimerCount(); - + resUseTimer = getMSTimerCount(); + // Treatment reservoir mgmt. state machine switch ( currentTrtResMgmtState ) { case TREATMENT_RESERVOIR_MGMT_START_STATE: currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; break; - case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: + case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: if ( DG_MODE_CIRC == dgOpMode ) { if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) @@ -249,7 +262,7 @@ case TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE: if ( DG_MODE_CIRC == dgOpMode ) { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; + currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; } break; @@ -272,7 +285,7 @@ if ( DG_MODE_FILL == dgOpMode ) { currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; - } + } break; case TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE: @@ -320,8 +333,8 @@ // Reset to start state to restart drain, fill, switch process. currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; } - break; - + break; + default: // TODO - s/w fault currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -120,7 +120,8 @@ void execDGInterfaceMonitor( void ); void initTreatmentReservoirMgmt( void ); -void execTreatmentReservoirMgmt( void ); +void dialysisResumed( void ); +void execTreatmentReservoirMgmt( void ); DG_OP_MODE_T getDGOpMode( void ); U32 getDGSubMode( void ); Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r88a641b7b0185e0bad77e21e6d438e1d7283fd28 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 88a641b7b0185e0bad77e21e6d438e1d7283fd28) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -48,8 +48,9 @@ #define MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE 0.02 ///< Max duty cycle change when ramping down ~ 300 mL/min/s. #define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.88 ///< Controller will error if PWM duty cycle > 90%, so set max to 88%. #define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.12 ///< Controller will error if PWM duty cycle < 10%, so set min to 12%. - -#define DIP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialIn pump is controlled + +/// Interval (ms/task time) at which the dialIn pump is controlled. +static const U32 DIP_CONTROL_INTERVAL = ( 10000 / TASK_GENERAL_INTERVAL ); #define DIP_P_COEFFICIENT 0.00035 ///< P term for dialIn pump control. #define DIP_I_COEFFICIENT 0.00035 ///< I term for dialIn pump control. @@ -64,12 +65,18 @@ #define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured motor speed and speed implied by measured flow. #define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). -#define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define DIP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for flow vs. motor speed error condition. -#define DIP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for motor off error condition. -#define DIP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) motor speed error condition. -#define DIP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) rotor speed error condition. -#define DIP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) pump direction error condition. +#define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. + +/// Persist time (task intervals) for flow vs. motor speed error condition. +static const U32 DIP_FLOW_VS_SPEED_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) for motor off error condition. +static const U32 DIP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) motor speed error condition. +static const U32 DIP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) rotor speed error condition. +static const U32 DIP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) pump direction error condition. +static const U32 DIP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -51,7 +51,8 @@ #define MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.88 ///< Controller will error if PWM duty cycle > 90%, so set max to 88%. #define MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.12 ///< Controller will error if PWM duty cycle < 10%, so set min to 12%. -#define DOP_CONTROL_INTERVAL ( 2000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate outlet pump is controlled. +/// Interval (ms/task time) at which the dialysate outlet pump is controlled. +static const U32 DOP_CONTROL_INTERVAL = ( 2000 / TASK_GENERAL_INTERVAL ); #define DOP_P_COEFFICIENT 0.0050 ///< P term for dialysate outlet pump control. #define DOP_I_COEFFICIENT 0.0001 ///< I term for dialysate outlet pump control. @@ -66,11 +67,16 @@ #define DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define DOP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define DOP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for motor off error condition. -#define DOP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) motor speed error condition. -#define DOP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) rotor speed error condition. -#define DOP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) pump direction error condition. +/// Persist time (task intervals) for motor off error condition. +static const U32 DOP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) motor speed error condition. +static const U32 DOP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) rotor speed error condition. +static const U32 DOP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) pump direction error condition. +static const U32 DOP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); + #define DOP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. #define DOP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< Motor controller current should always exceed this when pump should be running. #define DOP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r8b7c7ff2bdb82aca355e3eed90cbdc6eb9507719 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 8b7c7ff2bdb82aca355e3eed90cbdc6eb9507719) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -51,11 +51,14 @@ #define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). #define VENOUS_PRESSURE_DIAG_CONDITION 3 ///< Venous pressure status bits diagnostic condition (alarm). -#define MAX_TIME_BETWEEN_VENOUS_READINGS ( 500 / TASK_GENERAL_INTERVAL ) ///< Maximum time without fresh inline venous pressure reading. +static const U32 MAX_TIME_BETWEEN_VENOUS_READINGS = ( 500 / TASK_GENERAL_INTERVAL ); ///< Maximum time without fresh inline venous pressure reading. #define OCCLUSION_THRESHOLD 25000 ///< Threshold above which an occlusion is detected. #define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. +#define EMPTY_SALINE_BAG_THRESHOLD_MMHG -300.0 ///< Threshold below which the saline bag is considered empty (in mmHg). TODO - get real threshold from Systems +static const U32 EMPTY_SALINE_BAG_PERSISTENCE = ( 250 / TASK_GENERAL_INTERVAL ); ///< Time that saline bag looks empty before saying it is empty. TODO - use persistent alarm when updated + #define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. /// Defined states for the pressure and occlusion monitor state machine. @@ -93,6 +96,7 @@ static U32 bloodPumpSelfTestTimerCount = 0; ///< Timer counter for pressure self-test. static U32 staleVenousPressureCtr = 0; ///< Timer counter for stale venous pressure reading. +static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. // ********** private function prototypes ********** @@ -147,6 +151,35 @@ return result; } +/*********************************************************************//** + * @brief + * The isSalineBagEmpty function determines whether the saline bag is empty. + * It is assumed that this function will only be called from mode handling + * (General Task) when pumping (BP) from the saline bag. + * Determination is based on pressure going below a negative threshold. + * @details Inputs: arterial line pressure + * @details Outputs: none + * @return TRUE if arterial line pressure is below threshold, FALSE if not. + *************************************************************************/ +BOOL isSalineBagEmpty( void ) +{ + BOOL result = FALSE; + + if ( getMeasuredArterialPressure() < EMPTY_SALINE_BAG_THRESHOLD_MMHG ) + { + if ( ++emptySalineBagCtr >= EMPTY_SALINE_BAG_PERSISTENCE ) + { + result = TRUE; + } + } + else + { + emptySalineBagCtr = 0; + } + + return result; +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -40,13 +40,11 @@ // ********** private definitions ********** #define MAX_UF_RATE_ML_PER_HOUR 2750.0 ///< Maximum ultrafiltration rate in mL/hour -#define MAX_UF_RATE_ACCURACY_ERROR_ML_HR 100.0 ///< Maximum ultrafiltration rate accuracy error in mL/hr over each hour of treatment. -#define MAX_UF_RATE_ACCURACY_ERROR_PCT 0.05 ///< Minimum ultrafilteration rate accuracy in percentage of set point (5%) over each hour of treatment. #define MAX_UF_ACCURACY_ERROR_ML 250.0 ///< Maximum ultrafiltration accuracy error in mL over the entire treatment. /// Saline bolus data broadcast interval (ms/task time) count. -#define SALINE_BOLUS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) +static const U32 SALINE_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Ultrafiltration rate accuracy check interval count. -#define UF_ACCURACY_CHECK_INTERVAL ((1 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL) +static const U32 UF_ACCURACY_CHECK_INTERVAL = ((1 * MIN_PER_HOUR * SEC_PER_MIN * 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 150 ///< Fixed rate for saline bolus delivery. @@ -74,7 +72,6 @@ static U32 setDialysateFlowRate; ///< Currently set dialysate flow rate (from prescription). static F32 maxUFVolumeML; ///< Currently set total ultrafiltration volume for treatment (from prescription). static F32 setUFRate; ///< Currently set ultrafiltration rate (from prescription). -static F32 maxUFRateAccuracyError_Ml_hr; ///< Minimum ultrafiltration rate accuracy over 1 hour duration (5% or 100 mL, whichever is greater). 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. @@ -139,7 +136,6 @@ setDialysateFlowRate = 0; maxUFVolumeML = 0.0; setUFRate = 0.0; - maxUFRateAccuracyError_Ml_hr = MAX_UF_RATE_ACCURACY_ERROR_ML_HR; salineBolusBroadcastTimerCtr = 0; totalSalineVolumeDelivered = 0.0; @@ -186,7 +182,38 @@ *************************************************************************/ void transitionToDialysis( void ) { - startAirTrapControl(); // TODO - do we need to start this sooner? After prime? + // Set last UF timestamp so UF ref is resumed from this time + lastUFTimeStamp = getMSTimerCount(); + // Send dialysate outlet pump latest UF volumes + setDialOutUFVolumes( refUFVolume, measUFVolume ); + + // Inform DG interface that dialysis has started/resumed + dialysisResumed(); + + // Set valves for dialysis + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // Restart pumps +#ifndef RUN_PUMPS_OPEN_LOOP + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); +#else + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); +#endif + setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // TODO - Heparin pump + // Tell DG to start heating dialysate + cmdStartDGTrimmerHeater(); + + startAirTrapControl(); + + // Set user alarm recovery actions allowed in this sub-mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); } /*********************************************************************//** @@ -208,8 +235,6 @@ setDialysateFlowRate = dPFlow; maxUFVolumeML = maxUFVol; setUFRate = uFRate; - maxUFRateAccuracyError_Ml_hr = MAX_UF_RATE_ACCURACY_ERROR_PCT * uFRate * (F32)MIN_PER_HOUR; - maxUFRateAccuracyError_Ml_hr = MAX( maxUFRateAccuracyError_Ml_hr, MAX_UF_RATE_ACCURACY_ERROR_ML_HR ); if ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) { @@ -226,41 +251,6 @@ /*********************************************************************//** * @brief - * The startDialysis function starts/resumes dialysis. This function - * will be called by Treatment Mode when beginning or resuming dialysis - * treatment. - * @details Inputs: none - * @details Outputs: Dialysis module prepared for immediate resumption. - * @return none - *************************************************************************/ -void startDialysis( void ) -{ - // Set last UF timestamp so UF ref is resumed from this time - lastUFTimeStamp = getMSTimerCount(); - // Send dialysate outlet pump latest UF volumes - setDialOutUFVolumes( refUFVolume, measUFVolume ); - - // Set valves for dialysis - setValvePosition( VDI, VALVE_POSITION_B_OPEN ); - setValvePosition( VDO, VALVE_POSITION_B_OPEN ); - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - // Restart pumps -#ifndef RUN_PUMPS_OPEN_LOOP - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); -#else - setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); -#endif - setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // TODO - Heparin pump - // Tell DG to start heating dialysate - cmdStartDGTrimmerHeater(); -} - -/*********************************************************************//** - * @brief * The stopDialysis function stops dialysis. This function will be called * by Treatment Mode when an alarm occurs or the user pressed the stop button. * Dialysis may be resumed later. @@ -736,7 +726,7 @@ updateUFVolumes(); // If we have reached target UF volume, UF is complete - if ( measUFVolume >= maxUFVolumeML ) + if ( refUFVolume >= maxUFVolumeML ) { result = UF_COMPLETED_STATE; } @@ -943,6 +933,7 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_EMPTY_SALINE_BAG, 0.0 ); // TODO - give data supporting empty bag detection errorFound = TRUE; + result = SALINE_BOLUS_STATE_IDLE; } #endif @@ -1004,7 +995,7 @@ currentUFState = UF_RUNNING_STATE; } // Resume dialysis - startDialysis(); + transitionToDialysis(); } } @@ -1066,22 +1057,19 @@ { F32 uFMeasRate = measUFVolume - lastUFVolumeChecked; // Volumes are at start/end of 1 hour period, so implied rate is per hour - // Check UF rate diff from target in last hour - if ( uFMeasRate > maxUFRateAccuracyError_Ml_hr ) + // Check UF rate over last hour + if ( uFMeasRate > MAX_UF_RATE_ML_PER_HOUR ) { #ifndef DISABLE_UF_ALARMS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_UF_RATE_TOO_HIGH_ERROR, uFMeasRate ); #endif } - // If actively performing ultrafiltration right now, increment timer and see if time to start another 1 hour check period - if ( UF_RUNNING_STATE == currentUFState ) + // Increment timer and see if time to start another 1 hour check period + if ( ++uFAccuracyCheckTimerCtr >= UF_ACCURACY_CHECK_INTERVAL ) { - if ( ++uFAccuracyCheckTimerCtr >= UF_ACCURACY_CHECK_INTERVAL ) - { - // Reset for next check interval - lastUFVolumeChecked = measUFVolume; - uFAccuracyCheckTimerCtr = 0; - } + // Reset for next check interval + lastUFVolumeChecked = measUFVolume; + uFAccuracyCheckTimerCtr = 0; } // Check total UF volume error Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r3d5a2ff09f3f4983699bfc61c7b63df1732970e0 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 3d5a2ff09f3f4983699bfc61c7b63df1732970e0) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include "AlarmMgmt.h" #include "Buttons.h" #include "ModePreTreat.h" #include "OperationModes.h" @@ -26,18 +27,33 @@ * @{ */ +// ********** private definitions ********** + +#define BLOOD_PUMP_RECIRC_FLOW_RATE 100 ///< Blood pump flow rate during recirculation in mL/min. +#define DIALYSATE_PUMP_RECIRC_FLOW_RATE 100 ///< Dialysate pump flow rate during recirculation in mL/min. + // ********** private data ********** static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user requests treatment begin. +static BOOL patientConnectionStartReqReceived = FALSE; ///< Flag indicates user requests patient connection. +static BOOL alarmActionStopReceived = FALSE; ///< Flag indicates alarm action stop received. +static BOOL alarmActionResumeReceived = FALSE; ///< Flag indicates alarm action resume received. -static HD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current state of pre-treatment mode state machine. +static HD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current state of pre-treatment mode state machine. +static HD_PRE_TREATMENT_MODE_STATE_T resumePreTreatmentState; ///< Pre-treatment mode state to be resumed when alarm action resume signal receives. // ********** private function prototypes ********** +static void handleAlarmActionStop( void ); +static void handleAlarmActionResume( void ); + static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateStartState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handlePretreatmentPauseState( void ); /*********************************************************************//** * @brief @@ -48,7 +64,12 @@ *************************************************************************/ void initPreTreatmentMode( void ) { + treatStartReqReceived = FALSE; + patientConnectionStartReqReceived = FALSE; + alarmActionStopReceived = FALSE; + alarmActionResumeReceived = FALSE; currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; + resumePreTreatmentState = HD_PRE_TREATMENT_START_STATE; } /*********************************************************************//** @@ -61,14 +82,12 @@ *************************************************************************/ void transitionToPreTreatmentMode( void ) { - treatStartReqReceived = FALSE; - // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); - currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; + initPreTreatmentMode(); } /*********************************************************************//** @@ -117,7 +136,7 @@ break; case HD_PRE_TREATMENT_RECIRCULATE_STATE: - currentPreTreatmentState = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + currentPreTreatmentState = handleRecirculateState(); break; case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: @@ -145,11 +164,12 @@ { BOOL result = FALSE; - if ( MODE_PRET == getCurrentOperationMode() ) + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) { treatStartReqReceived = TRUE; result = TRUE; } + sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected return result; @@ -166,12 +186,101 @@ *************************************************************************/ void signalAlarmActionToPreTreatmentMode( ALARM_ACTION_T action ) { - // TODO - implement + switch( action ) + { + case ALARM_ACTION_STOP: + handleAlarmActionStop(); + break; + + case ALARM_ACTION_RESUME: + handleAlarmActionResume(); + break; + + case ALARM_ACTION_END_TREATMENT: + requestNewOperationMode( MODE_POST ); + break; + + case ALARM_ACTION_ACK: + // Nothing to be done here + break; + + default: + // Ignore + break; + } } /*********************************************************************//** * @brief - * The handleSelfTestNoCartState function handles self-test with no cartrige. + * The handleAlarmActionStop function forwards the alarm action to corresponding + * sub-mode and sets appropriate flag to allow corresponding sub-mode handles. + * @details Inputs: currentPreTreatmentState + * @details Outputs: signals corresponding sub-mode of alarm action + * @return none + *************************************************************************/ +static void handleAlarmActionStop( void ) +{ + switch ( currentPreTreatmentState ) + { + case HD_PRE_TREATMENT_PRIME_STATE: + signalAlarmActionToPrimeMode( ALARM_ACTION_STOP ); + break; + + case HD_PRE_TREATMENT_RECIRCULATE_STATE: + // The corresponding sub-mode will handle the signal + alarmActionStopReceived = TRUE; + break; + + case HD_PRE_TREATMENT_START_STATE: + case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: + case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: + case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: + case HD_PRE_TREATMENT_CART_INSTALL_STATE: + case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: + // do nothing + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handleAlarmActionResume function forwards the alarm action to corresponding + * sub-mode and sets appropriate flag to allow corresponding sub-mode handles. + * @details Inputs: currentPreTreatmentState + * @details Outputs: signals corresponding sub-mode of alarm action + * @return none + *************************************************************************/ +static void handleAlarmActionResume( void ) +{ + switch ( currentPreTreatmentState ) + { + case HD_PRE_TREATMENT_PRIME_STATE: + signalAlarmActionToPrimeMode( ALARM_ACTION_RESUME ); + break; + + case HD_PRE_TREATMENT_RECIRCULATE_STATE: + case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: + case HD_PRE_TREATMENT_SELF_TEST_DRY_STATE: + case HD_PRE_TREATMENT_START_STATE: + case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: + case HD_PRE_TREATMENT_CART_INSTALL_STATE: + case HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE: + // do nothing + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE, (U32)currentPreTreatmentState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handleSelfTestNoCartState function handles self-test with no cartridge. * @details Inputs: none * @details Outputs: home blood pump and dialysate pumps * @return current state (sub-mode) @@ -180,6 +289,13 @@ { // TODO: Prompt user to close door + VALVE_T valve; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + homeValve( valve ); + } + homeBloodPump(); homeDialInPump(); homeDialOutPump(); @@ -191,9 +307,9 @@ /*********************************************************************//** * @brief - * The handleSelfTestDryState function handles dry self-test. + * The handleSelfTestDryState function performs dry self-test. * @details Inputs: none - * @details Outputs: transition to prime sub-mode when blood pump finished homing + * @details Outputs: transition to prime state on user request * @return current state (sub-mode) *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ) @@ -222,16 +338,65 @@ execPrime(); - if ( TRUE == isPrimingPassed() ) + if ( TRUE == isWetSelfTestsPassed() ) { state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); } return state; } /*********************************************************************//** * @brief + * The handleRecirculateStartState function change valves and heater settings + * for recirculation state during pre-treatment mode. + * @details Inputs: none + * @details Outputs: controlled valves and pumps + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateStartState( void ) +{ + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + setValveAirTrap( STATE_CLOSED ); + cmdSetDGActiveReservoir( DG_RESERVOIR_1 ); + cmdStartDGTrimmerHeater(); + + setBloodPumpTargetFlowRate( BLOOD_PUMP_RECIRC_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( DIALYSATE_PUMP_RECIRC_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + signalDialOutPumpHardStop(); + + return HD_PRE_TREATMENT_RECIRCULATE_STATE; +} + +/*********************************************************************//** + * @brief + * The handleRecirculateState function handles blood and dialysate circuits + * recirculation state during pre-treatment mode. + * @details Inputs: none + * @details Outputs: controlled valves and pumps + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + + // TODO Add handler to UI interaction + patientConnectionStartReqReceived = TRUE; + + if ( TRUE == patientConnectionStartReqReceived ) + { + state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handlePatientConnectionState function handles patient connection state * during pre-treatment mode. * @details Inputs: none Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -26,9 +26,12 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "Rinseback.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" +#include "TreatmentEnd.h" +#include "TreatmentRecirc.h" #include "TreatmentStop.h" #include "Utilities.h" #include "Valves.h" @@ -49,9 +52,12 @@ #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 TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the treatment time & state data is published on the CAN bus. +/// Interval (ms/task time) at which the treatment time data is published on the CAN bus. +static const U32 TREATMENT_TIME_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +/// Interval (ms/task time) at which the treatment state data is published on the CAN bus. +static const U32 TREATMENT_STATE_DATA_PUB_INTERVAL = ( 250 / TASK_GENERAL_INTERVAL ); /// Interval (ms/task time) at which updated, valid treatment setting ranges are published on the CAN bus. -#define TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) +static const U32 TREATMENT_SETTINGS_RANGES_PUB_INTERVAL = ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); #define CALC_ELAPSED_TREAT_TIME_IN_SECS() ( treatmentTimeMS / MS_PER_SECOND ) ///< Macro to calculate the elapsed treatment time in seconds. /// Macro to calculate the elapsed treatment time in minutes. @@ -63,6 +69,10 @@ static TREATMENT_STATE_T currentTreatmentState; ///< Current state (sub-mode) of treatment mode. +static BOOL bloodIsPrimed; ///< Flag indicates whether blood-side circuit has been primed with blood. Set FALSE at init and start of rinseback. Set TRUE at end of blood prime. +static BOOL rinsebackDone; ///< Flag indicates whether a rinseback has been completed. Set FALSE at start of blood prime. Set TRUE at init and end of rinseback. +static BOOL treatmentCompleted; ///< Flag indicates whether the treatment has completed. + static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in minutes). static U32 presBloodFlowRate; ///< Prescribed blood flow rate (in mL/min). static U32 presDialysateFlowRate; ///< Prescribed dialysate flow rate (in mL/min). @@ -71,12 +81,18 @@ static U32 treatmentTimeMS; ///< Elapsed treatment time (in ms). static U32 lastTreatmentTimeStamp; ///< Last time elapsed treatment time was recorded (a timestamp in ms). -static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment data broadcast timer counter used to schedule when to transmit data. +static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment time data broadcast timer counter used to schedule when to transmit data. +static U32 treatmentStateBroadcastTimerCtr; ///< Treatment state data broadcast timer counter used to schedule when to transmit data. static U32 treatmentParamsRangesBroadcastTimerCtr; ///< Treatment parameter ranges broadcast timer counter used to schedule when to transmit updated ranges. -// TODO - test code - remove later -static BUTTON_STATE_T lastOffButtonState = BUTTON_STATE_RELEASED; -static BOOL pendingUserEndTreatmentRequest; ///< Flag indicates user has requested treatment end. +static BOOL resumeTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment resume. +static BOOL initiateRinsebackAlarmResponseRequest; ///< Flag indicates user has requested rinseback. +static BOOL endTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment end. +static BOOL rinsebackToStoppedRequest; ///< Flag indicates user has requested return to treatment from rinseback workflow. +static BOOL endTreatmentRequest; ///< Flag indicates user has requested end of treatment from rinseback workflow. +static BOOL bloodPrimeToDialysisRequest; ///< Flag indicates blood prime has completed and time to start dialysis. +static BOOL rinsebackToRecircRequest; ///< Flag indicates user has requested to proceed to re-circulate sub-mode. +static BOOL treatmentEndToRinsebackRequest; ///< Flag indicates user has requested final rinseback. static U32 pendingParamChangesTimer; ///< User required to confirm UF volume change within 1 minute. static F32 pendingUFVolumeChange; ///< An ultrafiltration volume change (mL) is pending user confirmation. @@ -85,10 +101,16 @@ // ********** private function prototypes ********** +static void resetSignalFlags( void ); +static void resetAlarmSignalFlags( void ); static void broadcastTreatmentSettingsRanges( void ); static TREATMENT_STATE_T handleTreatmentStartState( void ); +static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ); static TREATMENT_STATE_T handleTreatmentDialysisState( void ); static TREATMENT_STATE_T handleTreatmentStopState( void ); +static TREATMENT_STATE_T handleTreatmentRinsebackState( void ); +static TREATMENT_STATE_T handleTreatmentRecircState( void ); +static TREATMENT_STATE_T handleTreatmentEndState( void ); /*********************************************************************//** * @brief @@ -101,18 +123,24 @@ { currentTreatmentState = TREATMENT_START_STATE; + bloodIsPrimed = FALSE; + treatmentCompleted = FALSE; + rinsebackDone = TRUE; + treatmentTimeMS = 0; lastTreatmentTimeStamp = 0; - treatmentTimeBroadcastTimerCtr = 0; - treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately + treatmentTimeBroadcastTimerCtr = TREATMENT_TIME_DATA_PUB_INTERVAL; // So we send time data immediately when we begin treatment mode + treatmentStateBroadcastTimerCtr = TREATMENT_STATE_DATA_PUB_INTERVAL; // So we send state data immediately when we begin treatment mode + treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode presTreatmentTimeSecs = 0; presBloodFlowRate = 0; presDialysateFlowRate = 0; presMaxUFVolumeML = 0.0; presUFRate = 0.0; - pendingUserEndTreatmentRequest = FALSE; + resetSignalFlags(); + resetAlarmSignalFlags(); pendingParamChangesTimer = 0; pendingUFVolumeChange = 0.0; @@ -122,6 +150,36 @@ /*********************************************************************//** * @brief + * The resetSignalFlags function resets all non-alarm signal flags. + * @details Inputs: none + * @details Outputs: non-alarm signal flags set to FALSE + * @return none + *************************************************************************/ +static void resetSignalFlags( void ) +{ + rinsebackToStoppedRequest = FALSE; + endTreatmentRequest = FALSE; + rinsebackToRecircRequest = FALSE; + bloodPrimeToDialysisRequest = FALSE; + treatmentEndToRinsebackRequest = FALSE; +} + +/*********************************************************************//** + * @brief + * The resetAlarmSignalFlags function resets all alarm signal flags. + * @details Inputs: none + * @details Outputs: alarm signal flags set to FALSE + * @return none + *************************************************************************/ +static void resetAlarmSignalFlags( void ) +{ + resumeTreatmentAlarmResponseRequest = FALSE; + initiateRinsebackAlarmResponseRequest = FALSE; + endTreatmentAlarmResponseRequest = FALSE; +} + +/*********************************************************************//** + * @brief * The transitionToTreatmentMode function prepares for transition to treatment mode. * @details Inputs: none * @details Outputs: @@ -133,13 +191,12 @@ initTreatmentMode(); initTreatmentReservoirMgmt(); // Initialize treatment sub-modes each time we transition to treatment mode + initBloodPrime(); initDialysis(); initTreatmentStop(); - - // Set user alarm recovery actions allowed in this mode - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); - setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); - setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); + initRinseback(); + initTreatmentRecirc(); + initTreatmentEnd(); } /*********************************************************************//** @@ -156,6 +213,77 @@ /*********************************************************************//** * @brief + * The isTreatmentCompleted function determines whether the treatment has + * completed (indicating treatment duration has elapsed). + * @details Inputs: treatmentCompleted + * @details Outputs: none + * @return treatmentCompleted + *************************************************************************/ +BOOL isTreatmentCompleted( void ) +{ + return treatmentCompleted; +} + +/*********************************************************************//** + * @brief + * The getRinsebackCompleted function determines whether a rinseback has been + * completed (indicating blood-side circuit should be primarily saline). + * @details Inputs: rinsebackDone + * @details Outputs: none + * @return rinsebackDone + *************************************************************************/ +BOOL getRinsebackCompleted( void ) +{ + return rinsebackDone; +} + +/*********************************************************************//** + * @brief + * The setRinsebackIsCompleted function sets that flag indicating whether a + * rinseback has been completed. Call this function with TRUE when rinseback + * operation is completed. Call this function with FALSE at start of blood + * prime operation. + * @details Inputs: none + * @details Outputs: rinsebackDone + * @param flag TRUE if rinseback has been completed, FALSE if not + * @return none + *************************************************************************/ +void setRinsebackIsCompleted( BOOL flag ) +{ + rinsebackDone = flag; +} + +/*********************************************************************//** + * @brief + * The getBloodIsPrimed function determines whether the blood-side circuit + * has been primed with blood (indicating blood-side circuit should be primarily blood). + * @details Inputs: bloodIsPrimed + * @details Outputs: none + * @return bloodIsPrimed + *************************************************************************/ +BOOL getBloodIsPrimed( void ) +{ + return bloodIsPrimed; +} + +/*********************************************************************//** + * @brief + * The setBloodIsPrimed function sets that flag indicating whether the + * blood-side circuit has been primed with blood. Call this function with + * TRUE when blood prime operation is completed. Call this function with + * FALSE at start of treatment or start of rinseback operation. + * @details Inputs: none + * @details Outputs: bloodIsPrimed + * @param flag TRUE if blood side circuit is primed with blood, FALSE if not + * @return none + *************************************************************************/ +void setBloodIsPrimed( BOOL flag ) +{ + bloodIsPrimed = flag; +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToTreatmentMode function executes the given alarm action * as appropriate while in Treatment Mode. * @details Inputs: none @@ -168,52 +296,19 @@ switch( action ) { case ALARM_ACTION_STOP: - switch ( currentTreatmentState ) - { - case TREATMENT_START_STATE: - case TREATMENT_DIALYSIS_STATE: - stopDialysis(); - transitionToTreatmentStop(); - currentTreatmentState = TREATMENT_STOP_STATE; - break; - - case TREATMENT_RINSEBACK_STATE: - // TODO - implement - break; - - case TREATMENT_RECIRC_STATE: - // TODO - implement - break; - - default: - // Ignore - break; - } + // Stop signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: - switch ( currentTreatmentState ) - { - case TREATMENT_STOP_STATE: - lastTreatmentTimeStamp = getMSTimerCount(); - startDialysis(); - transitionToDialysis(); - currentTreatmentState = TREATMENT_DIALYSIS_STATE; - break; - - default: - // Ignore - break; - } + resumeTreatmentAlarmResponseRequest = TRUE; break; case ALARM_ACTION_RINSEBACK: - // TODO - implement + initiateRinsebackAlarmResponseRequest = TRUE; break; case ALARM_ACTION_END_TREATMENT: - // TODO - temporary code - implement - currentTreatmentState = TREATMENT_END_STATE; + endTreatmentAlarmResponseRequest = TRUE; break; case ALARM_ACTION_ACK: @@ -228,6 +323,71 @@ /*********************************************************************//** * @brief + * The signalRinsebackToTreatmentStopped function signals that user wants to return + * to treatment from rinseback workflow. + * @details Inputs: none + * @details Outputs: rinsebackToStoppedRequest + * @return none + *************************************************************************/ +void signalGoToTreatmentStopped( void ) +{ + rinsebackToStoppedRequest = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalGoToRinseback function signals that user wants to perform + * a rinseback operation. + * @details Inputs: none + * @details Outputs: rinsebackRequested + * @return none + *************************************************************************/ +void signalGoToRinseback( void ) +{ + treatmentEndToRinsebackRequest = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalRinsebackToTreatmentEnd function signals that user wants to end the + * treatment from rinseback workflow. + * @details Inputs: none + * @details Outputs: rinsebackToEndTreatmentRequest + * @return none + *************************************************************************/ +void signalEndTreatment( void ) +{ + endTreatmentRequest = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalBloodPrimeToDialysis function signals that blood prime has + * completed and it is time to move on to dialysis. + * @details Inputs: none + * @details Outputs: bloodPrimeToDialysisRequest + * @return none + *************************************************************************/ +void signalBloodPrimeToDialysis( void ) +{ + bloodPrimeToDialysisRequest = TRUE; +} + +/*********************************************************************//** + * @brief + * The signalRinsebackToRecirc function signals that user wants to continue + * on to re-circulate portion of rinseback workflow. + * @details Inputs: none + * @details Outputs: rinsebackToRecircRequest + * @return none + *************************************************************************/ +void signalRinsebackToRecirc( void ) +{ + rinsebackToRecircRequest = TRUE; +} + +/*********************************************************************//** + * @brief * The execTreatmentMode function executes the Treatment Mode state machine. * @details Inputs: currentTreatmentState * @details Outputs: currentTreatmentState @@ -249,6 +409,10 @@ currentTreatmentState = handleTreatmentStartState(); break; + case TREATMENT_BLOOD_PRIME_STATE: + currentTreatmentState = handleTreatmentBloodPrimeState(); + break; + case TREATMENT_DIALYSIS_STATE: currentTreatmentState = handleTreatmentDialysisState(); break; @@ -258,30 +422,32 @@ break; case TREATMENT_RINSEBACK_STATE: - // TODO - implement + currentTreatmentState = handleTreatmentRinsebackState(); break; case TREATMENT_RECIRC_STATE: - // TODO - implement + currentTreatmentState = handleTreatmentRecircState(); break; case TREATMENT_END_STATE: - // TODO - implement - endAirTrapControl(); // TODO - move to appropriate place - requestNewOperationMode( MODE_POST ); // TODO - test code - remove later + currentTreatmentState = handleTreatmentEndState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_STATE, currentTreatmentState ); - currentTreatmentState = TREATMENT_END_STATE; break; } + + // Alarm response request flags should be handled at this point, reset in case not handled in current state + resetAlarmSignalFlags(); + // clear signal flags from sub-modes before calling sub-mode executives + resetSignalFlags(); + // Broadcast treatment data broadcastTreatmentTimeAndState(); broadcastTreatmentSettingsRanges(); - // Call various execs for treatment mode - execTreatmentReservoirMgmt(); + // Manage air trap control execAirTrapMonitorTreatment(); return currentTreatmentState; @@ -290,14 +456,15 @@ /*********************************************************************//** * @brief * The handleTreatmentStartState function handles the Start state of - * the Treatment Mode state machine. + * the Treatment Mode state machine. Should only pass through this state + * once at very beginning of treatment. * @details Inputs: none * @details Outputs: treatmentTimeMS, lastTreatmentTimeStamp * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentStartState( void ) { - TREATMENT_STATE_T result = TREATMENT_DIALYSIS_STATE; + TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; // Initialize treatment time treatmentTimeMS = 0; @@ -309,15 +476,51 @@ presMaxUFVolumeML = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; presUFRate = presMaxUFVolumeML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - // Kick dialysis sub-mode off - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); - startDialysis(); + transitionToBloodPrime(); return result; } /*********************************************************************//** * @brief + * The handleTreatmentBloodPrimeState function handles the blood prime state of + * the Treatment Mode state machine. + * @details Inputs: none + * @details Outputs: none + * @return next treatment mode state + *************************************************************************/ +static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ) +{ + TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; + + setRinsebackIsCompleted( FALSE ); + + // Handle alarm stoppage + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + transitionToTreatmentStop(); + result = TREATMENT_STOP_STATE; + } + else + { + execBloodPrime(); + + // Handle signals from blood prime sub-mode + if ( TRUE == bloodPrimeToDialysisRequest ) + { + lastTreatmentTimeStamp = getMSTimerCount(); + // Kick dialysis sub-mode off + setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + transitionToDialysis(); + result = TREATMENT_DIALYSIS_STATE; + } + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleTreatmentDialysisState function handles the Dialysis state of * the Treatment Mode state machine. * @details Inputs: none @@ -341,29 +544,25 @@ // End treatment if treatment duration has been reached if ( CALC_ELAPSED_TREAT_TIME_IN_SECS() >= presTreatmentTimeSecs ) { + treatmentCompleted = TRUE; + stopDialysis(); + transitionToTreatmentEnd(); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_END_OF_TREATMENT_WARNING, presTreatmentTimeSecs ); result = TREATMENT_END_STATE; } // Otherwise, execute state machine for treatment dialysis sub-mode else { + execTreatmentReservoirMgmt(); execDialysis(); - } - - // TODO - test code - remove later - if ( getOffButtonState() == BUTTON_STATE_PRESSED ) - { - if ( lastOffButtonState == BUTTON_STATE_RELEASED ) + // Handle alarm stoppage + if ( TRUE == doesAlarmStatusIndicateStop() ) { - lastOffButtonState = BUTTON_STATE_PRESSED; stopDialysis(); transitionToTreatmentStop(); result = TREATMENT_STOP_STATE; } } - else - { - lastOffButtonState = BUTTON_STATE_RELEASED; - } return result; } @@ -380,39 +579,148 @@ { TREATMENT_STATE_T result = TREATMENT_STOP_STATE; + // If user requests resumption of treatment, resume treatment + if ( TRUE == resumeTreatmentAlarmResponseRequest ) + { + resumeTreatmentAlarmResponseRequest = FALSE; + if ( TRUE == getBloodIsPrimed() ) + { + lastTreatmentTimeStamp = getMSTimerCount(); + transitionToDialysis(); + result = TREATMENT_DIALYSIS_STATE; + } + else + { + transitionToBloodPrime(); + result = TREATMENT_BLOOD_PRIME_STATE; + } + } + // If user requests rinseback, go to rinseback + else if ( TRUE == initiateRinsebackAlarmResponseRequest ) + { + // TODO - should we block rinseback request if no blood in line (i.e. already did a rinseback)? + transitionToRinseback(); + result = TREATMENT_RINSEBACK_STATE; + } // If user requests treatment end, end treatment - if ( TRUE == pendingUserEndTreatmentRequest ) + else if ( TRUE == endTreatmentAlarmResponseRequest ) { - result = TREATMENT_END_STATE; + requestNewOperationMode( MODE_POST ); } + // Otherwise execute state machine for treatment stop sub-mode else { - // Execute state machine for treatment stop sub-mode execTreatmentStop(); } - // TODO - test code - remove later - if ( getOffButtonState() == BUTTON_STATE_PRESSED ) + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentRinsebackState function executes the rinseback state of the + * Treatment Mode state machine. + * @details Inputs: none + * @details Outputs: treatment rinseback sub-mode executed. + * @return next treatment mode state + *************************************************************************/ +static TREATMENT_STATE_T handleTreatmentRinsebackState( void ) +{ + TREATMENT_STATE_T result = TREATMENT_RINSEBACK_STATE; + + // Execute treatment re-circ sub-mode + execRinseback(); + + // Handle signals from treatment end sub-mode + if ( TRUE == rinsebackToRecircRequest ) { - if ( lastOffButtonState == BUTTON_STATE_RELEASED ) - { - lastOffButtonState = BUTTON_STATE_PRESSED; - lastTreatmentTimeStamp = getMSTimerCount(); - startDialysis(); - transitionToDialysis(); - result = TREATMENT_DIALYSIS_STATE; - } + transitionToTreatmentRecirc(); + result = TREATMENT_RECIRC_STATE; } - else + else if ( TRUE == rinsebackToStoppedRequest ) { - lastOffButtonState = BUTTON_STATE_RELEASED; + transitionToTreatmentStop(); + result = TREATMENT_STOP_STATE; } + else if ( TRUE == endTreatmentRequest ) + { + requestNewOperationMode( MODE_POST ); + } return result; } /*********************************************************************//** * @brief + * The handleTreatmentRecircState function executes the re-circulate state of the + * Treatment Mode state machine. + * @details Inputs: none + * @details Outputs: treatment re-circulate sub-mode executed. + * @return next treatment mode state + *************************************************************************/ +static TREATMENT_STATE_T handleTreatmentRecircState( void ) +{ + TREATMENT_STATE_T result = TREATMENT_RECIRC_STATE; + + // Execute treatment re-circ sub-mode + execTreatmentRecirc(); + + // Handle signals from treatment end sub-mode + if ( TRUE == rinsebackToStoppedRequest ) + { + transitionToTreatmentStop(); + result = TREATMENT_STOP_STATE; + } + else if ( TRUE == endTreatmentRequest ) + { + requestNewOperationMode( MODE_POST ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentEndState function executes the end state of the + * Treatment Mode state machine. + * @details Inputs: none + * @details Outputs: treatment end sub-mode executed. + * @return next treatment mode state + *************************************************************************/ +static TREATMENT_STATE_T handleTreatmentEndState( void ) +{ + TREATMENT_STATE_T result = TREATMENT_END_STATE; + + // Handle final rinseback alarm response from user + if ( TRUE == initiateRinsebackAlarmResponseRequest ) + { + signalTreatmentEndAlarmRinsebackUserAction(); + } + // Handle alarm response from user to end treatment w/o rinseback + else if ( TRUE == endTreatmentAlarmResponseRequest ) + { + signalTreatmentEndAlarmEndTxUserAction(); + } + + // Execute treatment end sub-mode + execTreatmentEnd(); + + // Handle signals from treatment end sub-mode + if ( TRUE == treatmentEndToRinsebackRequest ) + { + transitionToRinseback(); + result = TREATMENT_RINSEBACK_STATE; + } + else if ( TRUE == endTreatmentRequest ) + { + requestNewOperationMode( MODE_POST ); + } + + return result; +} + +/*********************************************************************//** + * @brief * The verifyTreatmentDurationSettingChange function verifies and responds to * the user treatment duration setting change request. * @details Inputs: current operating mode, treatment states and parameters @@ -818,25 +1126,40 @@ U32 elapsedTreatmentTimeInSecs; // Update treatment time stats and broadcast - end treatment if time - elapsedTreatmentTimeInSecs = treatmentTimeMS / MS_PER_SECOND; - if ( elapsedTreatmentTimeInSecs >= presTreatmentTimeSecs ) - { - stopDialysis(); - elapsedTreatmentTimeInSecs = presTreatmentTimeSecs; - currentTreatmentState = TREATMENT_END_STATE; - } - // Broadcast treatment time and state data at interval + elapsedTreatmentTimeInSecs = CALC_ELAPSED_TREAT_TIME_IN_SECS(); + // Broadcast treatment time data at interval if ( ++treatmentTimeBroadcastTimerCtr >= TREATMENT_TIME_DATA_PUB_INTERVAL ) { - U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; - DIALYSIS_STATE_T dialysisState = getDialysisState(); - UF_STATE_T uFState = getUltrafiltrationState(); - SALINE_BOLUS_STATE_T salineBolusInProgress = getSalineBolusState(); + if ( isTreatmentCompleted() != TRUE ) + { + U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; - broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, timeRemaining ); - broadcastTreatmentState( currentTreatmentState, uFState, salineBolusInProgress ); + broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, timeRemaining ); + } + else // If treatment is completed, send zeroes to UI + { + broadcastTreatmentTime( 0, 0, 0 ); + } treatmentTimeBroadcastTimerCtr = 0; } + // Broadcast treatment state data at interval + if ( ++treatmentStateBroadcastTimerCtr >= TREATMENT_STATE_DATA_PUB_INTERVAL ) + { + TREATMENT_STATE_DATA_T payload; + + payload.treatmentSubMode = (U32)currentTreatmentState; + payload.uFState = getUltrafiltrationState(); + payload.salineBolusState = getSalineBolusState(); + payload.txStopState = getCurrentTreatmentStopState(); + payload.bldPrimeState = getCurrentBloodPrimeState(); + payload.rinsebackState = getCurrentRinsebackState(); + payload.txStopState = getCurrentTreatmentRecircState(); + payload.txEndState = getCurrentTreatmentEndState(); + payload.heparinState = HEPARIN_STATE_OFF; // TODO - get Heparin state when implemented + + broadcastTreatmentState( payload ); + treatmentStateBroadcastTimerCtr = 0; + } } /*********************************************************************//** @@ -882,3 +1205,36 @@ treatmentParamsRangesBroadcastTimerCtr = 0; } } + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetTreatmentTimeRemainingOverride function overrides the + * treatment time remaining. + * @details Inputs: presTreatmentTimeSecs, currentTreatmentState + * @details Outputs: treatmentTimeMS + * @param value override treatment time remaining overridden to this (in sec) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetTreatmentTimeRemainingOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( ( TRUE == isTestingActivated() ) && ( value < presTreatmentTimeSecs ) ) + { + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( currentTreatmentState < TREATMENT_END_STATE ) ) + { + result = TRUE; + treatmentTimeMS = ( presTreatmentTimeSecs - value ) * MS_PER_SECOND; + } + } + + return result; +} + +/**@}*/ Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -24,7 +24,7 @@ /** * @defgroup HDTreatmentMode HDTreatmentMode - * @brief TreatmentMode module. + * @brief The HDTreatmentMode module manages the treatment mode state machine and treatment related commands and requests. * * @addtogroup HDTreatmentMode * @{ @@ -47,6 +47,11 @@ U32 uFState; U32 salineBolusState; U32 heparinState; + U32 rinsebackState; + U32 txRecircState; + U32 bldPrimeState; + U32 txEndState; + U32 txStopState; } TREATMENT_STATE_DATA_T; /// Payload record structure for an ultrafiltration volume change confirmation message. @@ -76,14 +81,24 @@ S32 venHighLimit; } PRESSURE_LIMIT_CHANGE_RESPONSE_T; -// ********** private function prototypes ********** +// ********** public function prototypes ********** void initTreatmentMode( void ); // Initialize this module void transitionToTreatmentMode( void ); // Prepares for transition to treatment mode U32 execTreatmentMode( void ); // Execute the treatment mode state machine (call from OperationModes) void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for Treatment mode +void signalGoToTreatmentStopped( void ); // Rinseback or Re-circ sub-mode is signaling to return to treatment stopped sub-mode +void signalGoToRinseback( void ); // Requesting transition to rinseback sub-mode from other sub-mode +void signalEndTreatment( void ); // Requesting transition to post-treatment mode +void signalBloodPrimeToDialysis( void ); // Blood prime sub-mode is signaling to move on to dialysis sub-mode +void signalRinsebackToRecirc( void ); // Rinseback sub-mode is signaling to move on to re-circ sub-mode TREATMENT_STATE_T getTreatmentState( void ); // Determine the current treatment sub-mode (state) +BOOL isTreatmentCompleted( void ); // Determine whether the treatment has completed +BOOL getRinsebackCompleted( void ); // Determine whether a rinseback has been completed +void setRinsebackIsCompleted( BOOL flag ); // Set whether a rinseback has been completed (T blocks rinseback option) +BOOL getBloodIsPrimed( void ); // Determine whether the blood-side circuit of the dialyzer has been primed with blood +void setBloodIsPrimed( BOOL flag ); // Set whether the blood-side circuit of the dialyzer has been primed with blood (F causes Tx start/resume to do blood prime first) void broadcastTreatmentTimeAndState( void ); // Broadcast the times and states of this treatment @@ -93,6 +108,8 @@ BOOL verifyBloodAndDialysateRateSettingsChange( U32 bloodRate, U32 dialRate ); BOOL verifyPressureLimitsChange( PRESSURE_LIMIT_CHANGE_REQUEST_T *data ); +BOOL testSetTreatmentTimeRemainingOverride( U32 value ); + /**@}*/ #endif Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -r8e2cfecc47bb3912078b29513f1717c1567f0071 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 8e2cfecc47bb3912078b29513f1717c1567f0071) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -81,7 +81,8 @@ 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 noNewTreatment; ///< No new treatments may be started even if current treatment is ended + BOOL noNewTreatment; ///< No new treatments may be started even if current treatment is ended + BOOL noDialRecirc; ///< No dialysate re-circulation allowed at this time BOOL usrACKRequired; ///< The user must acknowledge top alarm BOOL lampOn; ///< The alarm lamp is on } COMP_ALARM_STATUS_T; @@ -238,6 +239,11 @@ SW_FAULT_ID_MODE_PRE_TREATMENT_PRIME_INVALID_STATE, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, // 95 + SW_FAULT_ID_BLOOD_PRIME_INVALID_STATE, + SW_FAULT_ID_RINSEBACK_INVALID_STATE, + SW_FAULT_ID_TREATMENT_END_INVALID_STATE, + SW_FAULT_ID_TREATMENT_RECIRC_INVALID_STATE, + SW_FAULT_ID_TREATMENT_STOP_INVALID_STATE, // 100 SW_FAULT_ID_MODE_PRIME_INVALID_ALARM_ACTION, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; @@ -253,9 +259,12 @@ void clearAlarm( ALARM_ID_T alarm ); void clearAlarmCondition( ALARM_ID_T alarm ); void setAlarmUserActionEnabled( ALARM_USER_ACTION_T action, BOOL enabled ); -void signalAlarmSilence( U32 cmd ); +void signalAlarmSilence( ALARM_SILENCE_CMD_T cmd ); void signalAlarmUserActionInitiated( ALARM_USER_ACTION_T action ); BOOL isAlarmActive( ALARM_ID_T alarm ); +BOOL isAnyAlarmActive( void ); +BOOL isDialysateRecircBlocked( void ); +BOOL doesAlarmStatusIndicateStop( void ); ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ); BOOL isAlarmRecoverable( ALARM_ID_T alarm ); void setAlarmAudioVolume( U32 volumeLevel ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -1195,6 +1195,18 @@ handleUFVolumeSetRequest( message ); break; + case MSG_ID_UI_RINSEBACK_CMD: + handlRinsebackCmd( message ); + break; + + case MSG_ID_UI_RECIRC_CMD: + handleTreatmentRecircCmd( message ); + break; + + case MSG_ID_UI_TX_END_CMD: + handleTreatmentEndCmd( message ); + break; + case MSG_ID_DG_COMMAND_RESPONSE: handleDGCmdResp( message ); break; @@ -1255,6 +1267,10 @@ case MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE: handleTestBloodFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: + handleTestTreatmentTimeRemainingOverrideRequest( message ); break; case MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE: @@ -1431,6 +1447,10 @@ handleTestDialOutPumpHomeRequest( message ); break; + case MSG_ID_HD_SET_OP_MODE_REQUEST: + handleTestSetOpModeRequest( message ); + break; + case MSG_ID_SUPER_CLEAR_ALARMS_CMD: handleTestSuperClearAlarmsRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -27,12 +27,15 @@ #include "ModePreTreat.h" #include "ModeStandby.h" #include "ModeTreatment.h" -#include "ModeTreatmentParams.h" -#include "PresOccl.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PresOccl.h" #include "RTC.h" #include "SafetyShutdown.h" #include "SystemComm.h" -#include "SystemCommMessages.h" +#include "SystemCommMessages.h" +#include "TreatmentEnd.h" +#include "TreatmentRecirc.h" #include "Utilities.h" #include "Valves.h" #include "WatchdogMgmt.h" @@ -361,8 +364,8 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; -} - +} + /*********************************************************************//** * @brief * The sendChangeBloodDialysateRateChangeResponse function constructs a change @@ -1086,28 +1089,19 @@ * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: treatment state msg constructed and queued - * @param subMode Current state (sub-mode) of treatment - * @param uFState Current state of ultrafiltration - * @param salineBolusState 1=saline bolus in progress, 0=not, 2=max bolus volume reached + * @param payload Record with treatment state data * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL broadcastTreatmentState( U32 subMode, U32 uFState, U32 salineBolusState ) +BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; - TREATMENT_STATE_DATA_T payload; - // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_TREATMENT_STATE; msg.hdr.payloadLen = sizeof( TREATMENT_STATE_DATA_T ); - payload.treatmentSubMode = subMode; - payload.uFState = uFState; - payload.salineBolusState = salineBolusState; - payload.heparinState = 0; // TODO - add this later - memcpy( payloadPtr, &payload, sizeof( TREATMENT_STATE_DATA_T ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer @@ -1229,6 +1223,124 @@ /***********************************************************************//** * @brief + * The broadcastTreatmentStopData function constructs a treatment stop data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: treatment stop data msg constructed and queued + * @param timeout treatment stop timeout (in sec) + * @param countdown treatment stop timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TREATMENT_STOP_TIMER_DATA; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &timeout, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &countdown, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastRinsebackData function constructs a rinseback data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: rinseback data msg constructed and queued + * @param data rinseback data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RINSEBACK_PROGRESS; + msg.hdr.payloadLen = sizeof( RINSEBACK_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( RINSEBACK_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastRecircData function constructs a treatment re-circ data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: treatment re-circ data msg constructed and queued + * @param timeout re-circulation timeout (in sec) + * @param countdown re-circulation timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRecircData( U32 timeout, U32 countdown ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RECIRC_PROGRESS; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &timeout, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &countdown, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastBloodPrimeData function constructs a blood prime data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: blood prime data msg constructed and queued + * @param data blood prime data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_BLOOD_PRIME_PROGRESS; + msg.hdr.payloadLen = sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief * The broadcastAirTrapData function constructs an HD air trap data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none @@ -1414,7 +1526,7 @@ memcpy( &cmd, payloadPtr, sizeof( U32 ) ); - signalAlarmSilence( cmd ); + signalAlarmSilence( (ALARM_SILENCE_CMD_T)cmd ); } else { @@ -1953,7 +2065,7 @@ sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); } } - + /*********************************************************************//** * @brief * The handleChangeBloodDialysateRateChangeRequest function handles a blood @@ -2072,7 +2184,177 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; +} + +/*********************************************************************//** + * @brief + * The handlRinsebackCmd function handles a rinseback user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handlRinsebackCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalRinsebackUserAction( (REQUESTED_RINSEBACK_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendRinsebackCmdResponse function constructs a rinseback user action + * response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Rinseback command response msg constructed and queued. + * @param accepted T/F - was rinseback user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendRinsebackCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RINSEBACK_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentRecircCmd function handles a treatment re-circ user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTreatmentRecircCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalTreatmentRecircUserAction( (REQUESTED_TREATMENT_RECIRC_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendTreatmentRecircCmdResponse function constructs a treatment re-circulation + * user action response to the UI and queues the msg for transmit on the appropriate + * CAN channel. + * @details Inputs: none + * @details Outputs: Treatment re-circ command response msg constructed and queued. + * @param accepted T/F - was re-circ user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentRecircCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RECIRC_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; } + +/*********************************************************************//** + * @brief + * The handleTreatmentEndCmd function handles a treatment end user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTreatmentEndCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalTreatmentEndUserAction( (REQUESTED_TREATMENT_END_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendTreatmentEndCmdResponse function constructs a treatment end + * user action response to the UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Treatment end command response msg constructed and queued. + * @param accepted T/F - was user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentEndCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TX_END_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} /*********************************************************************//** * @brief @@ -3428,6 +3710,31 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleTestTreatmentTimeRemainingOverrideRequest function handles a treatment + * time remaining override request message. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestTreatmentTimeRemainingOverrideRequest( MESSAGE_T *message ) +{ + U32 payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof(U32) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(U32) ); + result = testSetTreatmentTimeRemainingOverride( payload ); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /*********************************************************************//** * @brief * The handleTestHDSafetyShutdownOverrideRequest function handles a @@ -3556,86 +3863,8 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } -/*********************************************************************//** +/************************************************************************* * @brief - * The handleSetAccelCalibration function handles a request to set - * accelerometer calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetAccelCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(ACCEL_CAL_PAYLOAD_T) ) - { - ACCEL_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(ACCEL_CAL_PAYLOAD_T) ); - result = setAccelCalibration( payload.xOffset, payload.yOffset, payload.zOffset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief - * The handleSetBloodFlowCalibration function handles a request to set - * blood flow calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetBloodFlowCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(LINEAR_F32_CAL_PAYLOAD_T) ) - { - LINEAR_F32_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(LINEAR_F32_CAL_PAYLOAD_T) ); - result = setBloodFlowCalibration( payload.gain, payload.offset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief - * The handleSetDialysateFlowCalibration function handles a request to set - * dialysate flow calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetDialysateFlowCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(LINEAR_F32_CAL_PAYLOAD_T) ) - { - LINEAR_F32_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(LINEAR_F32_CAL_PAYLOAD_T) ); - result = setDialInFlowCalibration( payload.gain, payload.offset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleTestSetTreatmentParameter function handles a request to set * a specific treatment parameter value. * @details Inputs: none @@ -3910,9 +4139,8 @@ * @brief * The handleTestBloodPumpHomeRequest function handles a request to home * the blood pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -3933,9 +4161,8 @@ * @brief * The handleTestDialInPumpHomeRequest function handles a request to home * the dialysate inlet pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -3956,9 +4183,8 @@ * @brief * The handleTestDialOutPumpHomeRequest function handles a request to home * the dialysate outlet pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -3979,9 +4205,8 @@ * @brief * The handleTestSuperClearAlarmsRequest function handles a request to clear * all active alarms. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -3995,8 +4220,31 @@ memcpy( &key, message->payload, sizeof(U32) ); result = testClearAllAlarms( key ); + } - result = TRUE; + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSetOpModeRequest function handles a request to set the + * HD operation mode. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSetOpModeRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + U32 mode; + + memcpy( &mode, message->payload, sizeof(U32) ); + result = testSetOperationMode( (HD_OP_MODE_T)mode ); } // Respond to request Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rc282822f36836a8127f447c8ac5b8a50e851be63 -re23087e0c17f6ea81d60641fdb52121a8dd5a099 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision c282822f36836a8127f447c8ac5b8a50e851be63) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) @@ -21,6 +21,7 @@ #include "HDCommon.h" #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodPrime.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" @@ -30,6 +31,7 @@ #include "MsgQueues.h" #include "NVDataMgmt.h" #include "PresOccl.h" +#include "Rinseback.h" #include "Valves.h" /** @@ -136,9 +138,12 @@ // MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE BOOL sendChangeTreatmentDurationResponse( BOOL accepted, U32 reason, U32 time_min, F32 volume_mL ); +// MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: +void handleTestTreatmentTimeRemainingOverrideRequest( MESSAGE_T *message ); + // MSG_ID_TREATMENT_PARAM_CHANGE_RANGES BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, F32 minUFVol, F32 maxUFVol, U32 minDialRate, U32 maxDialRate ); - + // MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST void handleChangeBloodDialysateRateChangeRequest( MESSAGE_T *message ); @@ -157,6 +162,24 @@ // MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE BOOL sendPressureLimitsChangeResponse( PRESSURE_LIMIT_CHANGE_RESPONSE_T *data ); +// MSG_ID_UI_RINSEBACK_CMD +void handlRinsebackCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RINSEBACK_CMD_RESPONSE +BOOL sendRinsebackCmdResponse( BOOL accepted, U32 rejReason ); + +// MSG_ID_UI_RECIRC_CMD +void handleTreatmentRecircCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RECIRC_CMD_RESPONSE +BOOL sendTreatmentRecircCmdResponse( BOOL accepted, U32 rejReason ); + +// MSG_ID_UI_TX_END_CMD: +void handleTreatmentEndCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RECIRC_CMD_RESPONSE +BOOL sendTreatmentEndCmdResponse( BOOL accepted, U32 rejReason ); + // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS BOOL sendDialysateTempTargetsToDG( F32 primary, F32 trimmer ); @@ -221,7 +244,7 @@ BOOL broadcastTreatmentTime( U32 secsTotTreatment, U32 secsElapsed, U32 secsRemaining ); // MSG_ID_TREATMENT_STATE -BOOL broadcastTreatmentState( U32 subMode, U32 uFState, U32 salineBolusState ); +BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ); // MSG_ID_POWER_OFF_WARNING BOOL broadcastPowerOffWarning( void ); @@ -235,6 +258,18 @@ // MSG_ID_SALINE_BOLUS_DATA BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ); +// MSG_ID_HD_TREATMENT_STOP_TIMER_DATA +BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ); + +// MSG_ID_HD_RINSEBACK_PROGRESS +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ); + +// MSG_ID_HD_RECIRC_PROGRESS +BOOL broadcastRecircData( U32 timeout, U32 countdown ); + +// MSG_ID_HD_BLOOD_PRIME_PROGRESS +BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ); + // MSG_ID_HD_AIR_TRAP_DATA BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel ); @@ -386,15 +421,6 @@ // MSG_ID_HD_ACCEL_SEND_INTERVAL_OVERRIDE: void handleTestHDAccelBroadcastIntervalOverrideRequest( MESSAGE_T *message ); -// MSG_ID_HD_ACCEL_SET_CALIBRATION: -void handleSetAccelCalibration( MESSAGE_T *message ); - -// MSG_ID_HD_BLOOD_FLOW_SET_CALIBRATION: -void handleSetBloodFlowCalibration( MESSAGE_T *message ); - -// MSG_ID_HD_DIALYSATE_FLOW_SET_CALIBRATION: -void handleSetDialysateFlowCalibration( MESSAGE_T *message ); - // MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER void handleTestSetTreatmentParameter( MESSAGE_T *message ); @@ -439,12 +465,9 @@ // MSG_ID_SUPER_CLEAR_ALARMS_CMD void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ); -// MSG_ID_HD_REQUEST_CALIBRATION_DATA -void handleTestHDCalibrationDataRequest( MESSAGE_T *message ); +// MSG_ID_HD_SET_OP_MODE_REQUEST +void handleTestSetOpModeRequest( MESSAGE_T *message ); -// MSG_ID_HD_ERASE_CALIBRATION_DATA -void handleTestEraseHDCalibrationDataRequest( MESSAGE_T *message ); - /**@}*/ #endif