Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r7d229e65a33d587e2e5b03b4ce06e814012686e4 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 7d229e65a33d587e2e5b03b4ce06e814012686e4) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. @@ -16,14 +16,17 @@ ***************************************************************************/ #include "AlarmMgmt.h" -#include "Buttons.h" +#include "ConsumableSelfTest.h" #include "FPGA.h" #include "ModePreTreat.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PreTreatmentRecirc.h" #include "Prime.h" #include "SelfTests.h" +#include "SampleWater.h" #include "SystemCommMessages.h" +#include "TaskGeneral.h" /** * @addtogroup HDPreTreatmentMode @@ -32,24 +35,76 @@ // ********** private definitions ********** +/// Interval (ms/task time) at which the pre-treatment state data is published on the CAN bus. +#define PRE_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) + +/// Wait time for ui to transition on completion of a sub-mode (ms/task time). +#define SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +#define DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN 100 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. + +#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 700 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. + +#define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 ///< Primary heater target temperature offset from trimmer heater temperature. + + +/// States of the pre-treatment reservoir management state machine. +typedef enum PreTreatmentReservoirMgmt_States +{ + PRE_TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< Wait for signal to start drain and fill reservoirs + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE, ///< Command DG to start draining reservoir + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE, ///< After sending drain command, process DG drain command response + PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE, ///< Command DG to start filling reservoir + PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE, ///< After sending fill command, process DG fill command response + PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE, ///< Reservoir fill has completed + PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE, ///< Wait for prime operation to switch reservoir + PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE, ///< Pre-treatment reservoir management complete state + NUM_OF_PRE_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of pre-treatments reservoir mgmt. states +} PRE_TREATMENT_RESERVOIR_MGMT_STATE_T; + // ********** private data ********** -static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user requests treatment begin. -static BOOL alarmActionStopReceived = FALSE; ///< Flag indicates an alarm w/ stop property was triggered. +static BOOL confirmInstallRequested = FALSE; ///< Flag indicates user confirms disposable installation. +static BOOL continueToTreatmentRequested = FALSE; ///< Flag indicates user requests to continue to treatment from re-circ. +static BOOL setUFVolStatus; ///< The status of set UF volume operation. +static BOOL patientConnectionConfirm; ///< Flag indicates user has confirmed patient connection complete. +static BOOL treatmentStartRequested = FALSE; ///< Flag indicates user requests treatment begin. + 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 U32 preTreatmentPublishTimerCounter; ///< Pre-treatment data broadcast timer counter used to schedule when to transmit data. +static U32 submodeCompleteTransitionTimeCounter; ///< Sub-mode completed transition wait time counter. +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T currentReservoirMgmtState; ///< Current pre-treatment reservoir management state. +static BOOL fillReservoirOneStartRequested; ///< Flag indicates fill reservoir one has been requested. +static BOOL reservoirFilledStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Flag indicates a reservoir has been filled. + // ********** private function prototypes ********** +static void publishPreTreatmentState( void ); static void resetSignalFlags( void ); +static void transitionToCartridgeInstallation( void ); +static void transitionToPatientConnection( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( 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 handleRecirculateState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); +static void execPreTreatmentReservoirMgmt( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ); + /*********************************************************************//** * @brief * The initPreTreatmentMode function initializes the Pre-Treatment Mode module. @@ -60,7 +115,17 @@ void initPreTreatmentMode( void ) { currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + fillReservoirOneStartRequested = FALSE; + submodeCompleteTransitionTimeCounter = 0; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = FALSE; + reservoirFilledStatus[ DG_RESERVOIR_2 ] = FALSE; + + initSampleWater(); + initConsumableSelfTest(); initPrime(); initSelfTests(); @@ -83,6 +148,7 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); initPreTreatmentMode(); + cmdStopDGTrimmerHeater(); } /*********************************************************************//** @@ -105,16 +171,20 @@ switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_START_STATE: - cmdStartDG(); - cmdSetDGDialysateTargetTemps( 39.0, 37.0 ); +#ifndef SKIP_SAMPLE_WATER + transitionToSampleWater(); +#endif currentPreTreatmentState = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; break; case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: - transitionToNoCartSelfTests(); - currentPreTreatmentState = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + currentPreTreatmentState = handleWaterSampleState(); break; + case HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE: + currentPreTreatmentState = handleSelfTestConsumableState(); + break; + case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: currentPreTreatmentState = handleSelfTestNoCartState(); break; @@ -141,38 +211,133 @@ break; } + // Execute reservoir management for pre-treatment mode + execPreTreatmentReservoirMgmt(); + // Alarm response request flags should be handled at this point, reset in case not handled in current state resetSignalFlags(); + // Broadcast pre-treatment data + publishPreTreatmentState(); + return (U32)currentPreTreatmentState; } /*********************************************************************//** * @brief - * The signalUserBeginningTreatment function handles user start of a - * treatment. + * The signalUserConfirmInstallation function handles user confirmation of + * disposable installation. * @details Inputs: none - * @details Outputs: treatStartReqReceived, send response to treatment start + * @details Outputs: confirmInstallRequested * @return TRUE if signal accepted, FALSE if not *************************************************************************/ -BOOL signalUserBeginningTreatment( void ) +void signalUserConfirmInstallation( void ) { - BOOL result = FALSE; + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) ) + { + confirmInstallRequested = TRUE; + } +} - // TODO: check patient connection sub-mode state - if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) +/*********************************************************************//** + * @brief + * The signalUserContinueToTreatment function handles user request to continue + * to treatment. + * @details Inputs: none + * @details Outputs: handled and send response to continue to treatment request + * @return none + *************************************************************************/ +void signalUserContinueToTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( HD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ) { - treatStartReqReceived = TRUE; - result = TRUE; + continueToTreatmentRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; } - sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected + sendContinueToTreatmentCmdResponse( accepted, rejReason ); +} - return result; +/*********************************************************************//** + * @brief + * The setUserSetUFVolumeStatus function sets the status for user sets UF + * volume operation. + * @details Inputs: set UF volume operation status + * @details Outputs: setUFVolStatus + * @return none + *************************************************************************/ +void setUserSetUFVolumeStatus( BOOL status ) +{ + setUFVolStatus = status; } /*********************************************************************//** * @brief + * The signalUserConfirmPatientConnection function handles user confirms + * patient connection message. + * @details Inputs: none + * @details Outputs: handled and send response to patient connection confirmation + * @return none + *************************************************************************/ +void signalUserConfirmPatientConnection( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_UF_VOLUME_NOT_SET; + + if ( TRUE == setUFVolStatus ) + { + if ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) + { + patientConnectionConfirm = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendPatientConnectionConfirmCmdResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief + * The signalUserStartTreatment function handles user requests to start treatment. + * @details Inputs: patientConnectionConfirm, currentPreTreatmentState + * @details Outputs: handled and send response to treatment start request + * @return none + *************************************************************************/ +void signalUserStartTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NO_PATIENT_CONNECTION_CONFIRM; + +#ifndef SKIP_UI_INTERACTION + if ( TRUE == patientConnectionConfirm ) +#endif + { + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) + { + treatmentStartRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendStartTreatmentResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToPreTreatmentMode function executes the given alarm action * as appropriate while in PreTreatment Mode. * @details Inputs: none @@ -185,15 +350,22 @@ switch( action ) { case ALARM_ACTION_STOP: - alarmActionStopReceived = TRUE; + // Stop signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: alarmActionResumeReceived = TRUE; break; case ALARM_ACTION_END_TREATMENT: - requestNewOperationMode( MODE_STAN ); + if ( HD_PRE_TREATMENT_PRIME_STATE > currentPreTreatmentState ) + { + requestNewOperationMode( MODE_STAN ); + } + else + { + requestNewOperationMode( MODE_POST ); + } break; case ALARM_ACTION_ACK: @@ -208,20 +380,187 @@ /*********************************************************************//** * @brief + * The getReservoirFillStatus function returns the fill complete status for + * given reservoir. + * @details Inputs: reservoirFilledStatus + * @details Outputs: none + * @return TRUE if reservoir has been filled, otherwise FALSE; + *************************************************************************/ +BOOL getReservoirFillStatus( DG_RESERVOIR_ID_T reservoirID ) +{ + return reservoirFilledStatus[ reservoirID ]; +} + +/*********************************************************************//** + * @brief + * The publishPreTreatmentState function broadcasts pre-treatment sub-mode + * and current sub-mode state. + * @details Inputs: pre-treatment sub-mode, state + * @details Outputs: pre-treatment sub-mode, state messages sent on interval + * @return none + *************************************************************************/ +static void publishPreTreatmentState( void ) +{ + // Broadcast treatment time and state data at interval + if ( ++preTreatmentPublishTimerCounter >= PRE_TREATMENT_DATA_PUB_INTERVAL ) + { + PRE_TREATMENT_STATE_DATA_T preTreatmentData; + + preTreatmentData.preTreatmentSubMode = currentPreTreatmentState; + preTreatmentData.sampleWaterState = getSampleWaterState(); + preTreatmentData.consumableSelfTestsState = getConsumableSelfTestState(); + preTreatmentData.noCartSelfTestsState = getNoCartSelfTestsState(); + preTreatmentData.installState = 0; + preTreatmentData.drySelfTestsState = getDrySelfTestsState(); + preTreatmentData.primeState = getPrimeState(); + preTreatmentData.recircState = getPreTreatmentRecircState(); + preTreatmentData.patientConnectionState = 0; + + broadcastPreTreatmentState( &preTreatmentData ); + preTreatmentPublishTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief * The resetSignalFlags function resets all signal flags. * @details Inputs: none * @details Outputs: signal flags set to FALSE * @return none *************************************************************************/ static void resetSignalFlags( void ) { - treatStartReqReceived = FALSE; - alarmActionStopReceived = FALSE; + treatmentStartRequested = FALSE; + confirmInstallRequested = FALSE; + continueToTreatmentRequested = FALSE; + alarmActionResumeReceived = FALSE; } /*********************************************************************//** * @brief + * The transitionToCartridgeInstallation function prepares actuators before + * transition to pre-treatment install state. + * @details Inputs: none + * @details Outputs: valves are in insert position + * @return none + *************************************************************************/ +static void transitionToCartridgeInstallation( void ) +{ + VALVE_T valve; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); + } + + setValveAirTrap( STATE_CLOSED ); +} + +/*********************************************************************//** + * @brief + * The transitionToPatientConnection function prepares actuators before + * transition to pre-treatment patient connection state. + * @details Inputs: none + * @details Outputs: Stopped pumps + * @return none + *************************************************************************/ +static void transitionToPatientConnection( void ) +{ + VALVE_T valve; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + treatmentStartRequested = FALSE; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_C_CLOSE ); + } + + signalBloodPumpHardStop(); + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + cmdStartDGTrimmerHeater(); +} + +/*********************************************************************//** + * @brief + * The handleWaterSampleState function handles sample water state during + * pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed sample water state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + execSampleWater(); + +#ifndef SKIP_SAMPLE_WATER + if ( SAMPLE_WATER_COMPLETE_STATE == getSampleWaterState() ) +#endif + { + cmdDGSampleWater( SAMPLE_WATER_CMD_END ); + + if ( SELF_TEST_STATUS_PASSED == getSampleWaterResult() ) + { + if ( ( DG_MODE_STAN == dgOpMode ) && ( DG_STANDBY_MODE_STATE_IDLE == dgSubMode ) ) + { + state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + F32 const trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + F32 const primaryHeaterTemp = trimmerHeaterTemp + PRIMARY_HEATER_TARGET_TEMP_OFFSET; + + cmdStartDG(); + cmdSetDGDialysateTargetTemps( primaryHeaterTemp, trimmerHeaterTemp ); + transitionToConsumableSelfTest(); + } + else + { + cmdStopDG(); + } + } + else + { + requestNewOperationMode( MODE_STAN ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestConsumableState function handles consumable self-test state + * during pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed consumable self-test state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + + execConsumableSelfTest(); + + if ( CONSUMABLE_SELF_TESTS_COMPLETE_STATE == getConsumableSelfTestState() ) + { + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + fillReservoirOneStartRequested = TRUE; + transitionToNoCartSelfTests(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleSelfTestNoCartState function handles self-test with no cartridge. * @details Inputs: none * @details Outputs: home blood pump and dialysate pumps @@ -238,19 +577,44 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) + execNoCartSelfTests(); + + if ( NO_CART_SELF_TESTS_COMPLETE_STATE == getNoCartSelfTestsState() ) { - signalStopSelfTests(); + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + transitionToCartridgeInstallation(); + } } - execNoCartSelfTests(); + return state; +} - if ( TRUE == isNoCartSelfTestsPassed() ) +/*********************************************************************//** + * @brief + * The handleInstallState function handles disposable installation. + * @details Inputs: none + * @details Outputs: transition to prime sub-mode when blood pump finished + * homing + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleInstallState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + +#ifndef SKIP_UI_INTERACTION + if ( TRUE == confirmInstallRequested ) +#endif { - state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + confirmInstallRequested = FALSE; + state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + transitionToDrySelfTests(); } return state; @@ -274,28 +638,29 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopSelfTests(); - } - execDrySelfTests(); - if ( TRUE == isDrySelfTestsPassed() ) + if ( DRY_SELF_TESTS_COMPLETE_STATE == getDrySelfTestsState() ) { - transitionToPrime(); - state = HD_PRE_TREATMENT_PRIME_STATE; + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_PRIME_STATE; + transitionToPrime(); + } } return state; } /*********************************************************************//** * @brief - * The handlePrimeState function handles priming the blood and dialysate circuits. + * The handlePrimeState function handles priming the blood and dialysate + * circuits. * @details Inputs: none * @details Outputs: transition to self test wet state after priming passed * @return current state (sub-mode) @@ -311,21 +676,21 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePrime(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPrime(); - } - execPrime(); - if ( TRUE == isPrimeCompleted() ) + if ( HD_PRIME_COMPLETE == getPrimeState() ) { - state = HD_PRE_TREATMENT_RECIRCULATE_STATE; - activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); - transitionToPreTreatmentRecirc(); + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); + transitionToPreTreatmentRecirc(); + } } return state; @@ -350,19 +715,19 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePreTreatmentRecirc(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPreTreatmentRecirc(); - } - execPreTreatmentRecirc(); - if ( TRUE == isPatientConnectionRequested() ) +#ifndef SKIP_UI_INTERACTION + if ( TRUE == continueToTreatmentRequested ) +#endif { + continueToTreatmentRequested = FALSE; state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + transitionToPatientConnection(); } return state; @@ -378,15 +743,259 @@ *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) { - DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); - - if ( TRUE == treatStartReqReceived ) + if ( TRUE == treatmentStartRequested ) { + DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); setStartReservoirVolume( activeRes ); requestNewOperationMode( MODE_TREA ); } return HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; } +/*********************************************************************//** + * @brief + * The execPreTreatmentReservoirMgmt function executes the state machine for + * reservoir management during pre-treatment mode. + * @details Inputs: currentReservoirMgmtState + * @details Outputs: DG reservoirs' fills managed. + * @return none + *************************************************************************/ +static void execPreTreatmentReservoirMgmt( void ) +{ + // treatment reservoir mgmt. state machine + switch ( currentReservoirMgmtState ) + { + case PRE_TREATMENT_RESERVOIR_MGMT_START_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtStartState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCompleteState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtWaitReservoirSwitchState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE: + break; + + default: + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRIME_RESERVOIR_MGMT_INVALID_STATE, (U32)currentReservoirMgmtState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtStartState function handles reservoir + * management start state for pre-treatment mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + + if ( TRUE == fillReservoirOneStartRequested ) + { + fillReservoirOneStartRequested = FALSE; + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdState function sends drain + * command to DG when DG is in re-circulate mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + // If DG has not started yet, start DG + if ( DG_MODE_STAN == dgOpMode ) + { + cmdStartDG(); + } + + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdRespState function waits + * and processes DG drain command response. + * @details Inputs: DG drain command response + * @details Outputs: processed DG drain command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + if ( DG_MODE_DRAI == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdState function sends fill + * command to DG when DG is in re-circulate mode. + * @details Inputs: DG operation mode and operation sub-mode + * @details Outputs: sent fill command to DG + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + + if ( DG_RESERVOIR_1 == getDGInactiveReservoir() ) + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML ); + } + else + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdRespState function waits + * and processes DG fill command response. + * @details Inputs: DG fill command response + * @details Outputs: processed DG fill command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_FILL, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + if ( DG_MODE_FILL == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCompleteState function switches + * reservoir after the first one fill is complete and restart reservoir management + * state machine. + * @details Inputs: DG operation mode + * @details Outputs: switch active reservoir and signal prime fill complete status + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + if ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = TRUE; + } + else if ( ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) && ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) ) + { + reservoirFilledStatus[ DG_RESERVOIR_2 ] = TRUE; + state = PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE; + } + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtWaitReservoirSwitchState function waits + * until prime operation switches the active reservoir before filling up next reservoir. + * @details Inputs: DG intactive reservoir + * @details Outputs: start filling next reservoir + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + + if ( DG_RESERVOIR_2 == getDGInactiveReservoir() ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + return state; +} + /**@}*/ Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r62200ed6423dfd6ff7881bd0fc308162384e663e -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 62200ed6423dfd6ff7881bd0fc308162384e663e) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -17,6 +17,7 @@ #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodLeak.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" @@ -40,9 +41,6 @@ #define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. #define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. -#define BLOOD_LEAK_SELF_TEST_SET 0x1 ///< Initiate blood leak self-test. -#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. @@ -263,8 +261,7 @@ case NO_CART_SELF_TESTS_DIALYSATE_FLOW_METERS_STATE: execDialInFlowTest(); - // TODO: Use appropriate sensor driver - setFPGASensorTest( BLOOD_LEAK_SELF_TEST_SET ); + zeroBloodLeak(); currentNoCartSelfTestsState = NO_CART_SELF_TESTS_LEAK_DETECTORS_STATE; break; @@ -611,18 +608,14 @@ 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 ) + if ( SELF_TEST_STATUS_PASSED == getBloodLeakSelfTestStatus() ) { - // 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 ); + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE ); } if ( TRUE == doesAlarmStatusIndicateStop() ) Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -253,7 +253,8 @@ SW_FAULT_ID_HD_INVALID_COMMAND_RESPONSE_ID, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, SW_FAULT_ID_HD_INVALID_VALVE_SETTING_ID, - SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, // 110 + SW_FAULT_ID_HD_INVALID_BLOOD_LEAK_STATE, // 110 + SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, SW_FAULT_ID_HD_SYRINGE_INVALID_CONT_CMD, SW_FAULT_ID_HD_SYRINGE_INVALID_VREF, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -81,10 +81,15 @@ #define FPGA_AIRTRAP_LEVEL_LOW_MASK 0x0008 ///< Bit mask for air trap lower level sensor. #define FPGA_AIRTRAP_LEVEL_HIGH_MASK 0x0004 ///< Bit mask for air trap upper level sensor. -#define FPGA_FLUIDLEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. +#define FPGA_FLUID_LEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. +#define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector. +#define FPGA_BLOOD_LEAK_ZERO_STATE_MASK 0x2000 ///< Bit mask for blood leak detector zero. + +#define FPGA_BLOOD_LEAK_ZERO_CMD 0x02 ///< Bit for blood leak detector zero command. +#define FPGA_BLOOD_LEAK_SELF_TEST_CMD 0x01 ///< Bit for blood leak detector self test command. + #define FPGA_ADA_INPUT_STATUS_MASK 0x0001 ///< Bit mask for arterial air bubble detector input status. #define FPGA_ADV_INPUT_STATUS_MASK 0x0002 ///< Bit mask for venous air bubble detector input status. -#define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector status. // FPGA Sensors Record #pragma pack(push,1) @@ -1614,34 +1619,6 @@ /*********************************************************************//** * @brief - * The setFPGASensorTest function sets the sensor test output. - * @details Inputs: fpgaActuatorSetPoints - * @details Outputs: fpgaActuatorSetPoints - * @param sensorTest - * @return none - *************************************************************************/ -void setFPGASensorTest( U08 sensorTest ) -{ - fpgaActuatorSetPoints.fpgaSensorTest = sensorTest; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodLeakDetectorStatus function gets the latest blood leak - * detector status. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return TRUE if blood leak is detected, otherwise FALSE - *************************************************************************/ -BOOL getFPGABloodLeakDetectorStatus( void ) -{ - U16 const status = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_STATUS_MASK; - - return ( 0 == status ? FALSE : TRUE ); -} - -/*********************************************************************//** - * @brief * The getDoorState function gets the current state of door switch. * @details Inputs: none * @details Outputs: none @@ -1682,21 +1659,103 @@ /*********************************************************************//** * @brief - * The noFluidLeakDetected function returns TRUE if no fluid leak has been + * The noFPGAFluidLeakDetected function returns TRUE if no fluid leak has been * detected (dry) and FALSE if a fluid leak has been detected (wet). * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return noFluidLeakDetected + * @return noFPGAFluidLeakDetected *************************************************************************/ BOOL noFPGAFluidLeakDetected( void ) { - U16 noFluidLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_FLUIDLEAK_STATE_MASK; + U16 noFPGAFluidLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_FLUID_LEAK_STATE_MASK; - return ( 0 == noFluidLeakDetected ? FALSE : TRUE ); + return ( 0 == noFPGAFluidLeakDetected ? FALSE : TRUE ); } /*********************************************************************//** * @brief + * The noFPGABloodLeakDetected function returns TRUE if no blood leak has been + * detected and FALSE if a blood leak has been detected. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return noFPGABloodLeakDetected + *************************************************************************/ +BOOL noFPGABloodLeakDetected( void ) +{ + U16 noFPGABloodLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_STATUS_MASK; + + return ( 0 == noFPGABloodLeakDetected ? FALSE : TRUE ); +} + +/*********************************************************************//** + * @brief + * The FPGABloodLeakZeroDetected function returns TRUE if blood leak zeroing has + * been detected and FALSE if no blood leak zeroing has been detected. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return FPGABloodLeakZeroDetected + *************************************************************************/ +BOOL FPGABloodLeakZeroDetected( void ) +{ + U16 FPGABloodLeakZeroDetected = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_ZERO_STATE_MASK; + + return ( 0 == FPGABloodLeakZeroDetected ? FALSE : TRUE ); +} + +/*********************************************************************//** + * @brief + * The setFPGABloodLeakZero function sets the Blood Leak detector into + * zeroing mode via the FPGA. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return FPGABloodLeakZeroDetected + *************************************************************************/ +void setFPGABloodLeakZero( void ) +{ + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_ZERO_CMD; +} + +/*********************************************************************//** + * @brief + * The clearFPGABloodLeakZero function clears the Blood Leak detector from + * zeroing mode via the FPGA. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return none + *************************************************************************/ +void clearFPGABloodLeakZero( void ) +{ + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_ZERO_CMD; +} + +/*********************************************************************//** + * @brief + * The setFPGABloodLeakSelfTest function sets the Blood Leak detector into + * self-test mode via the FPGA. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return FPGABloodLeakZeroDetected + *************************************************************************/ +void setFPGABloodLeakSelfTest( void ) +{ + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_SELF_TEST_CMD; +} + +/*********************************************************************//** + * @brief + * The clearFPGABloodLeakSelfTest function clears the Blood Leak detector from + * self-test mode via the FPGA. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return none + *************************************************************************/ +void clearFPGABloodLeakSelfTest( void ) +{ + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_SELF_TEST_CMD; +} + +/*********************************************************************//** + * @brief * The setValveDialyzerInletPosition function sets the position of VDi * in counts * @details Inputs: fpgaActuatorSetPoints Index: firmware/App/Services/FPGA.h =================================================================== diff -u -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -99,7 +99,6 @@ BOOL getFPGAVenousAirBubbleStatus( void ); void setFPGASensorTest( U08 sensorTest ); -BOOL getFPGABloodLeakDetectorStatus( void ); OPN_CLS_STATE_T getFPGADoorState( void ); @@ -108,6 +107,13 @@ BOOL noFPGAFluidLeakDetected( void ); +BOOL noFPGABloodLeakDetected( void ); +BOOL FPGABloodLeakZeroDetected( void ); +void setFPGABloodLeakZero( void ); +void clearFPGABloodLeakZero( void ); +void setFPGABloodLeakSelfTest( void ); +void clearFPGABloodLeakSelfTest( void ); + void setFPGAValveDialyzerInletPosition( S16 setPoint ); S16 getFPGAValveDialyzerInletPosition( void ); U16 getFPGAValveDialyzerInletCurrentCounts( void ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -1523,9 +1523,22 @@ handleSetFluidLeakBroadcastIntervalOverrideRequest( message ); break; - case MSG_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE: - handleSetFluidLeakStateDetectorOverrideRequest( message ); + case MSG_ID_HD_FLUID_LEAK_STATE_OVERRIDE: + handleSetFluidLeakStateOverrideRequest( message ); + break; + case MSG_ID_HD_BLOOD_LEAK_DATA_SEND_INTERVAL_OVERRIDE: + handleSetBloodLeakDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_STATUS_OVERRIDE: + handleSetBloodLeakStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_ZERO_REQUEST: + handleBloodLeakZeroRequest( message ); + break; + case MSG_ID_HD_SET_OP_MODE_REQUEST: handleTestSetOpModeRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -7,8 +7,8 @@ * * @file SystemCommMessages.c * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Peman Montazemi +* @date (last) 18-Mar-2021 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -23,7 +23,7 @@ #include "AlarmLamp.h" #include "Buttons.h" #include "ConsumableSelfTest.h" -#include "DGInterface.h" +#include "DGInterface.h" #include "FPGA.h" #include "ModePreTreat.h" #include "ModeStandby.h" @@ -1885,6 +1885,38 @@ /***********************************************************************//** * @brief + * The broadcastBloodLeakData function constructs an HD blood leak data msg to \n + * be broadcasted and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: blood leak data msg constructed and queued + * @param status blood leak status + * @param state blood leak state + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastBloodLeakData( BLOOD_LEAK_STATUS_T status, U32 state ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 leakStatus = (U32)status; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_BLOOD_LEAK_DATA; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &leakStatus, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &state, 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 broadcastPrimeData function constructs a prime data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none @@ -4768,14 +4800,14 @@ /*********************************************************************//** * @brief - * The handleSetFluidLeakStateDetectorOverrideRequest function handles a request to + * The handleSetFluidLeakStateOverrideRequest function handles a request to * override the fluid leak detector state. * @details Inputs: none * @details Outputs: message handled * @param message : a pointer to the message to handle * @return none *************************************************************************/ -void handleSetFluidLeakStateDetectorOverrideRequest( MESSAGE_T *message ) +void handleSetFluidLeakStateOverrideRequest( MESSAGE_T *message ) { TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; BOOL result = FALSE; @@ -4800,6 +4832,94 @@ /*********************************************************************//** * @brief + * The handleSetBloodLeakDataBroadcastIntervalOverrideRequest function handles a + * request to override the blood leak data broadcast interval. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetBloodLeakDataBroadcastIntervalOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodLeakDataPublishIntervalOverride( (U32)( payload.state.u32 ) ); + } + else + { + result = testResetBloodLeakDataPublishIntervalOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleSetBloodLeakStatusOverrideRequest function handles a request to + * override the blood leak detector status. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetBloodLeakStatusOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodLeakStatusOverride( (BLOOD_LEAK_STATUS_T)( payload.state.u32 ) ); + } + else + { + result = testResetBloodLeakStatusOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroRequest function handles a request to + * zero the blood leak detector. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleBloodLeakZeroRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify payload length + if ( 0 == message->hdr.payloadLen ) + { + result = TRUE; + zeroBloodLeak(); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief * The handleHDSoftwareResetRequest function handles a request to reset the * HD firmware processor. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -21,6 +21,7 @@ #include "HDCommon.h" #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodLeak.h" #include "BloodPrime.h" #include "DGInterface.h" #include "DialInFlow.h" @@ -346,6 +347,9 @@ // MSG_ID_HD_FLUID_LEAK_STATE BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state ); +// MSG_ID_HD_BLOOD_LEAK_DATA +BOOL broadcastBloodLeakData( BLOOD_LEAK_STATUS_T status, U32 state ); + // MSG_ID_HD_PRIMING_STATUS_DATA BOOL broadcastPrimeData( PRIMING_DATA_PAYLOAD_T *primeDataPtr ); @@ -547,9 +551,18 @@ // MSG_ID_HD_FLUID_LEAK_SEND_INTERVAL_OVERRIDE void handleSetFluidLeakBroadcastIntervalOverrideRequest( MESSAGE_T *message ); -// MSG_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE -void handleSetFluidLeakStateDetectorOverrideRequest( MESSAGE_T *message ); +// MSG_ID_HD_FLUID_LEAK_STATE_OVERRIDE +void handleSetFluidLeakStateOverrideRequest( MESSAGE_T *message ); +// MSG_ID_HD_BLOOD_LEAK_DATA_SEND_INTERVAL_OVERRIDE +void handleSetBloodLeakDataBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_BLOOD_LEAK_STATUS_OVERRIDE +void handleSetBloodLeakStatusOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_BLOOD_LEAK_ZERO_REQUEST +void handleBloodLeakZeroRequest( MESSAGE_T *message ); + // MSG_ID_SUPER_CLEAR_ALARMS_CMD void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ); Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -rd6c75118f4e5792b40b744a0b29e44c78368a469 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision d6c75118f4e5792b40b744a0b29e44c78368a469) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -17,7 +17,8 @@ #include "Accel.h" #include "AirTrap.h" -#include "BloodFlow.h" +#include "BloodFlow.h" +#include "BloodLeak.h" #include "Buttons.h" #include "CPLD.h" #include "DialInFlow.h" @@ -87,6 +88,9 @@ // Monitor fluid leak detector execFluidLeak(); + // Monitor blood leak detector + execBloodLeak(); + #ifndef DISABLE_ACCELS // Monitor accelerometer execAccel(); Index: firmware/source/sys_main.c =================================================================== diff -u -rfaa5d7065729e8af72536688e161e123d684a5e0 -r04f033af4174bf41a7aa0ff9ccaae45b77472e01 --- firmware/source/sys_main.c (.../sys_main.c) (revision faa5d7065729e8af72536688e161e123d684a5e0) +++ firmware/source/sys_main.c (.../sys_main.c) (revision 04f033af4174bf41a7aa0ff9ccaae45b77472e01) @@ -54,6 +54,7 @@ #include "sys_dma.h" #include "adc.h" #include "can.h" +#include "i2c.h" #include "etpwm.h" #include "gio.h" #include "het.h" @@ -65,6 +66,7 @@ #include "Accel.h" #include "AirTrap.h" #include "AlarmLamp.h" +#include "Battery.h" #include "BloodFlow.h" #include "BloodLeak.h" #include "Buttons.h" @@ -82,6 +84,7 @@ #include "PresOccl.h" #include "RTC.h" #include "SafetyShutdown.h" +#include "SyringePump.h" #include "SystemComm.h" #include "TaskBG.h" #include "Timers.h" @@ -150,8 +153,8 @@ etpwmSetCmpA( etpwmREG7, etpwmREG7->TBPRD / 3 ); etpwmStartTBCLK(); canInit(); // CAN1 = CAN, re-purposing CAN2 and CAN3 Rx and Tx pins as GPIO - //canEnableloopback( canREG1, External_Lbk ); // TODO - debug code sciInit(); // SCI1 used for PC serial interface, SCI2 used for FPGA serial interface + i2cInit(); // I2C used for battery charger interface. dmaEnable(); // Enable DMA } @@ -172,7 +175,9 @@ initCPLD(); initSafetyShutdown(); initInternalADC(); + initBattery(); initRTC(); + initNVDataMgmt(); // Initialize services initCommBuffers(); initFPGA(); @@ -192,6 +197,7 @@ initBloodFlow(); initDialInFlow(); initDialOutFlow(); + initSyringePump(); initValves(); // Initialize modes initOperationModes();