Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -ra69fcb7945b0300b47ce3287f8cb22c7c26171dc -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision a69fcb7945b0300b47ce3287f8cb22c7c26171dc) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* 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. * -* @file DGInterface.c +* @file DGInterface.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Quang Nguyen +* @date (last) 24-Aug-2021 * -* @author (original) Sean -* @date (original) 08-Apr-2020 +* @author (original) Sean +* @date (original) 08-Apr-2020 * ***************************************************************************/ @@ -23,6 +23,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "Timers.h" @@ -33,15 +34,22 @@ // ********** 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 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 RESERVOIR_SETTLE_TIME_MS 5000 ///< Time (in ms) allotted for reservoir to settle (after fill, before drain). -#define MAX_RESERVOIR_VOLUME_ML 1950.0 ///< Maximum reservoir volume. Switch reservoirs if active reservoir exceeds this volume. +#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_PERSISTENCE_PERIOD ( 3 * MS_PER_SECOND ) ///< Persistence period for dialysate temperature alarm. + +#define DIALYSATE_TEMP_RECOVERY_TOLERANCE_C 2.0 ///< Dialysate temperature recovery tolerance in degree C. +#define DIALYSATE_TEMP_TOLERANCE_C 4.0 ///< Dialysate temperature tolerance in degree C. +#define DIALYSATE_TEMP_HIGH_LIMIT_C 42.0 ///< Dialysate high temperature limit in degree C. +#define DIALYSATE_TEMP_LOW_LIMIT_C 33.0 ///< Dialysate low temperature limit in degree C. + /// States of the treatment reservoir management state machine. typedef enum TreatmentReservoirMgmt_States { @@ -71,7 +79,6 @@ static U32 resMgmtTimer = 0; ///< Used for keeping state time. // 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 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. @@ -90,11 +97,10 @@ 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. -// 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 = 0.0; ///< Latest dialysate flow rate reported by the DG. +static BOOL dgDialysateFlowDataFreshFlag = FALSE; ///< 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. @@ -130,7 +136,7 @@ dgTrimmerTempSet = 0.0; dgActiveReservoirSet = DG_RESERVOIR_2; dgReservoirFillVolumeTargetSet = 0; - dgReservoirDrainVolumeTargetSet = 0; + dgReservoirDrainVolumeTargetSet = 0; // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) @@ -161,6 +167,9 @@ lgLoadCellReadingsIdx = 0; lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + + initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); } /*********************************************************************//** @@ -252,11 +261,11 @@ break; case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: - if ( DG_MODE_CIRC == dgOpMode ) + if ( DG_MODE_GENE == dgOpMode ) { - if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) + if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, TRUE ); } } else if ( DG_MODE_DRAI == dgOpMode ) @@ -270,7 +279,7 @@ break; case TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE: - if ( DG_MODE_CIRC == dgOpMode ) + if ( DG_MODE_GENE == dgOpMode ) { currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; } @@ -280,9 +289,9 @@ // Delay fill start if we have paused treatment? if ( getTreatmentState() == TREATMENT_DIALYSIS_STATE ) { - if ( DG_MODE_CIRC == dgOpMode ) + if ( DG_MODE_GENE == dgOpMode ) { - if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) + if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { U32 fillToVolume = FILL_RESERVOIR_TO_VOLUME_ML; @@ -305,7 +314,7 @@ break; case TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE: - if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getDGSubMode() ) ) + if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { resMgmtTimer = getMSTimerCount(); currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; @@ -419,76 +428,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. @@ -660,56 +631,24 @@ 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 ) +{ + 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. @@ -791,7 +730,7 @@ { dgStartCommandSent = TRUE; - sendDGStartStopCommand( START_DG_CMD ); + sendDGStartStopCommand( (BOOL)START_DG_CMD ); } /*********************************************************************//** @@ -806,7 +745,7 @@ { dgStarted = FALSE; - sendDGStartStopCommand( STOP_DG_CMD ); + sendDGStartStopCommand( (BOOL)STOP_DG_CMD ); } /*********************************************************************//** @@ -925,16 +864,19 @@ * @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; + payload.tareLoadCells = tareLoadCell; + payload.rinseConcentrateLines = rinse; + payload.cmd = start; dgReservoirDrainVolumeTargetSet = drainToVolMl; sendDGDrainCommand( &payload ); @@ -1113,6 +1055,47 @@ /*********************************************************************//** * @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 const dialysateHighTemp = ( ( ( dgDialysateTemp - dgTrimmerTempSet ) > DIALYSATE_TEMP_TOLERANCE_C ) || + ( dgDialysateTemp > DIALYSATE_TEMP_HIGH_LIMIT_C ) ); + + BOOL const dialysateLowTemp = ( ( ( dgTrimmerTempSet - dgDialysateTemp ) > DIALYSATE_TEMP_TOLERANCE_C ) || + ( dgDialysateTemp < DIALYSATE_TEMP_LOW_LIMIT_C ) ); + + BOOL const dialysateTempRecovered = fabs( dgDialysateTemp - dgTrimmerTempSet ) < DIALYSATE_TEMP_RECOVERY_TOLERANCE_C ? TRUE : FALSE; + +#ifndef DISABLE_DIALYSATE_TEMP_CHECK + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dialysateHighTemp ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dgTrimmerTempSet, dgDialysateTemp ); + } + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dialysateLowTemp ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dgTrimmerTempSet, dgDialysateTemp ); + } + + if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dialysateHighTemp ) ) + { + clearAlarmCondition( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH ); + } + + if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dialysateTempRecovered ) ) + { + clearAlarmCondition( ALARM_ID_DIALYSATE_TEMPERATURE_LOW ); + } +#endif +} + +/*********************************************************************//** + * @brief * The checkDGRestart function checks to see if DG has restarted after started * by HD and triggers appropriate alarm. * @details Inputs: dgStarted @@ -1121,15 +1104,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 );