Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -rc3cf7af051c1ee070df90a9c072df16be48f478f -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision c3cf7af051c1ee070df90a9c072df16be48f478f) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -156,6 +156,7 @@ static U32 syringePumpDataPublicationTimerCounter; ///< Used to schedule syringe pump data publication to CAN bus. static U32 syringePumpSpeedCalcTimerCounter; ///< Used to calculate measured rate from change in position over time. static U32 syringePumpRampTimerCtr; ///< Used to track ramp up time. +static HEPARIN_STATE_T heparinDeliveryState; ///< Current state of Heparin delivery. /// Interval (in ms) at which to publish syringe pump data to CAN bus. static OVERRIDE_U32_T syringePumpDataPublishInterval = { SYRINGE_PUMP_DATA_PUB_INTERVAL, SYRINGE_PUMP_DATA_PUB_INTERVAL, 0, 0 }; @@ -175,11 +176,13 @@ static S32 syringePumpPosition1SecAgo; ///< Position recorded at last 1 Hz speed check. static BOOL syringePumpRetractRequested; ///< Flag indicates a retract operation is requested. -static BOOL syringePumpPrimeRequested; ///< Flag indicates plunger seek and Heparin prime operations are requested. +static BOOL syringePumpSeekRequested; ///< Flag indicates a plunger seek operation is requested. +static BOOL syringePumpPrimeRequested; ///< Flag indicates a Heparin prime operation is requested. static BOOL syringePumpBolusRequested; ///< Flag indicates start or resume of a Heparin bolus operation is requested. static BOOL syringePumpContinuousRequested; ///< Flag indicates start or resume of a Heparin continuous delivery operation is requested. static BOOL syringePumpDACVrefSetRequested; ///< Flag indicates request to set DAC Vref for force sensor. +static BOOL syringePumpPositionKnown; ///< Flag indicates we know position from a prior retract to home. static BOOL syringePumpPlungerFound; ///< Flag indicates plunger was found. static BOOL syringePumpPrimeCompleted; ///< Flag indicates prime operation was completed. @@ -230,6 +233,7 @@ void initSyringePump( void ) { syringePumpState = SYRINGE_PUMP_INIT_STATE; + heparinDeliveryState = HEPARIN_STATE_OFF; syringePumpSelfTestState = SYRINGE_PUMP_SELF_TEST_STATE_START; syringePumpSetRate = 0.0; @@ -244,6 +248,7 @@ syringePumpSpeedCalcTimerCounter = 0; syringePumpRampTimerCtr = 0; + syringePumpPositionKnown = FALSE; syringePumpPlungerFound = FALSE; syringePumpPrimeCompleted = FALSE; @@ -263,6 +268,7 @@ static void resetSyringePumpRequestFlags( void ) { syringePumpRetractRequested = FALSE; + syringePumpSeekRequested = FALSE;;; syringePumpPrimeRequested = FALSE; syringePumpBolusRequested = FALSE; syringePumpContinuousRequested = FALSE; @@ -271,6 +277,121 @@ /*********************************************************************//** * @brief + * The userHeparinRequest function handles a command request from the user + * to pause or resume Heparin delivery. + * @details Inputs: none + * @details Outputs: + * @param cmd command from user + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ +BOOL userHeparinRequest( HEPARIN_CMD_T cmd ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + + if ( MODE_TREA == getCurrentOperationMode() ) + { + if ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) + { + if ( HEPARIN_CMD_PAUSE == cmd ) + { + if ( HEPARIN_STATE_DISPENSING == heparinDeliveryState ) + { + accepted = TRUE; + heparinDeliveryState = HEPARIN_STATE_PAUSED; + stopSyringePump(); + } + else + { + rejReason = REQUEST_REJECT_REASON_HEPARIN_PAUSE_INVALID_IN_THIS_STATE; + } + } + else if ( HEPARIN_CMD_RESUME == cmd ) + { + if ( HEPARIN_STATE_PAUSED == heparinDeliveryState ) + { + accepted = TRUE; + heparinDeliveryState = HEPARIN_STATE_DISPENSING; + startHeparinContinuous(); + } + else + { + rejReason = REQUEST_REJECT_REASON_HEPARIN_NOT_PAUSED; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; + } + + sendHeparinCommandResponse( (U32)accepted, (U32)rejReason, (U32)heparinDeliveryState ); + + return accepted; +} + +/*********************************************************************//** + * @brief + * The setHeparinOff function requests Heparin state be set to off - + * indicates syringe pump will not be needed in this treatment. + * @details Inputs: none + * @details Outputs: heparinDeliveryState + * @return none + *************************************************************************/ +void setHeparinOff( void ) +{ + heparinDeliveryState = HEPARIN_STATE_OFF; +} + +/*********************************************************************//** + * @brief + * The setHeparinStopped function requests Heparin state be set to stopped - + * indicates syringe pump will be needed in this treatment. + * @details Inputs: none + * @details Outputs: heparinDeliveryState + * @return none + *************************************************************************/ +void setHeparinStopped( void ) +{ + heparinDeliveryState = HEPARIN_STATE_STOPPED; +} + +/*********************************************************************//** + * @brief + * The setHeparinCompleted function requests Heparin state be set to completed - + * indicates we have entered the Heparin pre-stop period of this treatment. + * @details Inputs: none + * @details Outputs: heparinDeliveryState + * @return none + *************************************************************************/ +void setHeparinCompleted( void ) +{ + heparinDeliveryState = HEPARIN_STATE_COMPLETED; +} + +/*********************************************************************//** + * @brief + * The getHeparinState function returns the current Heparin state. + * @details Inputs: heparinDeliveryState + * @details Outputs: none + * @return heparinDeliveryState + *************************************************************************/ +HEPARIN_STATE_T getHeparinState( void ) +{ + return heparinDeliveryState; +} + +/*********************************************************************//** + * @brief * The stopSyringePump function requests syringe pump be stopped. * @details Inputs: none * @details Outputs: syringePumpSetRate, syringePumpRetractRequested, syringePumpState @@ -281,6 +402,10 @@ syringePumpSetRate = 0.0; setFPGASyringePumpStepToggleTime( SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP ); syringePumpState = SYRINGE_PUMP_OFF_STATE; + if ( ( HEPARIN_STATE_INITIAL_BOLUS == heparinDeliveryState ) || ( HEPARIN_STATE_DISPENSING == heparinDeliveryState ) ) + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } } /*********************************************************************//** @@ -292,7 +417,7 @@ *************************************************************************/ BOOL retractSyringePump( void ) { - if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( FALSE == isSyringeDetected() ) ) + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( FALSE == isSyringeDetected() ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) { syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; syringePumpRetractRequested = TRUE; @@ -303,17 +428,36 @@ /*********************************************************************//** * @brief - * The primeSyringePump function requests plunger seek and prime operations. + * The seekSyringePlunger function requests plunger seek operation. * @details Inputs: syringePumpState - * @details Outputs: syringePumpSetRate, syringePumpBolusRequested + * @details Outputs: syringePumpSetRate, syringePumpSeekRequested * @return TRUE if request accepted, FALSE if not *************************************************************************/ -BOOL primeSyringePump( void ) +BOOL seekSyringePlunger( void ) { if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && - ( TRUE == isSyringePumpHome() ) ) + ( TRUE == syringePumpPositionKnown ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) { syringePumpSetRate = SYRINGE_PUMP_SEEK_RATE; + syringePumpSeekRequested = TRUE; + } + + return syringePumpSeekRequested; +} + +/*********************************************************************//** + * @brief + * The primeSyringePump function requests a prime operation. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpPrimeRequested + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ +BOOL primeSyringePump( void ) +{ + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && + ( heparinDeliveryState != HEPARIN_STATE_OFF ) && ( TRUE == syringePumpPlungerFound ) ) + { + syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; } @@ -337,7 +481,8 @@ // If valid to start a bolus, kick it off if ( ( tgtRate >= MIN_HEPARIN_BOLUS_RATE ) && ( tgtRate <= MAX_HEPARIN_BOLUS_RATE ) && ( FALSE == isSyringePumpHome() ) ) { - if ( ( TRUE == isSyringeDetected() ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) ) + if ( ( TRUE == isSyringeDetected() ) && ( TRUE == syringePumpPrimeCompleted ) && + ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( HEPARIN_STATE_STOPPED == heparinDeliveryState ) ) { syringePumpSetRate = tgtRate; syringePumpBolusRequested = TRUE; @@ -366,7 +511,8 @@ if ( ( flowRate >= MIN_HEPARIN_CONTINUOUS_RATE ) && ( flowRate <= MAX_HEPARIN_CONTINUOUS_RATE ) && ( FALSE == isSyringePumpHome() ) ) { - if ( ( TRUE == isSyringeDetected() ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) ) + if ( ( TRUE == isSyringeDetected() ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && + ( ( ( HEPARIN_STATE_STOPPED == heparinDeliveryState ) || ( HEPARIN_STATE_PAUSED == heparinDeliveryState ) ) ) ) { syringePumpSetRate = flowRate; syringePumpContinuousRequested = TRUE; @@ -772,16 +918,22 @@ { result = SYRINGE_PUMP_RETRACT_STATE; } - else if ( TRUE == syringePumpPrimeRequested ) + else if ( TRUE == syringePumpSeekRequested ) { result = SYRINGE_PUMP_SEEK_STATE; } + else if ( TRUE == syringePumpPrimeRequested ) + { + result = SYRINGE_PUMP_PRIME_STATE; + } else if ( TRUE == syringePumpBolusRequested ) { + heparinDeliveryState = HEPARIN_STATE_INITIAL_BOLUS; result = SYRINGE_PUMP_HEP_BOLUS_STATE; } else if ( TRUE == syringePumpContinuousRequested ) { + heparinDeliveryState = HEPARIN_STATE_DISPENSING; result = SYRINGE_PUMP_HEP_CONTINUOUS_STATE; } else if ( TRUE == syringePumpDACVrefSetRequested ) @@ -840,6 +992,7 @@ syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); syringePumpPosition.data = 0; syringePumpVolumeStartPosition = 0; + syringePumpPositionKnown = TRUE; syringePumpVolumeDelivered.data = 0.0; syringePumpPlungerFound = FALSE; syringePumpPrimeCompleted = FALSE; @@ -875,14 +1028,10 @@ // Is plunger contact detected? if ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) { + stopPump = TRUE; syringePumpPlungerFound = TRUE; syringePumpVolumeDelivered.data = 0.0; syringePumpVolumeStartPosition = syringePumpPosition.data; - syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; - // Calculate target FPGA rate from set rate in mL/hr converted to microstep toggle interval in uSec - calcStepperToggleTimeForTargetRate( syringePumpSetRate ); - setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); - result = SYRINGE_PUMP_PRIME_STATE; } // Has syringe been removed? @@ -1011,18 +1160,21 @@ // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check volume vs. safety volume - stopPump = checkVolumeVsSafetyVolume( stopPump, SYRINGE_PUMP_VOLUME_CHECK_MARGIN ); - // Check for occlusion stopPump = checkOcclusionOrEmpty( stopPump ); - // Check for commanded vs. meas. rate - stopPump = checkMaxMeasRate( stopPump, SYRINGE_PUMP_RATE_CHECK_MARGIN ); + // Check if time to stop Heparin delivery + // TODO - implement pre-stop check // Check position > max travel stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); + // Check for commanded vs. meas. rate + stopPump = checkMaxMeasRate( stopPump, SYRINGE_PUMP_RATE_CHECK_MARGIN ); + + // Check volume vs. safety volume + stopPump = checkVolumeVsSafetyVolume( stopPump, SYRINGE_PUMP_VOLUME_CHECK_MARGIN ); + // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1079,6 +1231,7 @@ if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) { + heparinDeliveryState = HEPARIN_STATE_EMPTY; SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, force ) } else @@ -1133,6 +1286,7 @@ if ( pos > ( SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ) ) { result = TRUE; + heparinDeliveryState = HEPARIN_STATE_EMPTY; SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, getSyringePumpForceV() ) } else if ( pos > maxPos ) @@ -1306,9 +1460,11 @@ data.syringePumpPosition = getSyringePumpPosition(); data.syringePumpSetRate = syringePumpSetRate; data.syringePumpState = (U32)syringePumpState; + data.heparinDeliveryState = (U32)heparinDeliveryState; data.syringePumpVolumeDelivered = getSyringePumpVolumeDelivered(); - broadcastSyringePumpData( data ); + broadcastSyringePumpData( data ); + broadcastHeparinData( data.syringePumpVolumeDelivered ); syringePumpDataPublicationTimerCounter = 0; } } @@ -1411,7 +1567,11 @@ result = retractSyringePump(); break; - case SYRINGE_PUMP_OP_SEEK_AND_PRIME: + case SYRINGE_PUMP_OP_SEEK: + result = seekSyringePlunger(); + break; + + case SYRINGE_PUMP_OP_PRIME: result = primeSyringePump(); break; Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -r6f9114398c3d37f2b17fff8fdb7f2b2c9bfc6a4b -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 6f9114398c3d37f2b17fff8fdb7f2b2c9bfc6a4b) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -221,14 +221,17 @@ BOOL signalUserCancelTreatment( void ) { BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; if ( MODE_TPAR == getCurrentOperationMode() ) { treatmentCancelled = TRUE; result = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; } - sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected + sendInitiateTreatmentResponseMsg( result, rejReason ); + return result; } Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -rbb80dbac26147ab08413efa91007f7ffed43c38f -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision bb80dbac26147ab08413efa91007f7ffed43c38f) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -11,7 +11,7 @@ * @date (last) 28-Jan-2021 * * @author (original) Quang Nguyen -* @date (original) 28-Jan-2021s +* @date (original) 28-Jan-2021 * ***************************************************************************/ @@ -21,8 +21,11 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "FPGA.h" +#include "ModeTreatmentParams.h" #include "PresOccl.h" #include "SelfTests.h" +#include "SyringePump.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" @@ -41,24 +44,30 @@ #define BLOOD_LEAK_NORMAL_OPERATION 0x0 ///< Return blood leak to normal operation. #define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. +#define NORMALIZED_PRESSURE_SELF_TEST_TIME ( 2 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize in ms. #define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -50.0 ///< Arterial pressure low limit after running blood pump. #define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 400 ///< Venous pressure high limit after running blood pump. -#define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). +#define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 5.0 ///< Difference in pressure readings after return to normal state tolerance (in mmHg). #define DIP_FLOW_RATE_SETUP_ML_MIN 100 ///< Dialysate inlet pump flow rate during the setup for wet self-test. #define DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN 100 ///< Dialysate inlet pump flow rate during the first displacement in wet self-test. -#define DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 300 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. +#define DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN 600 ///< Dialysate inlet pump flow rate during the second displacement in wet self-test. -#define WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML 1500 ///< Setup volume for reservoir one before wet self-test in ml. -#define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100 ///< Target of first displacement volume in ml. -#define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 300 ///< Target of second displacement volume in ml. -#define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 5 ///< Tolerance on integrated volume in percentage. +#define WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML 1200.0 ///< Setup volume for reservoir one before wet self-test in ml. +#define WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML 100.0 ///< Target of first displacement volume in ml. +#define WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML 600.0 ///< Target of second displacement volume in ml. +#define WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE 5.0 ///< Tolerance on integrated volume in percentage. #define WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G 1.5 ///< Tolerance in the load cell readings of the displacement in grams. #define WET_SELF_TEST_DISPLACEMENT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Time to displace dialysate in wet self-test in ms. #define RESERVOIR_SETTLE_TIME_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time allotted for reservoir to settle in ms. +#define MAX_NO_CARTRIDGE_SELF_TEST_TIME SEC_PER_MIN ///< Maximum no cartridge self-test time (in seconds). +#define MAX_DRY_SELF_TEST_TIME ( 3 * SEC_PER_MIN ) ///< Maximum dry self-test time (in seconds). + +#define SELF_TEST_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND ) ///< Interval (ms/task time) at which self-test time data is published on the CAN bus. + /// Multiplier to conver flow (mL/min) into volume (mL) for period of general task interval. static const F32 SELF_TEST_FLOW_INTEGRATOR = ( ( 1.0 * TASK_GENERAL_INTERVAL ) / ( SEC_PER_MIN * MS_PER_SECOND ) ); @@ -67,7 +76,7 @@ { WET_SELF_TESTS_START_STATE = 0, ///< Wet self-tests starting state. WET_SELF_TESTS_SETUP_STATE, ///< Setup reservoirs for wet self-tests. - WET_SELF_TESTS_BUBBLE_DETECTOR_STATE, ///< Bubble detectors wet self-tests state. + WET_SELF_TESTS_PRIME_CHECK_STATE, ///< Prime check wet self-tests state, checks for primed patient lines. WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE, ///< Setup valve and start dialysate pump for first displacement. WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE, ///< Fill reservoir 2 with 100 mL of dialysate from reservoir 1 state. WET_SELF_TESTS_FIRST_DISPLACEMENT_VERIFY_STATE, ///< After first displacement completed verify state. @@ -81,14 +90,13 @@ // ********** private data ********** -static BOOL noCartSelfTestsResult; ///< Result of no cartridge self-tests. static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; ///< Current state of the no cartridge self-tests state machine. static U32 runPumpStartTime; ///< Beginning time when pumps start running -static BOOL hasPumpsStarted; ///< Flag indicates if pumps have started running for self-test. +static BOOL havePumpsStarted; ///< Flag indicates pumps have started running for self-test. -static BOOL drySelfTestsResult; ///< Result of dry self-tests. static DRY_SELF_TESTS_STATE_T currentDrySelfTestsState; ///< Current state of the dry self-tests state machine. static U32 pressureSelfTestBloodPumpRunStartTime; ///< Pressure dry self-test blood pump runs start time. +static U32 pressureSelfTestNormalizedStartTime; ///< Normalized pressure dry self-test start time. static F32 previousNormalArterialPressure; ///< Holds the previous normal arterial pressure reading. static F32 previousNormalVenousPressure; ///< Holds the previous normal venous pressure reading. @@ -101,8 +109,12 @@ static F32 setupDisplacementVolume; ///< Hold the setup displacement volume to get reservoir one to target volume. static BOOL isValvesSettingSent; ///< Flag indicates valve setting change has been send to DG. +static U32 selfTestStartTime; ///< Starting time of self-test (in ms). +static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). + +static BOOL useHeparin; ///< Flag indicates the user of heparin. + static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. -static BOOL selfTestsStopRequested; ///< Flag indicates alarm requesting to stop self-test. // ********** private function prototypes ********** @@ -112,21 +124,24 @@ static void handleNoCartSelfTestsStopRequest( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestsWaitForClosedDoor( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestPumpsState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( void ); +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStartHomingState( void ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ); -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ); static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStoppedState( void ); static void handleDrySelfTestsStopRequest( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestWaitForDoorCloseState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsSetupState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); static void handleWetSelfTestsStopRequest( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); -static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( SELF_TEST_STATUS_T *result ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( SELF_TEST_STATUS_T *result ); @@ -144,6 +159,8 @@ *************************************************************************/ void initSelfTests( void ) { + selfTestStartTime = 0; + selfTestPreviousPublishDataTime = 0; } /*********************************************************************//** @@ -161,19 +178,6 @@ /*********************************************************************//** * @brief - * The signalStopPrime function signals self-tests to stop when an - * alarm with stop property has been triggered. - * @details Inputs: none - * @details Outputs: primeStopRequested - * @return none - *************************************************************************/ -void signalStopSelfTests( void ) -{ - selfTestsStopRequested = TRUE; -} - -/*********************************************************************//** - * @brief * The resetSelfTestsFlags function resets all self-tests signal flags. * @details Inputs: none * @details Outputs: signal flags set to FALSE @@ -182,7 +186,6 @@ static void resetSelfTestsFlags( void ) { selfTestsResumeRequested = FALSE; - selfTestsStopRequested = FALSE; } /*********************************************************************//** @@ -210,10 +213,15 @@ *************************************************************************/ void transitionToNoCartSelfTests( void ) { - noCartSelfTestsResult = FALSE; + F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; runPumpStartTime = 0; - hasPumpsStarted = FALSE; + havePumpsStarted = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -223,61 +231,43 @@ * The execNoCartSelfTests function executes the no cartridge self-tests * state machine. * @details Inputs: currentNoCartSelfTestsState - * @details Outputs: currentNoCartSelfTestsState, noCartSelfTestsResult + * @details Outputs: currentNoCartSelfTestsState * @return none *************************************************************************/ void execNoCartSelfTests( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - // execute no cartridge self-tests state machine switch ( currentNoCartSelfTestsState ) { case NO_CART_SELF_TESTS_START_STATE: -#ifdef SKIP_SELF_TESTS - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; -#else currentNoCartSelfTestsState = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; -#endif break; case NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestsWaitForClosedDoor(); break; case NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE: - result = execPresOcclTest(); - - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE; - } + execPresOcclTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_BLOOD_FLOW_METERS_STATE: - result = execBloodFlowTest(); - - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE; - } + execBloodFlowTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE; break; case NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE: - result = execDialInFlowTest(); - - if ( SELF_TEST_STATUS_PASSED == result ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_PUMPS_STATE; - } + execDialInFlowTest(); + currentNoCartSelfTestsState = NO_CART_SELF_TESTS_PUMPS_STATE; break; case NO_CART_SELF_TESTS_PUMPS_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestPumpsState(); break; case NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE: - currentNoCartSelfTestsState = handleNoCartSelfTestLeakDetectorsState( &result ); + currentNoCartSelfTestsState = handleNoCartSelfTestLeakDetectorsState(); break; case NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE: @@ -286,27 +276,18 @@ break; case NO_CART_SELF_TESTS_START_HOMING_STATE: - // TODO: Implement self tests - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; + currentNoCartSelfTestsState = handleNoCartSelfTestStartHomingState(); break; case NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestHomeValvesAndPumpState(); break; - case NO_CART_SELF_TESTS_HOME_IDLE_STATE: - if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) - { - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_COMPLETE_STATE; - } - break; - case NO_CART_SELF_TESTS_STOPPED_STATE: currentNoCartSelfTestsState = handleNoCartSelfTestStoppedState(); break; case NO_CART_SELF_TESTS_COMPLETE_STATE: - noCartSelfTestsResult = TRUE; break; default: @@ -321,22 +302,27 @@ // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); - if ( SELF_TEST_STATUS_FAILED == result ) + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_NO_CART_SELF_TEST_FAILURE, currentNoCartSelfTestsState ); + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + broadcastNoCartSelfTestTime( MAX_NO_CARTRIDGE_SELF_TEST_TIME, ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); } } /*********************************************************************//** * @brief - * The isNoCartSelfTestsPassed function returns the status of no cartridge self-tests. - * @details Inputs: none + * The getNoCartSelfTestsState function returns the current state of no + * cartridge self-tests sub-mode. + * @details Inputs: currentNoCartSelfTestsState * @details Outputs: none - * @return TRUE if no cartridge self-tests passed, otherwise FALSE + * @return current no cartridge self-tests state *************************************************************************/ -BOOL isNoCartSelfTestsPassed( void ) +U32 getNoCartSelfTestsState( void ) { - return noCartSelfTestsResult; + return (U32)currentNoCartSelfTestsState; } /*********************************************************************//** @@ -349,11 +335,17 @@ *************************************************************************/ void transitionToDrySelfTests() { - drySelfTestsResult = FALSE; + F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ); currentDrySelfTestsState = DRY_SELF_TESTS_START_STATE; pressureSelfTestBloodPumpRunStartTime = 0; + pressureSelfTestNormalizedStartTime = 0; previousNormalArterialPressure = 0.0; previousNormalVenousPressure = 0.0; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -362,7 +354,7 @@ * @brief * The execDrySelfTests function executes the dry self-tests state machine. * @details Inputs: currentDrySelfTestsState - * @details Outputs: currentDrySelfTestsState, drySelfTestsResult + * @details Outputs: currentDrySelfTestsState * @return none *************************************************************************/ void execDrySelfTests( void ) @@ -373,8 +365,13 @@ switch ( currentDrySelfTestsState ) { case DRY_SELF_TESTS_START_STATE: -#ifdef SKIP_SELF_TESTS - currentDrySelfTestsState = DRY_SELF_TESTS_COMPLETE_STATE; +#ifdef SKIP_DRY_SELF_TESTS + // TODO: Remove once dry self-test is ready to use + if ( TRUE == useHeparin ) + { + primeSyringePump(); + } + currentDrySelfTestsState = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; #else currentDrySelfTestsState = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; #endif @@ -384,9 +381,18 @@ currentDrySelfTestsState = handleDrySelfTestWaitForDoorCloseState(); break; + case DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE: + currentDrySelfTestsState = handleDrySelfTestUsedCartridgeCheckState(); + break; + case DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE: if ( SELF_TEST_STATUS_PASSED == execPresOcclDryTest() ) { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_OPEN ); currentDrySelfTestsState = DRY_SELF_TESTS_PRESSURE_SENSORS_SETUP_STATE; } break; @@ -403,12 +409,15 @@ currentDrySelfTestsState = handleDrySelfTestPressureSensorsNormalState( &result ); break; + case DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); + break; + case DRY_SELF_TESTS_STOPPED_STATE: currentDrySelfTestsState = handleDrySelfTestStoppedState(); break; case DRY_SELF_TESTS_COMPLETE_STATE: - drySelfTestsResult = TRUE; break; default: @@ -427,18 +436,27 @@ { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_DRY_SELF_TEST_FAILURE, currentDrySelfTestsState ); } + + // Publish current self-test time data + if ( calcTimeSince( selfTestPreviousPublishDataTime ) >= SELF_TEST_TIME_DATA_PUB_INTERVAL ) + { + U32 const elapsedSelfTestTimeInSecs = calcTimeSince( selfTestStartTime ) / MS_PER_SECOND; + + selfTestPreviousPublishDataTime = getMSTimerCount(); + broadcastDrySelfTestTime( MAX_DRY_SELF_TEST_TIME, ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); + } } /*********************************************************************//** * @brief - * The isDrySelfTestsPassed function returns the status of dry self-tests. - * @details Inputs: none + * The getDrySelfTestsState function returns the current state of dry self-tests sub-mode. + * @details Inputs: currentDrySelfTestsState * @details Outputs: none - * @return TRUE if dry self-tests passed, otherwise FALSE + * @return current dry self-tests state *************************************************************************/ -BOOL isDrySelfTestsPassed( void ) +U32 getDrySelfTestsState( void ) { - return drySelfTestsResult; + return (U32)currentDrySelfTestsState; } /*********************************************************************//** @@ -457,6 +475,8 @@ displacementStartTime = 0; fmdIntegratedVolume = 0.0; isValvesSettingSent = FALSE; + selfTestStartTime = getMSTimerCount(); + selfTestPreviousPublishDataTime = getMSTimerCount(); resetSelfTestsFlags(); } @@ -483,8 +503,8 @@ currentWetSelfTestsState = handleWetSelfTestSetupState(); break; - case WET_SELF_TESTS_BUBBLE_DETECTOR_STATE: - currentWetSelfTestsState = handleWetSelfTestBubbleDetectorsState( &result ); + case WET_SELF_TESTS_PRIME_CHECK_STATE: + currentWetSelfTestsState = handleWetSelfTestPrimeCheckState( &result ); break; case WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE: @@ -559,12 +579,11 @@ *************************************************************************/ static void handleNoCartSelfTestsStopRequest( void ) { - if ( TRUE == selfTestsStopRequested ) + if ( TRUE == doesAlarmStatusIndicateStop() ) { - setupForSelfTestsStop(); - currentNoCartSelfTestsState = NO_CART_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; + + setupForSelfTestsStop(); } } @@ -584,6 +603,7 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); + // TODO: Use appropriate sensor driver if ( STATE_CLOSED == getFPGADoorState() ) { state = NO_CART_SELF_TESTS_OCCLUSION_SENSORS_STATE; @@ -604,9 +624,9 @@ { NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_PUMPS_STATE; - if ( FALSE == hasPumpsStarted ) + if ( FALSE == havePumpsStarted ) { - hasPumpsStarted = TRUE; + havePumpsStarted = TRUE; setBloodPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( PUMP_SELF_TEST_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); @@ -620,6 +640,7 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); + // TODO: Use appropriate sensor driver setFPGASensorTest( BLOOD_LEAK_SELF_TEST_SET ); state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; } @@ -629,14 +650,42 @@ /*********************************************************************//** * @brief - * The handleNoCartSelfTestHomeValvesAndPumpState function homes all valves - * and pumps. + * The handleNoCartSelfTestLeakDetectorsState function verify leak detectors status. * @details Inputs: none * @details Outputs: none + * @param result self-test result * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( void ) { + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; + // TODO: Use appropriate sensor driver + BOOL const bloodLeakDetector = getFPGABloodLeakDetectorStatus(); + + if ( TRUE == bloodLeakDetector ) + { + // TODO: Use appropriate sensor driver + setFPGASensorTest( BLOOD_LEAK_NORMAL_OPERATION ); + state = NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE; + } + else + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE, (U32)bloodLeakDetector ); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleNoCartSelfTestStartHomingState function start homing process for + * all the valves and pumps. + * @details Inputs: none + * @details Outputs: Valves and pumps started homing + * @return the next state of no cartridge self-tests state machine + *************************************************************************/ +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestStartHomingState( void ) +{ VALVE_T valve; for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) @@ -648,30 +697,30 @@ homeDialInPump(); homeDialOutPump(); - return NO_CART_SELF_TESTS_HOME_IDLE_STATE; + if ( TRUE == useHeparin ) + { + retractSyringePump(); + } + + return NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; } /*********************************************************************//** * @brief - * The handleNoCartSelfTestLeakDetectorsState function verify leak detectors status. + * The handleNoCartSelfTestHomeValvesAndPumpState function homes all valves + * and pumps. * @details Inputs: none * @details Outputs: none - * @param result self-test result * @return the next state of no cartridge self-tests state machine *************************************************************************/ -static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestLeakDetectorsState( SELF_TEST_STATUS_T *result ) +static NO_CART_SELF_TESTS_STATE_T handleNoCartSelfTestHomeValvesAndPumpState( void ) { - NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; + NO_CART_SELF_TESTS_STATE_T state = NO_CART_SELF_TESTS_HOME_VALVES_AND_PUMPS_STATE; - if ( TRUE == getFPGABloodLeakDetectorStatus() ) + if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) && ( FALSE == isBloodPumpRunning() ) ) { - setFPGASensorTest( BLOOD_LEAK_NORMAL_OPERATION ); - state = NO_CART_SELF_TESTS_BOARD_TEMPERATURE_STATE; + state = NO_CART_SELF_TESTS_COMPLETE_STATE; } - else - { - *result = SELF_TEST_STATUS_FAILED; - } return state; } @@ -691,6 +740,7 @@ if ( TRUE == selfTestsResumeRequested ) { selfTestsResumeRequested = FALSE; + havePumpsStarted = TRUE; state = NO_CART_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } @@ -707,19 +757,18 @@ *************************************************************************/ static void handleDrySelfTestsStopRequest( void ) { - if ( TRUE == selfTestsStopRequested ) + if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForSelfTestsStop(); currentDrySelfTestsState = DRY_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; } } /*********************************************************************//** * @brief - * The handleDrySelfTestWaitForDoorCloseState function verify no fluid is detected - * by bubble detectors. + * The handleDrySelfTestWaitForDoorCloseState function makes sure door is + * closed before starting self-tests. * @details Inputs: none * @details Outputs: none * @return the next state of dry self-tests state machine @@ -728,8 +777,35 @@ { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; + // TODO: Use appropriate sensor driver if ( STATE_CLOSED == getFPGADoorState() ) { + state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestUsedCartridgeCheckState function verify no fluid is + * detected by bubble detectors to ensure the cartridge is new. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestUsedCartridgeCheckState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + + // TODO: Use appropriate sensor driver + BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); + BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); + + if ( ( TRUE == isADADetectedAir ) && ( TRUE == isADVDetectedAir ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && + ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) + { state = DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE; } @@ -772,16 +848,20 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; - F32 const arterialPressure = getMeasuredArterialPressure(); F32 const venousPressure = getMeasuredVenousPressure(); + + // End the test when reaching target pressure or time out if ( ( TRUE == didTimeout( pressureSelfTestBloodPumpRunStartTime, BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ) ) || ( ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG >= arterialPressure ) || ( VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG <= venousPressure ) ) { + // Test pass when reading positive arterial pressure and negative venous pressure if ( ( arterialPressure < 0) && ( venousPressure > 0 ) ) { + signalBloodPumpHardStop(); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - setValveAirTrap( STATE_CLOSED ); + setValveAirTrap( STATE_OPEN ); + pressureSelfTestNormalizedStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; } else @@ -806,16 +886,50 @@ { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; - F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure); - F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure); + F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure ); + F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure ); - if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_TIME ) ) { - state = DRY_SELF_TESTS_COMPLETE_STATE; + if ( ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + { + if ( TRUE == useHeparin ) + { + primeSyringePump(); + } + state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + } + else + { + *result = SELF_TEST_STATUS_FAILED; + } } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDrySelfTestSyringePumpPrimeState function handles the prime + * operation for syringe pump. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; + + if ( TRUE == useHeparin ) + { + if ( TRUE == isSyringePumpPrimed() ) + { + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + } else { - *result = SELF_TEST_STATUS_FAILED; + state = DRY_SELF_TESTS_COMPLETE_STATE; } return state; @@ -852,12 +966,11 @@ *************************************************************************/ static void handleWetSelfTestsStopRequest( void ) { - if ( TRUE == selfTestsStopRequested ) + if ( TRUE == doesAlarmStatusIndicateStop() ) { setupForSelfTestsStop(); currentWetSelfTestsState = WET_SELF_TESTS_STOPPED_STATE; - selfTestsStopRequested = FALSE; } } @@ -879,20 +992,18 @@ if ( FALSE == isValvesSettingSent ) { + isValvesSettingSent = TRUE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + if ( resOneWeight > WET_SELF_TEST_RESERVOIR_ONE_SETUP_VOLUME_ML ) { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); cmdChangeDGValveSetting( DG_VALVE_SETTING_R1_TO_R2 ); } else { - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); cmdChangeDGValveSetting( DG_VALVE_SETTING_R2_TO_R1 ); } - - isValvesSettingSent = TRUE; } if ( ( TRUE == isValvesSettingSent ) && ( TRUE == getDGCommandResponse( DG_CMD_VALVE_SETTING, &cmdResp ) ) ) @@ -903,15 +1014,11 @@ if ( FALSE == cmdResp.rejected ) { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SETUP_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_SETUP_STATE; } } -#ifdef SKIP_SELF_TESTS - state = WET_SELF_TESTS_COMPLETE_STATE; -#endif - return state; } @@ -932,25 +1039,26 @@ if ( setupDisplacementVolume <= 0 ) { signalDialInPumpHardStop(); - state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + state = WET_SELF_TESTS_PRIME_CHECK_STATE; } return state; } /*********************************************************************//** * @brief - * The handleWetSelfTestBubbleDetectorsState function handles the wet self-test - * for bubble detectors. - * @details Inputs: Arterial and venous air bubble status + * The handleWetSelfTestPrimeCheckState function checks arterial and venous + * lines to make sure they are primed. + * @details Inputs: Arterial and venous bubble detectors status * @details Outputs: Test pass/fail * @param result self-test result * @return the next state of wet self-tests state machine *************************************************************************/ -static WET_SELF_TESTS_STATE_T handleWetSelfTestBubbleDetectorsState( SELF_TEST_STATUS_T *result ) +static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( SELF_TEST_STATUS_T *result ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BUBBLE_DETECTOR_STATE; + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_PRIME_CHECK_STATE; + // TODO: Use appropriate sensor driver BOOL const isADADetectedAir = getFPGAArterialAirBubbleStatus(); BOOL const isADVDetectedAir = getFPGAVenousAirBubbleStatus(); @@ -1000,7 +1108,7 @@ { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_FIRST_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_FIRST_DISPLACEMENT_STATE; } } @@ -1048,9 +1156,9 @@ if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) { - F32 const resOneDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ] ); - F32 const resTwoDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ] ); - F32 const integratedVolumeToTargetPercent = 1 - ( fmdIntegratedVolume / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ); + F32 const resOneDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_1 ] - getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); + F32 const resTwoDiffAfterDisplacement = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ]; + F32 const integratedVolumeToTargetPercent = fabs( 1.0 - ( fmdIntegratedVolume / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ) ); if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE ) ) @@ -1079,7 +1187,7 @@ WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_SECOND_DISPLACEMENT_SETUP_STATE; DG_CMD_RESPONSE_T cmdResp; - if ( ( FALSE == isValvesSettingSent ) && ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) ) + if ( FALSE == isValvesSettingSent ) { reservoirVolume[ DG_RESERVOIR_1 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ); reservoirVolume[ DG_RESERVOIR_2 ] = getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); @@ -1099,7 +1207,7 @@ { setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SECOND_DISPLACEMENT_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); displacementStartTime = getMSTimerCount(); - fmdIntegratedVolume = 0; + fmdIntegratedVolume = 0.0; state = WET_SELF_TESTS_SECOND_DISPLACEMENT_STATE; } } @@ -1148,9 +1256,9 @@ if ( TRUE == didTimeout( settleStartTime, RESERVOIR_SETTLE_TIME_MS ) ) { - F32 const resOneDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ] ); - F32 const resTwoDiffAfterDisplacement = fabs( getReservoirWeightLargeFilter( DG_RESERVOIR_2 ) - reservoirVolume[ DG_RESERVOIR_2 ] ); - F32 const integratedVolumeToTargetPercent = 1 - ( fmdIntegratedVolume / WET_SELF_TEST_FIRST_DISPLACEMENT_TARGET_VOLUME_ML ); + F32 const resOneDiffAfterDisplacement = getReservoirWeightLargeFilter( DG_RESERVOIR_1 ) - reservoirVolume[ DG_RESERVOIR_1 ]; + F32 const resTwoDiffAfterDisplacement = reservoirVolume[ DG_RESERVOIR_2 ] - getReservoirWeightLargeFilter( DG_RESERVOIR_2 ); + F32 const integratedVolumeToTargetPercent = fabs( 1.0 - ( fmdIntegratedVolume / WET_SELF_TEST_SECOND_DISPLACEMENT_TARGET_VOLUME_ML ) ); if ( ( fabs( resOneDiffAfterDisplacement - resTwoDiffAfterDisplacement) <= WET_SELF_TEST_DISPLACEMENT_TOLERANCE_G ) && ( integratedVolumeToTargetPercent <= WET_SELF_TEST_INTEGRATED_VOLUME_TOLERANCE ) ) Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rbb80dbac26147ab08413efa91007f7ffed43c38f -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision bb80dbac26147ab08413efa91007f7ffed43c38f) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -191,7 +191,12 @@ void checkInFromDG( void ) { dgIsCommunicating = TRUE; - timeOfLastDGCheckIn = getMSTimerCount(); + timeOfLastDGCheckIn = getMSTimerCount(); + + if ( TRUE == isAlarmActive( ALARM_ID_DG_COMM_TIMEOUT ) ) + { + clearAlarm( ALARM_ID_DG_COMM_TIMEOUT ); + } } /*********************************************************************//** @@ -933,6 +938,7 @@ } if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) { + activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); dgIsCommunicating = FALSE; } } @@ -1179,8 +1185,8 @@ handleTreatmentParametersFromUI( message ); break; - case MSG_ID_UI_START_TREATMENT: - handleUIStartTreatmentMsg( message ); + case MSG_ID_UI_INITIATE_TREATMENT_REQUEST: + handleInitiateTreatmentRequest( message ); break; case MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS: @@ -1211,6 +1217,38 @@ handleTreatmentEndCmd( message ); break; + case MSG_ID_UI_SAMPLE_WATER_CMD: + handleSampleWaterCmd( message ); + break; + + case MSG_ID_UI_SAMPLE_WATER_RESULT: + handleSampleWaterResult( message ); + break; + + case MSG_ID_UI_CONSUMABLE_INSTALL_CONFIRM: + handleConsumableInstallConfirm( message ); + break; + + case MSG_ID_UI_INSTALLATION_CONFIRM: + handleInstallationConfirm( message ); + break; + + case MSG_ID_UI_START_PRIME_REQUEST: + handleStartPrimeCmd( message ); + break; + + case MSG_ID_UI_PATIENT_CONNECTION_BEGIN_REQUEST: + handleContinueToTreatmentCmd( message ); + break; + + case MSG_ID_UI_PATIENT_CONNECTION_CONFIRM: + handlePatientConnectionConfirmCmd( message ); + break; + + case MSG_ID_UI_START_TREATMENT_REQUEST: + handleStartTreatmentRequest( message ); + break; + case MSG_ID_DG_COMMAND_RESPONSE: handleDGCmdResp( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rbb80dbac26147ab08413efa91007f7ffed43c38f -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision bb80dbac26147ab08413efa91007f7ffed43c38f) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -20,8 +20,9 @@ #include "reg_system.h" #include "Accel.h" -#include "AlarmLamp.h" -#include "Buttons.h" +#include "AlarmLamp.h" +#include "Buttons.h" +#include "ConsumableSelfTest.h" #include "DGInterface.h" #include "FPGA.h" #include "ModePreTreat.h" @@ -31,6 +32,7 @@ #include "OperationModes.h" #include "PresOccl.h" #include "RTC.h" +#include "SampleWater.h" #include "SafetyShutdown.h" #include "SystemComm.h" #include "SystemCommMessages.h" @@ -63,7 +65,8 @@ static U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); static BOOL sendTestAckResponseMsg( MSG_ID_T msgID, BOOL ack ); -static BOOL sendAckResponseMsg( MSG_ID_T msgID, COMM_BUFFER_T buffer, BOOL ack ); +static BOOL sendAckResponseMsg( MSG_ID_T msgID, COMM_BUFFER_T buffer, BOOL ack ); +static BOOL sendUIResponseMsg( MSG_ID_T msgID, BOOL accepted, U32 reason ); /*********************************************************************//** * @brief @@ -180,9 +183,9 @@ /*********************************************************************//** * @brief - * The sendTestAckResponseMsg function constructs a simple response - * message for a handled test message and queues it for transmit on the - * appropriate UART channel. + * The sendAckResponseMsg function constructs a simple response + * message for a handled message and queues it for transmit on the + * appropriate CAN channel. * @details Inputs: none * @details Outputs: response message constructed and queued for transmit. * @param msgID ID of handled message that we are responding to @@ -206,10 +209,44 @@ return result; } + +/*********************************************************************//** + * @brief + * The sendUIResponseMsg function constructs an UI response message for a + * handled UI message and queues it for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: response message constructed and queued for transmit. + * @param msgID ID of handled message that we are responding to + * @param accepted T/F - request accepted? + * @param reason reason code if rejected + * @return TRUE if response message successfully queued for transmit, FALSE if not + *************************************************************************/ +static BOOL sendUIResponseMsg( MSG_ID_T msgID, BOOL accepted, U32 reason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = msgID; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &reason, 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; +} + // *********************************************************************** // ***************** Message Sending Helper Functions ******************** // *********************************************************************** + /*********************************************************************//** * @brief @@ -509,8 +546,239 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; -} +} +/*********************************************************************//** + * @brief + * The handleSampleWaterCmd function handles a sample water 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 handleSampleWaterCmd( MESSAGE_T *message ) +{ + if ( sizeof( U32 ) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof( U32 ) ); + signalSampleWaterUserAction( (REQUESTED_SAMPLE_WATER_USER_ACTIONS_T)cmd ); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The sendSampleWaterCmdResponse function constructs a sample water user action + * response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Sample water command response msg constructed and queued. + * @param accepted T/F - was sample water request accepted? + * @param reason reason why request was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendSampleWaterCmdResponse( BOOL accepted, U32 reason ) +{ + return sendUIResponseMsg( MSG_ID_HD_SAMPLE_WATER_CMD_RESPONSE, accepted, reason ); +} + +/*********************************************************************//** + * @brief + * The handleSampleWaterCmd function handles a sample water result msg from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleSampleWaterResult( MESSAGE_T *message ) +{ + if ( sizeof( U32 ) == message->hdr.payloadLen ) + { + U32 result; + + memcpy( &result, &message->payload[0], sizeof( U32 ) ); + setSampleWaterResult( (BOOL) result ); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The handleConsumableInstallConfirm function handles a consumable install + * confirm msg from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleConsumableInstallConfirm( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalUserConfirmConsumableInstall(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The handleInstallationConfirm function handles user confirms disposable + * installation msg from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleInstallationConfirm( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalUserConfirmInstallation(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The handlePrimingStartCmd function handles user confirms disposable + * installation msg from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleStartPrimeCmd( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalStartPrime(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The sendStartPrimeCmdResponse function constructs a start prime user action + * response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Start prime command response msg constructed and queued. + * @param accepted T/F - was start prime request accepted? + * @param reason reason why request was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendStartPrimeCmdResponse( BOOL accepted, U32 reason ) +{ + return sendUIResponseMsg( MSG_ID_HD_START_PRIME_RESPONSE, accepted, reason ); +} + +/*********************************************************************//** + * @brief + * The handleContinueToTreatmentCmd function handles user request to continue + * to treatment. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleContinueToTreatmentCmd( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalUserContinueToTreatment(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The sendContinueToTreatmentCmdResponse function constructs a continue to treatment + * user action response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Continue to treatment request response msg constructed and queued. + * @param accepted T/F - was continue to treatment request accepted? + * @param reason reason why request was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendContinueToTreatmentCmdResponse( BOOL accepted, U32 reason ) +{ + return sendUIResponseMsg( MSG_ID_HD_PATIENT_CONNECTION_BEGIN_RESPONSE, accepted, reason ); +} + +/*********************************************************************//** + * @brief + * The handlePatientConnectionConfirmCmd function handles user confirms + * patient connection. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handlePatientConnectionConfirmCmd( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalUserConfirmPatientConnection(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The sendPatientConnectionConfirmCmdResponse function constructs a patient connection confirm + * user action response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Patient connection confirm response msg constructed and queued. + * @param accepted T/F - was patient connection confirm accepted? + * @param reason reason why request was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendPatientConnectionConfirmCmdResponse( BOOL accepted, U32 reason ) +{ + return sendUIResponseMsg( MSG_ID_HD_PATIENT_CONNECTION_CONFIRM_RESPONSE, accepted, reason ); +} + +/*********************************************************************//** + * @brief + * The handleStartTreatmentRequest function handles user requests to start treatment. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none. + *************************************************************************/ +void handleStartTreatmentRequest( MESSAGE_T *message ) +{ + if ( 0 == message->hdr.payloadLen ) + { + signalUserStartTreatment(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); +} + +/*********************************************************************//** + * @brief + * The sendStartTreatmentResponse function constructs a start treatment user action + * response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Patient connection confirm response msg constructed and queued. + * @param accepted T/F - was patient connection confirm accepted? + * @param reason reason why request was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendStartTreatmentResponse( BOOL accepted, U32 reason ) +{ + return sendUIResponseMsg( MSG_ID_HD_START_TREATMENT_RESPONSE, accepted, reason ); +} + /*********************************************************************//** * @brief * The sendDialysateTempTargetsToDG function constructs a dialysate temperature @@ -603,11 +871,12 @@ * The sendDGFillCommand function constructs a DG fill command message * and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none - * @details Outputs: DG fill command msg constructed and queued. + * @details Outputs: DG fill command msg constructed and queued. + * @param cmd start or stop fill command * @param fillToVolumeMl volume (in mL) to fill inactive reservoir to * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDGFillCommand( U32 fillToVolumeMl ) +BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl ) { BOOL result; MESSAGE_T msg; @@ -616,10 +885,12 @@ // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_FILL_CMD; - msg.hdr.payloadLen = sizeof( U32 ); + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &fillToVolumeMl, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &cmd, sizeof( U32 ) ); - memcpy( payloadPtr, &fillToVolumeMl, 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_DG, ACK_REQUIRED ); @@ -719,18 +990,21 @@ * The sendDGSampleWaterCommand function constructs a DG sample water command * message and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none - * @details Outputs: DG sample water command msg constructed and queued. + * @details Outputs: DG sample water command msg constructed and queued. + * @param cmd sample water sub-command * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDGSampleWaterCommand( void ) +BOOL sendDGSampleWaterCommand( SAMPLE_WATER_CMD_T cmd ) { BOOL result; MESSAGE_T msg; // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_SAMPLE_WATER_CMD; - msg.hdr.payloadLen = 0; + msg.hdr.payloadLen = sizeof( U32 ); + + memcpy( msg.payload, &cmd, 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_DG, ACK_REQUIRED ); @@ -1231,6 +1505,34 @@ return result; } + +/*********************************************************************//** + * @brief + * The broadcastPreTreatmentState function constructs a pre-treatment state msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: pre-treatment state msg constructed and queued + * @param preTreatmentDataPtr pointer to pre-treatment data record to broadcast + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastPreTreatmentState( PRE_TREATMENT_STATE_DATA_T *preTreatmentDataPtr ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_PRE_TREATMENT_STATE; + msg.hdr.payloadLen = sizeof( PRE_TREATMENT_STATE_DATA_T ); + + memcpy( payloadPtr, preTreatmentDataPtr, sizeof( PRE_TREATMENT_STATE_DATA_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 @@ -1494,12 +1796,73 @@ return result; } +/*********************************************************************//** + * @brief + * The broadcastNoCartSelfTestTime function sends out the no cartridge self-test + * progress data. + * @details Inputs: none + * @details Outputs: no cartridge self-test time data msg constructed and queued + * @param timeout no cartridge self-test timeout (in sec) + * @param countdown no cartridge self-test timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastNoCartSelfTestTime( 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_NO_CART_SELF_TEST_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 broadcastDrySelfTestTime function sends out the dry self-test progress data. + * @details Inputs: none + * @details Outputs: dry self-test time data msg constructed and queued + * @param timeout dry self-test timeout (in sec) + * @param countdown dry self-test timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastDrySelfTestTime( 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_DRY_SELF_TEST_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 broadcastAirTrapData function constructs an HD air trap data msg to \n + * The broadcastPrimeData function constructs a priming status data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none - * @details Outputs: air trap data msg constructed and queued + * @details Outputs: priming data msg constructed and queued * @param primeDataPtr prime data record pointer * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ @@ -1900,14 +2263,14 @@ /*********************************************************************//** * @brief - * The handleUIStartTreatmentMsg function handles a treatment start/cancel + * The handleInitiateTreatmentRequest function handles a treatment initiate/cancel * message from the UI. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleUIStartTreatmentMsg( MESSAGE_T *message ) +void handleInitiateTreatmentRequest( MESSAGE_T *message ) { BOOL result = FALSE; @@ -1917,17 +2280,13 @@ memcpy( &cmd, message->payload, sizeof(U32) ); - if ( 0 == cmd ) // Initiate treatment (go to treatment params mode) + if ( 0 == cmd ) // Cancel treatment (return from aborted treatment params mode) { - result = signalUserStartingTreatment(); - } - else if ( 1 == cmd ) // Cancel treatment (return from aborted treatment params mode) - { result = signalUserCancelTreatment(); } - else if ( 2 == cmd ) // Start treatment + else if ( 1 == cmd ) // Initiate treatment (go to treatment params mode) { - result = signalUserBeginningTreatment(); + result = signalUserInitiateTreatment(); } } @@ -1936,34 +2295,18 @@ /*********************************************************************//** * @brief - * The sendTreatmentStartResponseMsg function constructs a treatment start - * request response message to the UI and queues the msg for transmit on + * The sendInitiateTreatmentResponseMsg function constructs a initiate treatment + * response message to the UI and queues the msg for transmit on * the appropriate CAN channel. * @details Inputs: none * @details Outputs: Treatment start response msg constructed and queued. * @param accepted T/F - request accepted? * @param reason reason code if rejected * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendTreatmentStartResponseMsg( BOOL accepted, U32 reason ) +BOOL sendInitiateTreatmentResponseMsg( BOOL accepted, U32 reason ) { - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_START_TREATMENT_RESPONSE; - msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); - - memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); - payloadPtr += sizeof( BOOL ); - memcpy( payloadPtr, &reason, 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; + return sendUIResponseMsg( MSG_ID_HD_INITIATE_TREATMENT_RESPONSE, accepted, reason ); } /*********************************************************************//** @@ -2074,6 +2417,7 @@ memcpy( &uFVolumeMl, message->payload, sizeof(F32) ); result = validateAndSetUFVolume( uFVolumeMl ); + setUserSetUFVolumeStatus( result ); } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, result ); Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rbb80dbac26147ab08413efa91007f7ffed43c38f -r4179eaf9c16e3607ce8abd961f154c2aaab2dffd --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision bb80dbac26147ab08413efa91007f7ffed43c38f) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 4179eaf9c16e3607ce8abd961f154c2aaab2dffd) @@ -26,7 +26,8 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" -#include "Prime.h" +#include "Prime.h" +#include "ModePreTreat.h" #include "ModeTreatment.h" #include "MsgQueues.h" #include "NVDataMgmt.h" @@ -94,11 +95,11 @@ // MSG_ID_DG_RESERVOIR_DATA: void handleDGReservoirData( MESSAGE_T *message ); -// MSG_ID_UI_START_TREATMENT -void handleUIStartTreatmentMsg( MESSAGE_T *message ); +// MSG_ID_UI_INITIATE_TREATMENT_REQUEST +void handleInitiateTreatmentRequest( MESSAGE_T *message ); -// MSG_ID_HD_START_TREATMENT_RESPONSE -BOOL sendTreatmentStartResponseMsg( BOOL accepted, U32 reason ); +// MSG_ID_UI_INITIATE_TREATMENT_RESPONSE +BOOL sendInitiateTreatmentResponseMsg( BOOL accepted, U32 reason ); // MSG_ID_UI_NEW_TREATMENT_PARAMS void handleTreatmentParametersFromUI( MESSAGE_T *message ); @@ -187,6 +188,47 @@ // MSG_ID_HD_RECIRC_CMD_RESPONSE BOOL sendTreatmentEndCmdResponse( BOOL accepted, U32 rejReason ); +// MSG_ID_UI_SAMPLE_WATER_CMD +void handleSampleWaterCmd( MESSAGE_T *message ); + +// MSG_ID_HD_SAMPLE_WATER_CMD_RESPONSE +BOOL sendSampleWaterCmdResponse( BOOL accepted, U32 reason ); + +// MSG_ID_UI_SAMPLE_WATER_RESULT +void handleSampleWaterResult( MESSAGE_T *message ); + +// MSG_ID_UI_CONSUMABLE_INSTALL_CONFIRM +void handleConsumableInstallConfirm( MESSAGE_T *message ); + +// MSG_ID_UI_INSTALLATION_CONFIRM +void handleInstallationConfirm( MESSAGE_T *message ); + +// MSG_ID_UI_START_PRIME_REQUEST +void handleStartPrimeCmd( MESSAGE_T *message ); + +// MSG_ID_HD_START_PRIME_RESPONSE +BOOL sendStartPrimeCmdResponse( BOOL accepted, U32 reason ); + +// MSG_ID_UI_CONTINUE_TO_TREATMENT_REQUEST +void handleContinueToTreatmentCmd( MESSAGE_T *message ); + +// MSG_ID_HD_CONTINUE_TO_TREATMENT_RESPONSE +BOOL sendContinueToTreatmentCmdResponse( BOOL accepted, U32 reason ); + +// MSG_ID_UI_PATIENT_CONNECTION_CONFIRM +void handlePatientConnectionConfirmCmd( MESSAGE_T *message ); + +// MSG_ID_HD_PATIENT_CONNECTION_CONFIRM_RESPONSE +BOOL sendPatientConnectionConfirmCmdResponse( BOOL accepted, U32 reason ); + +// MSG_ID_UI_START_TREATMENT_REQUEST +void handleStartTreatmentRequest( MESSAGE_T *message ); + +// MSG_ID_HD_START_TREATMENT_RESPONSE +BOOL sendStartTreatmentResponse( BOOL accepted, U32 reason ); + +// *********** public DG command functions ********** + // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS BOOL sendDialysateTempTargetsToDG( F32 primary, F32 trimmer ); @@ -197,7 +239,7 @@ BOOL sendDGChangeValveSettingCommand( U32 valveSettingCmd ); // MSG_ID_DG_FILL_CMD -BOOL sendDGFillCommand( U32 fillToVolumeMl ); +BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl ); // MSG_ID_DG_DRAIN_CMD BOOL sendDGDrainCommand( DRAIN_RESERVOIR_CMD_PAYLOAD_T *drainCmdPtr ); @@ -209,14 +251,16 @@ BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start, F32 trimmerHtrTemp ); // MSG_ID_DG_SAMPLE_WATER_CMD -BOOL sendDGSampleWaterCommand( void ); +BOOL sendDGSampleWaterCommand( SAMPLE_WATER_CMD_T cmd ); // MSG_ID_DG_COMMAND_RESPONSE void handleDGCmdResp( MESSAGE_T *messagePtr ); // MSG_ID_DG_OP_MODE void handleDGOpMode( MESSAGE_T *message ); +// *********** public data broad cast functions ********** + // MSG_ID_HD_ACCELEROMETER_DATA BOOL broadcastAccelData( F32 x, F32 y, F32 z, F32 xm, F32 ym, F32 zm, F32 xt, F32 yt, F32 zt ); @@ -242,7 +286,7 @@ BOOL broadcastDialInFlowData( DIALIN_PUMP_STATUS_PAYLOAD_T *dialInData ); // MSG_ID_DIALYSATE_OUT_FLOW_DATA -BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); +BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); // MSG_ID_HD_SYRINGE_PUMP_DATA BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ); @@ -261,6 +305,9 @@ // MSG_ID_TREATMENT_STATE BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ); + +// MSG_ID_PRE_TREATMENT_STATE +BOOL broadcastPreTreatmentState( PRE_TREATMENT_STATE_DATA_T *preTreatmentDataPtr ); // MSG_ID_POWER_OFF_WARNING BOOL broadcastPowerOffWarning( void ); @@ -289,6 +336,12 @@ // MSG_ID_HD_AIR_TRAP_DATA BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel ); +// MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS +BOOL broadcastNoCartSelfTestTime( U32 timeout, U32 countdown ); + +// MSG_ID_HD_DRY_SELF_TEST_PROGRESS +BOOL broadcastDrySelfTestTime( U32 timeout, U32 countdown ); + // MSG_ID_HD_PRIMING_STATUS_DATA BOOL broadcastPrimeData( PRIMING_DATA_PAYLOAD_T *primeDataPtr );