/************************************************************************** * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeTreatment.c * * @date 19-Sep-2019 * @author S. Nash * * @brief Top-level state machine for the treatment mode. * **************************************************************************/ #include "AlarmLamp.h" #include "BloodFlow.h" #include "Buttons.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" #include "Buttons.h" #include "TaskGeneral.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "Timers.h" #include "TreatmentStop.h" #include "ModeTreatment.h" #ifdef RM46_EVAL_BOARD_TARGET #include "Timers.h" static U32 start; #endif // ********** private definitions ********** #define TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) // interval (ms/task time) at which the treatment time data is published on the CAN bus /// Sub-mode states while in treatment mode typedef enum Treatment_States { TREATMENT_START_STATE = 0, ///< Start treatment, prime blood side with gradual ramp for 1 min. while dialyzer is bypassed. No dialysis or UF taking place. TREATMENT_DIALYSIS_STATE, ///< Perform dialysis. Deliver Heparin as prescribed. Deliver UF as prescribed. Handle saline boluses as requested. TREATMENT_STOP_STATE, ///< Treatment stopped. All pumps off. Dializer bypassed. TREATMENT_RINSEBACK_STATE, ///< Perform rinseback with saline. Dialyzer bypassed. Dialysate recirculating. TREATMENT_RINSEBACK_PAUSE_STATE, ///< Rinseback paused. Blood pump off. Dialyzer bypassed. Dialysate recirculating. TREATMENT_RECIRC_SETUP_STATE, ///< Rinseback complete. Blood pump off. Blood lines closed. User to disconnect and shunt blood lines. TREATMENT_RECIRC_STATE, ///< Recirculate saline and dialysate while patient disconnected. Blood lines open and shunted. Dialyzer is bypassed. TREATMENT_RECIRC_PAUSE_STATE, ///< Recirculate paused. Blood pump off. Blood lines closed and shunted. Dialyzer is bypassed. TREATMENT_RECIRC_STOP_STATE, ///< Recirculate stopped. Blood pump off. Blood lines open. Waiting for patient to unshunt and connect and resume treatment. TREATMENT_DIALYSIS_END_STATE, ///< Dialysis has ended. Blood pump slowed. Dialyzer is bypassed. Dialysate is recirculated. User can rinseback. TREATMENT_END_STATE, ///< Treatment has ended. All pumps off. Dialyzer is bypassed. Blood lines are closed. User to disconnect. NUM_OF_TREATMENT_STATES ///< # of treatment states (sub-modes). } TREATMENT_STATE_T; // ********** private data ********** static TREATMENT_STATE_T currentTreatmentState; static U32 presTreatmentTimeSecs; static U32 presBloodFlowRate; static U32 presDialysateFlowRate; static F32 presMaxUFVolumeML; static F32 presUFRate; static U32 treatmentTimeMS; static U32 lastTreatmentTimeStamp; static U32 treatmentTimeBroadcastTimerCtr; static BUTTON_STATE_T lastOffButtonState = BUTTON_STATE_RELEASED; // ********** private function prototypes ********** static TREATMENT_STATE_T handleTreatmentStartState( void ); static TREATMENT_STATE_T handleTreatmentDialysisState( void ); static TREATMENT_STATE_T handleTreatmentStopState( void ); /************************************************************************* * @brief * The initTreatmentMode function initializes the Treatment Mode module. * @details * Inputs : none * Outputs : Treatment Mode module initialized. * @param none * @return none *************************************************************************/ void initTreatmentMode( void ) { currentTreatmentState = TREATMENT_START_STATE; treatmentTimeMS = 0; lastTreatmentTimeStamp = 0; treatmentTimeBroadcastTimerCtr = 0; } /************************************************************************* * @brief * The transitionToTreatmentMode function prepares for transition to treatment mode. * @details * Inputs : none * Outputs : * @param none * @return none *************************************************************************/ void transitionToTreatmentMode( void ) { // initialize treatment mode each time we transition to it initTreatmentMode(); // initialize treatment sub-modes each time we transition to treatment mode initDialysis(); initTreatmentStop(); // temporary test code. TODO - remove later #ifndef UF_TEST_ENABLED setBloodPumpTargetFlowRate( 400, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 400, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 400, MOTOR_DIR_REVERSE, PUMP_CONTROL_MODE_OPEN_LOOP ); #endif #ifdef RM46_EVAL_BOARD_TARGET // TODO - temporary test code for eval board start = getMSTimerCount(); #endif } /************************************************************************* * @brief * The execTreatmentMode function executes the Treatment Mode state machine. * @details * Inputs : none * Outputs : * @param none * @return none *************************************************************************/ void execTreatmentMode( void ) { U32 elapsedTreatmentTimeInSecs; #ifndef UF_TEST_ENABLED BOOL stop = isStopButtonPressed(); if ( TRUE == stop ) { requestNewOperationMode( MODE_POST ); } #else // treatment mode state machine switch ( currentTreatmentState ) { case TREATMENT_START_STATE: currentTreatmentState = handleTreatmentStartState(); break; case TREATMENT_DIALYSIS_STATE: currentTreatmentState = handleTreatmentDialysisState(); break; case TREATMENT_STOP_STATE: currentTreatmentState = handleTreatmentStopState(); break; case TREATMENT_RINSEBACK_STATE: // TODO - implement break; case TREATMENT_RINSEBACK_PAUSE_STATE: // TODO - implement break; case TREATMENT_RECIRC_SETUP_STATE: // TODO - implement break; case TREATMENT_RECIRC_STATE: // TODO - implement break; case TREATMENT_RECIRC_PAUSE_STATE: // TODO - implement break; case TREATMENT_RECIRC_STOP_STATE: // TODO - implement break; case TREATMENT_DIALYSIS_END_STATE: // TODO - implement break; case TREATMENT_END_STATE: // TODO - implement requestNewOperationMode( MODE_POST ); // TODO - test code - remove later break; default: // TODO - s/w fault break; } // update treatment time stats and broadcast - end treatment if time elapsedTreatmentTimeInSecs = treatmentTimeMS / MS_PER_SECOND; if ( elapsedTreatmentTimeInSecs >= presTreatmentTimeSecs ) { stopDialysis(); elapsedTreatmentTimeInSecs = presTreatmentTimeSecs; currentTreatmentState = TREATMENT_END_STATE; } // broadcast treatment time and state data at interval if ( ++treatmentTimeBroadcastTimerCtr >= TREATMENT_TIME_DATA_PUB_INTERVAL ) { U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; DIALYSIS_STATE_T dialysisState = getDialysisState(); UF_STATE_T uFState = getUltrafiltrationState(); BOOL salineBolusInProgress = ( dialysisState == DIALYSIS_SOLUTION_INFUSION_STATE ? TRUE : FALSE ); broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, timeRemaining ); broadcastTreatmentState( currentTreatmentState, uFState, salineBolusInProgress ); treatmentTimeBroadcastTimerCtr = 0; } #endif #ifdef RM46_EVAL_BOARD_TARGET // TODO - temporary test code for eval board - move to next mode after 10 sec if ( TRUE == didTimeout( start, 10000U ) ) { // requestNewOperationMode( MODE_POST ); } #endif } /************************************************************************* * @brief * The handleTreatmentStartState function handles the Start state of \n * the Treatment Mode state machine. * @details * Inputs : none * Outputs : none * @param none * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentStartState( void ) { TREATMENT_STATE_T result = TREATMENT_DIALYSIS_STATE; // initialize treatment time treatmentTimeMS = 0; lastTreatmentTimeStamp = getMSTimerCount(); // get prescription settings TODO - hard-coded for now presTreatmentTimeSecs = 3600; presBloodFlowRate = 300; presDialysateFlowRate = 400; presMaxUFVolumeML = 300.0; presUFRate = 10.0; // kick dialysis sub-mode off setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); startDialysis(); return result; } /************************************************************************* * @brief * The handleTreatmentDialysisState function handles the Dialysis state of \n * the Treatment Mode state machine. * @details * Inputs : none * Outputs : none * @param none * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentDialysisState( void ) { TREATMENT_STATE_T result = TREATMENT_DIALYSIS_STATE; U32 newTime = getMSTimerCount(); U32 msSinceLast = calcTimeBetween( lastTreatmentTimeStamp, newTime ); // update treatment time treatmentTimeMS += msSinceLast; lastTreatmentTimeStamp = newTime; // execute state machine for treatment dialysis sub-mode execDialysis(); // TODO - test code - remove later if ( getOffButtonState() == BUTTON_STATE_PRESSED ) { if ( lastOffButtonState == BUTTON_STATE_RELEASED ) { lastOffButtonState = BUTTON_STATE_PRESSED; stopDialysis(); result = TREATMENT_STOP_STATE; } } else { lastOffButtonState = BUTTON_STATE_RELEASED; } return result; } /************************************************************************* * @brief * The handleTreatmentStopState function executes the Stop state of the \n * Treatment Mode state machine. * @details * Inputs : none * Outputs : none * @param none * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentStopState( void ) { TREATMENT_STATE_T result = TREATMENT_STOP_STATE; // execute state machine for treatment stop sub-mode execTreatmentStop(); // TODO - test code - remove later if ( getOffButtonState() == BUTTON_STATE_PRESSED ) { if ( lastOffButtonState == BUTTON_STATE_RELEASED ) { lastOffButtonState = BUTTON_STATE_PRESSED; lastTreatmentTimeStamp = getMSTimerCount(); startDialysis(); result = TREATMENT_DIALYSIS_STATE; } } else { lastOffButtonState = BUTTON_STATE_RELEASED; } return result; } /************************************************************************* * @brief * The verifyUFSettingsChange function verifies new ultrafiltration settings \n * from the user. * @details * Inputs : none * Outputs : none * @param uFVolume : . * @param adjustment : . * @return TRUE if new UF settings valid, FALSE if not. *************************************************************************/ BOOL verifyUFSettingsChange( F32 uFVolume, UF_ADJ_T adjustment ) { BOOL result = FALSE; OP_MODE currMode = getCurrentOperationMode(); // check if we are in treatment mode if ( MODE_TREA == currMode ) { // check } //sendChangeUFSettingsResponse( BOOL accepted, U32 volume_mL, U32 time_min, F32 ufRate_mL_min, U32 timeDiff, F32 rateDiff ); return result; } /************************************************************************* * @brief * The verifyUFSettingsConfirmation function verifies the user confirmed \n * ultrafiltration settings change(s) and, if valid, implements the new settings. * @details * Inputs : none * Outputs : none * @param confirmed : . * @param uFVolume : . * @param treatmentTime : . * @param uFRate : . * @return next treatment mode state *************************************************************************/ BOOL verifyUFSettingsConfirmation( BOOL confirmed, F32 uFVolume, U32 treatmentTime, F32 uFRate ) { BOOL result = FALSE; return result; }