/************************************************************************** * * Copyright (c) 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 Dialysis.c * * @date 15-Jan-2020 * @author S. Nash * * @brief State machine for the dialysis sub-mode of treatment mode. * **************************************************************************/ #include "BloodFlow.h" #include "Buttons.h" #include "Dialysis.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "OperationModes.h" #include "Timers.h" #include "ModeTreatment.h" // ********** private definitions ********** typedef enum Dialysis_States { DIALYSIS_START_STATE = 0, DIALYSIS_UF_STATE, DIALYSIS_SOLUTION_INFUSION_STATE, NUM_OF_DIALYSIS_STATES } DIALYSIS_STATE_T; typedef enum UF_States { UF_START_STATE = 0, UF_PAUSED_STATE, UF_RUNNING_STATE, UF_COMPLETED_OR_OFF_STATE, NUM_OF_UF_STATES } UF_STATE_T; // ********** private data ********** static DIALYSIS_STATE_T currentDialysisState; static UF_STATE_T currentUFState; static F32 refUFVolume; static F32 measUFVolume; static F32 resStartVolume; static F32 measUFVolumeFromPriorReservoirs; static U32 uFTimeMS; static U32 lastUFTimeStamp; static U32 setBloodFlowRate; static U32 setDialysateFlowRate; static F32 maxUFVolumeML; static F32 setUFRate; // ********** private function prototypes ********** static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSolutionInfusionState( void ); static UF_STATE_T handleUFStartState( void ); static UF_STATE_T handleUFPausedState( void ); static UF_STATE_T handleUFRunningState( void ); static UF_STATE_T handleUFCompletedOrOffState( void ); static void updateUFVolumes( void ); /************************************************************************* * @brief * The initDialysis function initializes the Dialysis module. * @details * Inputs : none * Outputs : Dialysis module initialized. * @param none * @return none *************************************************************************/ void initDialysis( void ) { currentDialysisState = DIALYSIS_START_STATE; currentUFState = UF_START_STATE; refUFVolume = 0.0; measUFVolume = 0.0; resStartVolume = 0.0; measUFVolumeFromPriorReservoirs = 0.0; uFTimeMS = 0; lastUFTimeStamp = 0; setBloodFlowRate = 0; setDialysateFlowRate = 0; maxUFVolumeML = 0.0; setUFRate = 0.0; } /************************************************************************* * @brief * The transitionToDialysis function prepares for transition to dialysis sub-mode. * @details * Inputs : none * Outputs : * @param none * @return none *************************************************************************/ void transitionToDialysis( void ) { // while in treatment mode, we may transition in and out of dialysis sub-mode. // we'll want to retain our state to facilitate resumption of dialysis. } /************************************************************************* * @brief * The setDialysisParams function sets the dialysis treatment parameters. * @details * Inputs : none * Outputs : dialysis treatment parameters are set. * @param bPFlow : target blood pump flow rate (in mL/min). * @param dPFlow : target dialysate inlet pump flow rate (in mL/min). * @param maxUFVol : maximum ultrafiltration volume (in mL). * @param uFRate : target ultrafiltration rate (in mL/min). * @return none *************************************************************************/ void setDialysisParams( U32 bPFlow, U32 dPFlow, F32 maxUFVol, F32 uFRate ) { setBloodFlowRate = bPFlow; setDialysateFlowRate = dPFlow; maxUFVolumeML = maxUFVol; setUFRate = uFRate; } /************************************************************************* * @brief * The startDialysis function starts/resumes dialysis. * @details * Inputs : none * Outputs : none * @return none *************************************************************************/ void startDialysis( void ) { lastUFTimeStamp = getMSTimerCount(); setDialOutUFVolumes( refUFVolume, measUFVolume ); setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } /************************************************************************* * @brief * The stopDialysis function stops dialysis. This may be due to an alarm \n * or user pressed the stop button. Dialysis may be resumed later. * @details * Inputs : none * Outputs : none * @return none *************************************************************************/ void stopDialysis( void ) { setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } /************************************************************************* * @brief * The execDialysis function executes the Dialysis sub-mode state machine. * @details * Inputs : currentDialysisState * Outputs : currentDialysisState * @param none * @return none *************************************************************************/ void execDialysis( void ) { switch ( currentDialysisState ) { case DIALYSIS_START_STATE: resStartVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); // always start dialysis w/ reservoir 1 currentDialysisState = DIALYSIS_UF_STATE; break; case DIALYSIS_UF_STATE: currentDialysisState = handleDialysisUltrafiltrationState(); break; case DIALYSIS_SOLUTION_INFUSION_STATE: currentDialysisState = handleDialysisSolutionInfusionState(); break; default: // TODO - s/w fault break; } } /************************************************************************* * @brief * The handleDialysisUltrafiltrationState function handles the ultrafiltration \n * state of the Dialysis state machine. * @details * Inputs : none * Outputs : none * @return next Dialysis state. *************************************************************************/ static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ) { DIALYSIS_STATE_T result = DIALYSIS_UF_STATE; switch ( currentUFState ) { case UF_START_STATE: currentUFState = handleUFStartState(); break; case UF_PAUSED_STATE: currentUFState = handleUFPausedState(); break; case UF_RUNNING_STATE: currentUFState = handleUFRunningState(); break; case UF_COMPLETED_OR_OFF_STATE: currentUFState = handleUFCompletedOrOffState(); break; default: // TODO - s/w fault break; } return result; } /************************************************************************* * @brief * The handleDialysisSolutionInfusionState function handles the solution \n * infustion state of the Dialysis state machine. * @details * Inputs : none * Outputs : none * @return next Dialysis state. *************************************************************************/ static DIALYSIS_STATE_T handleDialysisSolutionInfusionState( void ) { DIALYSIS_STATE_T result = DIALYSIS_SOLUTION_INFUSION_STATE; return result; } /************************************************************************* * @brief * The handleUFStartState function handles the Start state of the \n * ultrafiltration state machine. * @details * Inputs : none * Outputs : none * @return next ultrafiltration state. *************************************************************************/ static UF_STATE_T handleUFStartState( void ) { UF_STATE_T result; if ( maxUFVolumeML < NEARLY_ZERO ) { result = UF_COMPLETED_OR_OFF_STATE; } else { lastUFTimeStamp = getMSTimerCount(); uFTimeMS = 0; result = UF_RUNNING_STATE; } return result; } /************************************************************************* * @brief * The handleUFPausedState function handles the Paused state of the \n * ultrafiltration state machine. * @details * Inputs : none * Outputs : none * @return next ultrafiltration state. *************************************************************************/ static UF_STATE_T handleUFPausedState( void ) { UF_STATE_T result = UF_PAUSED_STATE; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); // TODO - test code - remove later if ( TRUE == isStopButtonPressed() ) { lastUFTimeStamp = getMSTimerCount(); // restart UF time accumulation result = UF_RUNNING_STATE; } return result; } /************************************************************************* * @brief * The handleUFRunningState function handles the Running state of the \n * ultrafiltration state machine. * @details * Inputs : none * Outputs : none * @return next ultrafiltration state. *************************************************************************/ static UF_STATE_T handleUFRunningState( void ) { UF_STATE_T result = UF_RUNNING_STATE; U32 newTime = getMSTimerCount(); U32 msSinceLast = calcTimeBetween( lastUFTimeStamp, newTime ); // update UF time uFTimeMS += msSinceLast; lastUFTimeStamp = newTime; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); // TODO - test code - remove later if ( TRUE == isStopButtonPressed() ) { result = UF_PAUSED_STATE; } return result; } /************************************************************************* * @brief * The handleUFCompletedOrOffState function handles the UF Completed or Off \n * state of the ultrafiltration state machine. * @details * Inputs : none * Outputs : none * @return next ultrafiltration state *************************************************************************/ static UF_STATE_T handleUFCompletedOrOffState( void ) { UF_STATE_T result = UF_COMPLETED_OR_OFF_STATE; // calculate UF volumes and provide to dialysate outlet pump controller updateUFVolumes(); // TODO - test code - remove later if ( TRUE == isStopButtonPressed() ) { // do nothing } return result; } /************************************************************************* * @brief * The updateUFVolumes function updates the ultrafiltration volumes based on \n * set UF rate, latest UF elapsed time, and the latest load cell weight for the \n * currently used reservoir. Updated UF volumes are then sent to the dialysate \n * outlet pump controller. * @details * Inputs : setUFRate, uFTimeMS, load cell weight * Outputs : refUFVolume, measUFVolume * @return none *************************************************************************/ static void updateUFVolumes( void ) { F32 latestResVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); // TODO - just res 1 for now - add reservoir switching, mgmt later. // calculate UF volumes and provide to dialysate outlet pump controller refUFVolume = ( ( (F32)uFTimeMS / MS_PER_SECOND ) / SEC_PER_MIN ) * setUFRate; measUFVolume = measUFVolumeFromPriorReservoirs + ( latestResVolume - resStartVolume ); setDialOutUFVolumes( refUFVolume, measUFVolume ); }