Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r44a100f8e5210a02c23b8fcc4527d8e96d577381 -r99291dfcff27720fde696dfe4d262dc003d85d1a --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 44a100f8e5210a02c23b8fcc4527d8e96d577381) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 99291dfcff27720fde696dfe4d262dc003d85d1a) @@ -1,19 +1,21 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 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 DGInterface.c +* @file DGInterface.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Dara Navaei +* @date (last) 15-Jul-2022 * -* @author (original) Sean -* @date (original) 08-Apr-2020 +* @author (original) Sean +* @date (original) 08-Apr-2020 * ***************************************************************************/ + +#include // To check for NaN #include "DialInFlow.h" #include "Dialysis.h" @@ -23,6 +25,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Timers.h" @@ -33,85 +36,74 @@ // ********** private definitions ********** -#define START_DG_CMD TRUE ///< Parameter for DG start/stop command function. True = start. -#define STOP_DG_CMD FALSE ///< Parameter for DG start/stop command function. False = stop. - -#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Time (in ms) allotted for reservoir to settle (after fill, before drain). +#define START_DG_CMD TRUE ///< Parameter for DG start/stop command function. True = start. +#define STOP_DG_CMD FALSE ///< Parameter for DG start/stop command function. False = stop. -#define MAX_RESERVOIR_VOLUME_ML 1950.0 ///< Maximum reservoir volume. Switch reservoirs if active reservoir exceeds this volume. +#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. -#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 2.0F ///< Dialysate temperature out of target tolerance C. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. +#define DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C 46.0F ///< Dialysate high safety temperature limit in C. +#define DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature high safety timeout in milliseconds. +#define DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C 42.0F ///< Dialysate low safety temperature limit in C. +#define DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature low safety timeout in milliseconds. -/// States of the treatment reservoir management state machine. -typedef enum TreatmentReservoirMgmt_States -{ - TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< If DG not already in re-circ mode, try to get it there. - TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE, ///< In DG re-circ, wait for lines to flush - then start draining inactive reservoir. - TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE, ///< Wait for drain to complete. - TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE, ///< Wait to fill inactive reservoir (if appropriate) - then start filling inactive reservoir. - TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE, ///< Wait for fill to complete. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE, ///< Wait a bit for filled reservoir to settle before getting baseline weight (volume). - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE, ///< Wait for active reservoir to be consumed and switch cmd given - then back to flush DG lines state. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Wait for inactive reservoir to settle before getting final weight (volume) before starting to drain. - NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir mgmt. states. -} TREATMENT_RESERVOIR_MGMT_STATE_T; - // ********** private data ********** // DG status -static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. -static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. -static BOOL dgStartCommandSent = FALSE; ///< Flag indicates command to start DG has been sent. -static BOOL dgStarted = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop. +static DG_OP_MODE_T dgCurrentOpMode; ///< Current DG operation mode. +static U32 dgSubMode; ///< Current state (sub-mode) of current DG operation mode. +static BOOL dgStartCommandSent; ///< Flag indicates command to start DG has been sent. +static BOOL dgStarted; ///< Flag indicates whether we have commanded the DG to start or stop. static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. // State machine states -/// Current state of treatment mode reservoir management. -static TREATMENT_RESERVOIR_MGMT_STATE_T currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; -static U32 resMgmtTimer = 0; ///< Used for keeping state time. +static U32 timeStartMS = 0; // TODO is this needed? // DG sensor data -static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. -static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. +static F32 dgDialysateTemp; ///< Dialysate temperature reported by the DG. static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. -static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. -static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. +static F32 dgTrimmerTempSet; ///< Trimmer heater target temperature commanded. static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. /// Measured weight from load cells. static OVERRIDE_F32_T loadCellWeightInGrams[ NUM_OF_LOAD_CELLS ]; /// Filtered (32 sample) weight of reservoirs. static F32 lgFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; +static F32 lgFilteredReservoirBackupWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; // Load cell filtering data -/// Holds load cell samples for large load cell moving average. -static F32 lgLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; -static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. -static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. +static F32 lgLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Holds load cell samples for large load cell moving average. +static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. +static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. +static F32 lgLoadCellBackupReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Holds load cell samples for large load cell moving average. +static F32 lgLoadCellBackupReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. -// DG pumps data -static F32 dgROPumpFlowRateMlMin = 0.0; ///< Latest RO water flow rate reported by the DG. -static U32 dgROPumpPressureSetPtPSI = 0; ///< Latest RO pump target pressure reported by the DG. -static U32 dgDrainPumpSpeedSetPtRPM = 0; ///< Latest Drain pump target speed reported by the DG. - +// DG Dialysate flow rate +static F32 dgDialysateFlowRateMlMin; ///< Latest dialysate flow rate reported by the DG. +static BOOL dgDialysateFlowDataFreshFlag; ///< Flag to signal the execDialInFlowMonitor() to process fresh flow rate data + // Reservoir data -static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. -static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. +static DG_RESERVOIR_ID_T dgActiveReservoir; ///< Latest active reservoir reported by the DG. +static DG_RESERVOIR_ID_T dgActiveReservoirSet; ///< Active reservoir commanded. + +// TODO remove below variables static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. static U32 dgReservoirFillVolumeTargetSet = 0; ///< Fill-to volume commanded. static U32 dgReservoirDrainVolumeTarget = 0; ///< Latest drain-to volume reported by the DG. static U32 dgReservoirDrainVolumeTargetSet = 0; ///< Drain-to volume commanded. -static U32 resUseTimer = 0; ///< Used to track time pumping from active reservoir (for volume used calculation). -static F32 resUseVolumeMl = 0.0; ///< Accumulated volume used from active reservoir. +static DG_DISINFECT_UI_STATES_T disinfectsStatus; ///< DG disinfects status. +static DG_MIXING_RATIOS_T dgMixingRatios; ///< DG mixing ratios. + // DG command response static DG_CMD_RESPONSE_T dgCmdResp[ NUM_OF_DG_COMMANDS ]; ///< Keep the latest DG command response for each command. // ********** private function prototypes ********** -static void checkDGRestart( void ); - +static void checkDGRestart( void ); + /*********************************************************************//** * @brief * The initDGInterface function initializes the DGInterface module. @@ -123,29 +115,37 @@ { U32 i, j; - dgStarted = FALSE; - dgTrimmerHeaterOn = FALSE; - dgPrimaryTempSet = 0.0; - dgTrimmerTempSet = 0.0; - dgActiveReservoirSet = DG_RESERVOIR_2; - dgReservoirFillVolumeTargetSet = 0; - dgReservoirDrainVolumeTargetSet = 0; + dgStarted = FALSE; + dgTrimmerHeaterOn = FALSE; + dgTrimmerTempSet = 0.0F; + dgActiveReservoirSet = DG_RESERVOIR_2; + dgActiveReservoir = DG_RESERVOIR_2; + dgReservoirFillVolumeTargetSet = 0; + dgReservoirDrainVolumeTargetSet = 0; + dgDialysateTemp = 0.0F; + dgCurrentOpMode = DG_MODE_INIT; + dgSubMode = 0; + dgStartCommandSent = FALSE; + dgDialysateFlowRateMlMin = 0.0; + dgDialysateFlowDataFreshFlag = FALSE; // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - loadCellWeightInGrams[ i ].data = 0.0; + loadCellWeightInGrams[ i ].data = 0.0; loadCellWeightInGrams[ i ].ovInitData = 0.0; - loadCellWeightInGrams[ i ].ovData = 0.0; - loadCellWeightInGrams[ i ].override = 0; + loadCellWeightInGrams[ i ].ovData = 0.0; + loadCellWeightInGrams[ i ].override = 0; } // initialize reservoirs weights for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) { lgFilteredReservoirWeightInGrams[ i ] = 0.0; + for ( j = 0; j < SIZE_OF_LARGE_LOAD_CELL_AVG; j++ ) { - lgLoadCellReadings[ i ][ j ] = 0.0; + lgLoadCellReadings[ i ][ j ] = 0.0; + lgLoadCellBackupReadings[ i ][ j ] = 0.0; } } @@ -157,9 +157,17 @@ dgCmdResp[ i ].rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } - lgLoadCellReadingsIdx = 0; - lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; - lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + lgLoadCellReadingsIdx = 0; + lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; + lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ); + + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); } /*********************************************************************//** @@ -178,23 +186,6 @@ checkDGRestart(); } - -/*********************************************************************//** - * @brief - * The initTreatmentReservoirMgmt function initializes the treatment reservoir - * management state machine. - * @details Inputs: none - * @details Outputs: treatment reservoir management state machine initialized. - * @return none - *************************************************************************/ -void initTreatmentReservoirMgmt( void ) -{ - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; - resMgmtTimer = 0; - resUseTimer = getMSTimerCount(); - resUseVolumeMl = 0.0; -} - /*********************************************************************//** * @brief * The dialysisResumed function initializes the reservoir re-use timer @@ -205,158 +196,11 @@ *************************************************************************/ void dialysisResumed( void ) { - resUseTimer = getMSTimerCount(); + timeStartMS = getMSTimerCount(); } /*********************************************************************//** * @brief - * The execTreatmentReservoirMgmt function executes the state machine for the - * reservoir management during treatment mode. - * @details Inputs: none - * @details Outputs: DG reservoirs (drains & fills) managed. - * @return none - *************************************************************************/ -void execTreatmentReservoirMgmt( void ) -{ - DG_OP_MODE_T dgOpMode = getDGOpMode(); - U32 dgSubMode = getDGSubMode(); - U32 msSinceLastVolumeCalc = calcTimeSince( resUseTimer ); - F32 flowRateMlPerMs = (F32)getTargetDialInFlowRate() / (F32)( MS_PER_SECOND * SEC_PER_MIN ); - - // Calculate volume used from active reservoir - do not accumulate if saline bolus in progress - if ( SALINE_BOLUS_STATE_IN_PROGRESS != getSalineBolusState() ) - { - resUseVolumeMl += ( flowRateMlPerMs * msSinceLastVolumeCalc ); - } - resUseTimer = getMSTimerCount(); - - // Alarm if active reservoir is full and inactive reservoir is not yet ready - if ( getReservoirWeight( getDGActiveReservoir() ) > MAX_RESERVOIR_VOLUME_ML ) - { - if ( currentTrtResMgmtState < TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_RESERVOIR_FULL_AND_DG_NOT_READY_TO_SWITCH, getReservoirWeight( getDGActiveReservoir() ), (F32)currentTrtResMgmtState ) - } - else - { - clearAlarmCondition( ALARM_ID_HD_RESERVOIR_FULL_AND_DG_NOT_READY_TO_SWITCH ); - } - } - - // Treatment reservoir mgmt. state machine - switch ( currentTrtResMgmtState ) - { - case TREATMENT_RESERVOIR_MGMT_START_STATE: - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; - break; - - case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: - if ( DG_MODE_CIRC == dgOpMode ) - { - if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) - { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, FALSE ); - } - } - else if ( DG_MODE_DRAI == dgOpMode ) - { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE; - } - else - { - // TODO - ??? - } - break; - - case TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE: - if ( DG_MODE_CIRC == dgOpMode ) - { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; - } - break; - - case TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE: - // Delay fill start if we have paused treatment? - if ( getTreatmentState() == TREATMENT_DIALYSIS_STATE ) - { - if ( DG_MODE_CIRC == dgOpMode ) - { - if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) - { - U32 fillToVolume = FILL_RESERVOIR_TO_VOLUME_ML; - - if ( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) <= SLOW_DIALYSATE_FLOW_ML_MIN ) - { - fillToVolume = FILL_RESERVOIR_TO_VOLUME_LOW_FLOW_ML; - } - cmdStartDGFill( fillToVolume ); - } - } - else - { - // TODO - ??? - } - } - if ( DG_MODE_FILL == dgOpMode ) - { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; - } - break; - - case TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE: - if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getDGSubMode() ) ) - { - resMgmtTimer = getMSTimerCount(); - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; - } - break; - - case TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE: - if ( TRUE == didTimeout( resMgmtTimer, RESERVOIR_SETTLE_TIME_MS ) ) - { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE; - } - break; - - case TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE: - // Reservoir switch during treatment should only occur in this state (i.e. when DG is ready). - // Switch reservoirs when active reservoir is spent or full (i.e. we have pumped fill volume through dialyzer) and DG ready - if ( ( resUseVolumeMl >= (F32)dgReservoirFillVolumeTargetSet ) || ( getReservoirWeight( getDGActiveReservoir() ) > MAX_RESERVOIR_VOLUME_ML ) ) - { - DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); - - // Signal dialysis sub-mode to capture baseline volume for next reservoir. - setStartReservoirVolume( inactiveRes ); - // Command DG to switch reservoirs - cmdSetDGActiveReservoir( inactiveRes ); - // Signal dialysis sub-mode to switch reservoirs - signalReservoirsSwitched(); - resUseVolumeMl = 0.0; - // Wait for used reservoir to settle - resMgmtTimer = getMSTimerCount(); - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; - } - break; - - case TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE: - if ( TRUE == didTimeout( resMgmtTimer, RESERVOIR_SETTLE_TIME_MS ) ) - { - // Signal dialysis sub-mode to capture final volume of prior reservoir after settling. - setFinalReservoirVolume(); - // Reset to start state to restart drain, fill, switch process. - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; - } - break; - - default: - // TODO - s/w fault - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; - break; - } -} - -/*********************************************************************//** - * @brief * The getDGOpMode function gets the current DG operating mode. * @details Inputs: dgCurrentOpMode * @details Outputs: none @@ -418,76 +262,38 @@ return ( dgActiveReservoir == dgActiveReservoirSet ); } -/*********************************************************************//** - * @brief - * The getDGPressure function gets the latest pressure reported by the DG - * for a given pressure sensor. - * @details Inputs: dgPressures[] - * @details Outputs: none - * @param sensorID pressure sensor we are getting reading for - * @return Latest pressure reading reported by DG for the given sensor. - *************************************************************************/ -F32 getDGPressure( DG_PRESSURE_SENSORS_T sensorID ) -{ - F32 result = 0.0; - - if ( sensorID < NUM_OF_DG_PRESSURE_SENSORS ) - { - result = dgPressures[ sensorID ]; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_PRESSURE_ID, sensorID ) - } - - return result; +/*********************************************************************//** + * @brief + * The getDGDialysateFlowRateLMin function gets the latest dialysate flow + * rate reported by the DG. + * @details Inputs: dgDialysateFlowRateMlMin + * @details Outputs: none + * @return Latest dialysate flow rate (in L/min) reported by DG. + *************************************************************************/ +F32 getDGDialysateFlowRateLMin( void ) +{ + F32 result = dgDialysateFlowRateMlMin; + + return result; } + +/*********************************************************************//** + * @brief + * The getDialysateFlowDataFreshFlag function returns a flag to indicate + * if the dialysate flow rate data reported by the DG is fresh or stale data. + * @details Inputs: dgDialysateFlowDataFreshFlag + * @details Outputs: dgDialysateFlowDataFreshFlag + * @return T/F flag to indicate fresh/stale status of dialysate flow data. + *************************************************************************/ +BOOL getDialysateFlowDataFreshFlag( void ) +{ + BOOL result = dgDialysateFlowDataFreshFlag; + + dgDialysateFlowDataFreshFlag = FALSE; + + return result; +} -/*********************************************************************//** - * @brief - * The getDGROPumpPressureSetPt function gets the latest RO pump - * pressure set point reported by the DG. - * @details Inputs: dgROPumpPressureSetPtPSI - * @details Outputs: none - * @return Latest RO pump pressure set point reported by DG. - *************************************************************************/ -U32 getDGROPumpPressureSetPt( void ) -{ - U32 result = dgROPumpPressureSetPtPSI; - - return result; -} - -/*********************************************************************//** - * @brief - * The getDGROPumpFlowRateMlMin function gets the latest RO pump flow - * rate reported by the DG. - * @details Inputs: dgROPumpFlowRateMlMin - * @details Outputs: none - * @return Latest RO pump flow rate reported by DG. - *************************************************************************/ -F32 getDGROPumpFlowRateMlMin( void ) -{ - F32 result = dgROPumpFlowRateMlMin; - - return result; -} - -/*********************************************************************//** - * @brief - * The getDGDrainPumpRPMSetPt function gets the latest drain pump RPM - * set point reported by the DG. - * @details Inputs: dgDrainPumpSpeedSetPtRPM - * @details Outputs: none - * @return Latest drain pump RPM set point reported by DG. - *************************************************************************/ -U32 getDGDrainPumpRPMSetPt( void ) -{ - U32 result = dgDrainPumpSpeedSetPtRPM; - - return result; -} - /*********************************************************************//** * @brief * The getLoadCellWeight function gets the current load cell weight. @@ -542,8 +348,65 @@ /*********************************************************************//** * @brief - * The getReservoirWeight function gets the load cell weight of a given - * reservoir. + * The getReservoirBackupWeightLargeFilter function gets the backup load cell weight + * of the given reservoir after large (32 sample) filter applied. + * @details Inputs: lgFilteredReservoirWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get filtered weight for + * @return the current filtered weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirBackupWeightLargeFilter( DG_RESERVOIR_ID_T resID ) +{ + F32 result = 0.0; + + if ( resID < NUM_OF_DG_RESERVOIRS ) + { + result = lgFilteredReservoirBackupWeightInGrams[ resID ]; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getDialysateTemperature function gets the latest dialysate temperature. + * @details Inputs: dgDialysateTemp + * @details Outputs: none + * @return the current dialysate temperature + *************************************************************************/ +F32 getDialysateTemperature( void ) +{ + return dgDialysateTemp; +} + +/*********************************************************************//** + * @brief + * The getDGDisinfectsStates function returns the DG disinfects readings. + * @details Inputs: none + * @details Outputs: none + * @return the current DG disinfects readings + *************************************************************************/ +DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +{ + return disinfectsStatus; +} + +/*********************************************************************//** + * @brief + * The getDGMixingRatios function returns the DG mixing ratios and the fill + * prep time. + * @details Inputs: none + * @details Outputs: none + * @return getDGMixingRatios which is the DG mixing ratios + *************************************************************************/ +DG_MIXING_RATIOS_T getDGMixingRatios( void ) +{ + return dgMixingRatios; +} + +/*********************************************************************//** + * @brief + * The getReservoirWeight function gets the load cell weight of a given reservoir. * @details Inputs: loadCellWeightInGrams[] * @details Outputs: none * @param resID ID of reservoir to get weight for @@ -562,7 +425,7 @@ * The setDGOpMode function sets the latest DG operating mode reported by * the DG. * @details Inputs: none - * @details Outputs: dgCurrentOpMode + * @details Outputs: dgCurrentOpMode, dgSubMode * @param opMode operating mode reported by DG * @param subMode sub-mode (current state) of operating mode reported by DG * @return none @@ -598,22 +461,6 @@ /*********************************************************************//** * @brief - * The setDGDialysateTemperatures function sets the latest temperature data - * reported by the DG. - * @details Inputs: none - * @details Outputs: dgPrimaryTemp, dgTrimmerTemp - * @param primaryHtrTemp Primary heater temperature reported by DG - * @param trimmerHtrTemp Trimmer heater temperature reported by DG - * @return none - *************************************************************************/ -void setDGDialysateTemperatures( F32 primaryHtrTemp, F32 trimmerHtrTemp ) -{ - dgPrimaryTemp = primaryHtrTemp; - dgTrimmerTemp = trimmerHtrTemp; -} - -/*********************************************************************//** - * @brief * The setDGReservoirsData function sets the latest reservoir data * reported by the DG. * @details Inputs: none @@ -636,56 +483,30 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, resID ); } } - -/*********************************************************************//** - * @brief - * The setDGPressures function sets the latest pressures reported by the DG. - * @details Inputs: none - * @details Outputs: dgPressures[] - * @param roIn latest RO pump inlet pressure reported by DG - * @param roOut latest RO pump outlet pressure reported by DG - * @param drainIn latest drain pump inlet pressure reported by DG - * @param drainOut latest drain pump outlet pressure reported by DG - * @return none - *************************************************************************/ -void setDGPressures( F32 roIn, F32 roOut, F32 drainIn, F32 drainOut ) -{ - dgPressures[ DG_PRESSURE_SENSOR_RO_PUMP_INLET ] = roIn; - dgPressures[ DG_PRESSURE_SENSOR_RO_PUMP_OUTLET ] = roOut; - dgPressures[ DG_PRESSURE_SENSOR_DRAIN_PUMP_INLET ] = drainIn; - dgPressures[ DG_PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] = drainOut; -} - -/*********************************************************************//** - * @brief - * The setDGROPumpData function sets the latest RO pump data reported by the DG. - * @details Inputs: none - * @details Outputs: dgROPumpPressureSetPtPSI, dgROPumpFlowRateMlMin - * @param presSetPt latest RO pump pressure set point reported by DG - * @param flowRate latest RO pump flow rate (LPM) reported by DG - * @return none - *************************************************************************/ -void setDGROPumpData( U32 presSetPt, F32 flowRate ) -{ - dgROPumpPressureSetPtPSI = presSetPt; - dgROPumpFlowRateMlMin = flowRate * ML_PER_LITER; -} - -/*********************************************************************//** - * @brief - * The setDGDrainPumpData function sets the latest drain pump data reported by the DG. - * @details Inputs: none - * @details Outputs: dgDrainPumpSpeedSetPtRPM - * @param rpmSetPt latest drain pump RPM set point reported by DG - * @return none - *************************************************************************/ -void setDGDrainPumpData( U32 rpmSetPt ) -{ - dgDrainPumpSpeedSetPtRPM = rpmSetPt; -} - + /*********************************************************************//** * @brief + * The setDialysateFlowData function sets the latest dialysate flow rate + * and its freshness status. The dialysate flow data is reported by the DG. + * @details Inputs: none + * @details Outputs: dgDialysateFlowRateMlMin + * @param flowRate latest dialysate flow rate (mL/min) reported by DG + * @return none + *************************************************************************/ +void setDialysateFlowData( F32 flowRate ) +{ + // Check if the sent value by DG is a NaN + if ( isnan( flowRate ) ) + { + flowRate = 0.0; + } + + dgDialysateFlowRateMlMin = flowRate; + dgDialysateFlowDataFreshFlag = TRUE; +} + +/*********************************************************************//** + * @brief * The setNewLoadCellReadings function sets the latest DG reservoir load cell * readings sent by the DG (in g or mL). New readings are expected once * every 100 ms. @@ -717,28 +538,61 @@ lgLoadCellReadings[ res ][ lgLoadCellReadingsIdx ] = wt; lgLoadCellReadingsTotal[ res ] += wt; lgFilteredReservoirWeightInGrams[ res ] = lgLoadCellReadingsTotal[ res ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; + + wt = ( res == DG_RESERVOIR_1 ? res1Backup : res2Backup ); + lgLoadCellBackupReadingsTotal[ res ] -= lgLoadCellBackupReadings[ res ][ lgLoadCellReadingsIdx ]; + lgLoadCellBackupReadings[ res ][ lgLoadCellReadingsIdx ] = wt; + lgLoadCellBackupReadingsTotal[ res ] += wt; + lgFilteredReservoirBackupWeightInGrams[ res ] = lgLoadCellBackupReadingsTotal[ res ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; } lgLoadCellReadingsIdx = INC_WRAP( lgLoadCellReadingsIdx, 0, SIZE_OF_LARGE_LOAD_CELL_AVG - 1 ); // Update Dialysis sub-mode with new reservoir volumes updateReservoirVolumes( res1Primary, res2Primary ); } +/*********************************************************************//** + * @brief + * The setDGDisinfectsStates function sets the latest disinfects states + * from DG. + * @details Inputs: none + * @details Outputs: disinfectsStatus + * @param states latest DG disinfects state readings + * @return none + *************************************************************************/ +void setDGDisinfectsStates( DG_DISINFECT_UI_STATES_T states ) +{ + memcpy( &disinfectsStatus, &states, sizeof(DG_DISINFECT_UI_STATES_T) ); +} + +/*********************************************************************//** + * @brief + * The setDGMixingRatios function sets the mixing ratios as well as the fill + * prep time upon a request from DG. + * @details Inputs: none + * @details Outputs: dgMixingRatios + * @param ratios the mixing ratios from DG + * @return none + *************************************************************************/ +void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ) +{ + memcpy( &dgMixingRatios, &ratios, sizeof(DG_MIXING_RATIOS_T) ); +} + /*********************************************************************//** * @brief - * The cmdSetDGDialysateTargetTemps function sends a target dialysate - * temperature command message to the DG. + * The cmdSetDGDialysateHeatingParams function sends the dialysate heating + * parameters to DG. * @details Inputs: none - * @details Outputs: dgPrimaryTempSet, dgTrimmerTempSet - * @param primaryHtrTemp commanded target dialysate temperature for the primary heater - * @param trimmerHtrTemp commanded target dialysate temperature for the trimmer heater + * @details Outputs: dgTrimmerTempSet + * @param heatingParams Dialysate heating parameters to be sent to DG * @return none *************************************************************************/ -void cmdSetDGDialysateTargetTemps( F32 primaryHtrTemp, F32 trimmerHtrTemp ) +void cmdSetDGDialysateHeatingParams( DG_CMD_DIALYSATE_HEATING_PARAMS_T heatingParams ) { - dgPrimaryTempSet = primaryHtrTemp; - dgTrimmerTempSet = trimmerHtrTemp; - sendDialysateTempTargetsToDG( dgPrimaryTempSet, dgTrimmerTempSet ); + dgTrimmerTempSet = heatingParams.trimmerTargetTemperature; + // TODO what should we do with the BOOL return of this function? + sendDialysateHeatingParamsToDG( &heatingParams ); } /*********************************************************************//** @@ -751,8 +605,9 @@ *************************************************************************/ void cmdStartDG( void ) { - dgStartCommandSent = TRUE; - sendDGStartStopCommand( START_DG_CMD ); + dgStartCommandSent = TRUE; + + sendDGStartStopCommand( (BOOL)START_DG_CMD ); } /*********************************************************************//** @@ -765,8 +620,9 @@ *************************************************************************/ void cmdStopDG( void ) { - dgStarted = FALSE; - sendDGStartStopCommand( STOP_DG_CMD ); + dgStarted = FALSE; + + sendDGStartStopCommand( (BOOL)STOP_DG_CMD ); } /*********************************************************************//** @@ -780,8 +636,9 @@ void cmdStartDGTrimmerHeater( void ) { dgTrimmerHeaterOn = TRUE; - dgCmdResp[ DG_CMD_START_TRIMMER_HEATER ].commandID = DG_CMD_NONE; - sendDGStartStopTrimmerHeaterCommand( START_DG_CMD, dgTrimmerTempSet ); + dgCmdResp[ DG_CMD_START_TRIMMER_HEATER ].commandID = DG_CMD_NONE; + + sendDGStartStopTrimmerHeaterCommand( START_DG_CMD ); } /*********************************************************************//** @@ -796,7 +653,8 @@ { dgTrimmerHeaterOn = FALSE; dgCmdResp[ DG_CMD_STOP_TRIMMER_HEATER ].commandID = DG_CMD_NONE; - sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD, 0 ); + + sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD ); } /*********************************************************************//** @@ -813,7 +671,8 @@ if ( resID < NUM_OF_DG_RESERVOIRS ) { dgActiveReservoirSet = resID; - dgCmdResp[ DG_CMD_SWITCH_RESERVOIR ].commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_SWITCH_RESERVOIR ].commandID = DG_CMD_NONE; + sendDGSwitchReservoirCommand( (U32)resID ); } else @@ -836,6 +695,7 @@ if ( valveSettingID < NUM_OF_DG_VALVE_SETTTINGS ) { dgCmdResp[ DG_CMD_VALVE_SETTING ].commandID = DG_CMD_NONE; + sendDGChangeValveSettingCommand( (U32)valveSettingID ); } else @@ -849,14 +709,16 @@ * The cmdStartDGFill function sends a fill command message to the DG. * @details Inputs: none * @details Outputs: fill command sent to DG. - * @param fillToVolMl volume (in mL) to fill inactive reservoir to + * @param fillToVolMl volume (in mL) to fill inactive reservoir to + * @param targetFlowLPM target flow rate in L/min * @return none *************************************************************************/ -void cmdStartDGFill( U32 fillToVolMl ) +void cmdStartDGFill( U32 fillToVolMl, F32 targetFlowLPM ) { dgCmdResp[ DG_CMD_START_FILL ].commandID = DG_CMD_NONE; - dgReservoirFillVolumeTargetSet = fillToVolMl; - sendDGFillCommand( DG_CMD_START, fillToVolMl ); + dgReservoirFillVolumeTargetSet = fillToVolMl; + + sendDGFillCommand( DG_CMD_START, fillToVolMl, targetFlowLPM ); } /*********************************************************************//** @@ -870,7 +732,8 @@ { dgCmdResp[ DG_CMD_STOP_FILL ].commandID = DG_CMD_NONE; dgReservoirFillVolumeTargetSet = 0; - sendDGFillCommand( DG_CMD_STOP, 0 ); + + sendDGFillCommand( DG_CMD_STOP, 0, 0 ); } /*********************************************************************//** @@ -879,17 +742,21 @@ * @details Inputs: none * @details Outputs: drain command sent to DG. * @param drainToVolMl volume (in mL) to drain inactive reservoir to - * @param tareLoadCell flag to tell DG tare load cell or not + * @param tareLoadCell flag to tell DG tare load cell or not + * @param start flag to tell DG to start or stop the drain mode * @return none *************************************************************************/ -void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell ) +void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell, BOOL rinse, BOOL start ) { DRAIN_RESERVOIR_CMD_PAYLOAD_T payload; dgCmdResp[ DG_CMD_START_DRAIN ].commandID = DG_CMD_NONE; - payload.drainToVolumeML = drainToVolMl; - payload.tareLoadCells = tareLoadCell; - dgReservoirDrainVolumeTargetSet = drainToVolMl; + payload.drainToVolumeML = drainToVolMl; + payload.tareLoadCells = tareLoadCell; + payload.rinseConcentrateLines = rinse; + payload.cmd = start; + dgReservoirDrainVolumeTargetSet = drainToVolMl; + sendDGDrainCommand( &payload ); } @@ -903,10 +770,119 @@ void cmdDGSampleWater( SAMPLE_WATER_CMD_T cmd ) { sendDGSampleWaterCommand( cmd ); +} + +/*********************************************************************//** + * @brief + * The cmdStartDGFlush function sends a start flush command message to + * the DG. + * @details Inputs: none + * @details Outputs: start flush mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStartDGFlush( void ) +{ + BOOL start = TRUE; + dgCmdResp[ DG_CMD_START_FLUSH ].commandID = DG_CMD_NONE; + + sendDGStartFlushModeCommand( start ); +} + +/*********************************************************************//** + * @brief + * The cmdStopDGFlush function sends a stop flush command message to + * the DG. + * @details Inputs: none + * @details Outputs: stop flush mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStopDGFlush( void ) +{ + BOOL start = FALSE; + dgCmdResp[ DG_CMD_STOP_FLUSH ].commandID = DG_CMD_NONE; + + sendDGStartFlushModeCommand( start ); +} + +/*********************************************************************//** + * @brief + * The cmdStartDGHeatDisinfect function sends a start heat disinfect + * command message to the DG. + * @details Inputs: none + * @details Outputs: start heat disinfect mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStartDGHeatDisinfect( void ) +{ + BOOL start = TRUE; + dgCmdResp[ DG_CMD_START_HEAT_DISINFECT ].commandID = DG_CMD_NONE; + + sendDGStartHeatDisinfectModeCommand( start ); +} + +/*********************************************************************//** + * @brief + * The cmdStopDGHeatDisinfect function sends a stop heat disinfect + * command message to the DG. + * @details Inputs: none + * @details Outputs: stop heat disinfect mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStopDGHeatDisinfect( void ) +{ + BOOL start = FALSE; + dgCmdResp[ DG_CMD_STOP_HEAT_DISINFECT ].commandID = DG_CMD_NONE; + + sendDGStartHeatDisinfectModeCommand( start ); +} + +/*********************************************************************//** + * @brief + * The cmdStartDGChemicalDisinfect function sends a start chemical disinfect + * command message to the DG. + * @details Inputs: none + * @details Outputs: start chemical disinfect mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStartDGChemicalDisinfect( void ) +{ + BOOL start = TRUE; + dgCmdResp[ DG_CMD_START_CHEM_DISINFECT ].commandID = DG_CMD_NONE; + + sendDGStartChemicalDisinfectModeCommand( start ); } /*********************************************************************//** * @brief + * The cmdStopDGChemicalDisinfect function sends a stop chemical disinfect + * command message to the DG. + * @details Inputs: none + * @details Outputs: stop chemical disinfect mode command sent to DG. + * @return none + *************************************************************************/ +void cmdStopDGChemicalDisinfect( void ) +{ + BOOL start = FALSE; + dgCmdResp[ DG_CMD_STOP_CHEM_DISINFECT ].commandID = DG_CMD_NONE; + sendDGStartChemicalDisinfectModeCommand( start ); +} + +/*********************************************************************//** + * @brief + * The cmdRequestDGConcentrateRatios function sends a request to DG to receive + * the concentrate ratios. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +void cmdRequestDGMixingRatios( void ) +{ + dgCmdResp[ DG_CMD_REQUEST_CONC_MIXING_RATIOS ].commandID = DG_CMD_NONE; + sendDGConcentrateMixingRatiosRequest(); +} + +/*********************************************************************//** + * @brief * The handleDGCommandResponse function processes the latest DG command response. * @details Inputs: none * @details Outputs: process command response from DG @@ -970,6 +946,37 @@ /*********************************************************************//** * @brief + * The checkDialysateTemperature function checks the dialysate temperature + * reported by DG and alarm if temperature is out of range. + * @details Inputs: dgTrimmerTempSet, dgDialysateTemp, dgRedundantDialysateTemp + * @details Outputs: alarm if dialysate temperature is out of accepted range + * @return none + *************************************************************************/ +void checkDialysateTemperature( void ) +{ + BOOL isTDiTempAboveHighSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ? TRUE : FALSE ); + F32 TDiHigh = dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isTDiTempAboveDialysateTarget = ( TDiHigh >= dgDialysateTemp ? TRUE : FALSE ); + F32 TDiLow = dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isTDiTempBelowDialysateTarget = ( TDiLow >= dgDialysateTemp ? TRUE : FALSE ); + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, isTDiTempAboveHighSafety, dgDialysateTemp, DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ); + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, isTDiTempAboveLowSafety, dgDialysateTemp, DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ); + + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTDiTempAboveDialysateTarget, dgDialysateTemp, TDiHigh ); + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTDiTempBelowDialysateTarget, dgDialysateTemp, TDiLow ); + } +} + +// ********** private functions ********** + +/*********************************************************************//** + * @brief * The checkDGRestart function checks to see if DG has restarted after started * by HD and triggers appropriate alarm. * @details Inputs: dgStarted @@ -978,15 +985,15 @@ *************************************************************************/ static void checkDGRestart( void ) { - if ( ( dgStartCommandSent == TRUE ) && ( DG_MODE_CIRC == dgCurrentOpMode ) ) + if ( ( dgStartCommandSent == TRUE ) && ( DG_MODE_GENE == dgCurrentOpMode ) ) { dgStartCommandSent = FALSE; dgStarted = TRUE; } if ( TRUE == dgStarted ) { - if ( ( DG_MODE_FAUL != dgCurrentOpMode ) && ( DG_MODE_CIRC != dgCurrentOpMode ) && + if ( ( DG_MODE_FAUL != dgCurrentOpMode ) && ( DG_MODE_GENE != dgCurrentOpMode ) && ( DG_MODE_FILL != dgCurrentOpMode ) && ( DG_MODE_DRAI != dgCurrentOpMode ) ) { activateAlarmNoData( ALARM_ID_DG_RESTARTED_FAULT );