Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r24b2fe72608344e67ef37234085d15ad5e4fcc37 -rbd241ef5231a9869adaf7bb5ed166135beb2c0fb --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 24b2fe72608344e67ef37234085d15ad5e4fcc37) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision bd241ef5231a9869adaf7bb5ed166135beb2c0fb) @@ -36,11 +36,7 @@ #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 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 DIALYSATE_TEMP_PERSISTENCE_PERIOD ( 3 * MS_PER_SECOND ) ///< Persistence period for dialysate temperature alarm. @@ -50,20 +46,6 @@ #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 -{ - 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 @@ -74,14 +56,11 @@ 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 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. 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 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. @@ -108,17 +87,18 @@ 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. @@ -132,7 +112,6 @@ dgStarted = FALSE; dgTrimmerHeaterOn = FALSE; - dgPrimaryTempSet = 0.0; dgTrimmerTempSet = 0.0; dgActiveReservoirSet = DG_RESERVOIR_2; dgReservoirFillVolumeTargetSet = 0; @@ -188,23 +167,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 @@ -215,156 +177,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_GENE == dgOpMode ) - { - if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) - { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, TRUE ); - } - } - 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_GENE == 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_GENE == dgOpMode ) - { - if ( DG_GEN_IDLE_MODE_STATE_FLUSH_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_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_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. @@ -514,6 +331,18 @@ /*********************************************************************//** * @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 getDialysateTemperature function gets the latest dialysate temperature. * @details Inputs: dgDialysateTemp * @details Outputs: none @@ -526,14 +355,15 @@ /*********************************************************************//** * @brief - * The getDGDisinfectsStates function returns the DG disinfects readings. + * The getDGMixingRatios function returns the DG mixing ratios and the fill + * prep time. * @details Inputs: none - * @details Outputs: disinfectsStatus - * @return the current DG disinfects readings + * @details Outputs: none + * @return getDGMixingRatios which is the DG mixing ratios *************************************************************************/ -DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +DG_MIXING_RATIOS_T getDGMixingRatios( void ) { - return disinfectsStatus; + return dgMixingRatios; } /*********************************************************************//** @@ -593,22 +423,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 @@ -701,21 +515,34 @@ 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 ); } /*********************************************************************//** @@ -832,15 +659,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 ); + sendDGFillCommand( DG_CMD_START, fillToVolMl, targetFlowLPM ); } /*********************************************************************//** @@ -855,7 +683,7 @@ dgCmdResp[ DG_CMD_STOP_FILL ].commandID = DG_CMD_NONE; dgReservoirFillVolumeTargetSet = 0; - sendDGFillCommand( DG_CMD_STOP, 0 ); + sendDGFillCommand( DG_CMD_STOP, 0, 0 ); } /*********************************************************************//** @@ -873,11 +701,11 @@ DRAIN_RESERVOIR_CMD_PAYLOAD_T payload; dgCmdResp[ DG_CMD_START_DRAIN ].commandID = DG_CMD_NONE; - payload.drainToVolumeML = drainToVolMl; - payload.tareLoadCells = tareLoadCell; - payload.rinseConcentrateLines = rinse; - payload.cmd = start; - dgReservoirDrainVolumeTargetSet = drainToVolMl; + payload.drainToVolumeML = drainToVolMl; + payload.tareLoadCells = tareLoadCell; + payload.rinseConcentrateLines = rinse; + payload.cmd = start; + dgReservoirDrainVolumeTargetSet = drainToVolMl; sendDGDrainCommand( &payload ); } @@ -986,12 +814,25 @@ { 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 @@ -1094,6 +935,8 @@ #endif } +// ********** private functions ********** + /*********************************************************************//** * @brief * The checkDGRestart function checks to see if DG has restarted after started