/************************************************************************** * * 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 "Common.h" #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 at interval if ( ++treatmentTimeBroadcastTimerCtr >= TREATMENT_TIME_DATA_PUB_INTERVAL ) { broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, presTreatmentTimeSecs - elapsedTreatmentTimeInSecs ); 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 = 20.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; }