Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r549119eae64732f124d22df66de4fc88c56193c0 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 549119eae64732f124d22df66de4fc88c56193c0) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -118,6 +118,7 @@ static DG_DISINFECT_UI_STATES_T disinfectsStatus; ///< DG disinfects status. +static DG_MIXING_RATIOS_T dgMixingRatios; ///< DG mixing ratios. // TOD remove // TODO New variables for the reservoir management @@ -328,7 +329,7 @@ { fillToVolume = FILL_RESERVOIR_TO_VOLUME_LOW_FLOW_ML; } - cmdStartDGFill( fillToVolume ); + cmdStartDGFill( fillToVolume, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); } } else @@ -627,7 +628,7 @@ * @brief * The getDGDisinfectsStates function returns the DG disinfects readings. * @details Inputs: none - * @details Outputs: disinfectsStatus + * @details Outputs: none * @return the current DG disinfects readings *************************************************************************/ DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) @@ -637,6 +638,19 @@ /*********************************************************************//** * @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 @@ -800,6 +814,20 @@ 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 @@ -931,15 +959,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 ); } /*********************************************************************//** @@ -954,7 +983,7 @@ dgCmdResp[ DG_CMD_STOP_FILL ].commandID = DG_CMD_NONE; dgReservoirFillVolumeTargetSet = 0; - sendDGFillCommand( DG_CMD_STOP, 0 ); + sendDGFillCommand( DG_CMD_STOP, 0, 0 ); } /*********************************************************************//** @@ -1085,12 +1114,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 Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r549119eae64732f124d22df66de4fc88c56193c0 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 549119eae64732f124d22df66de4fc88c56193c0) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -32,15 +32,25 @@ // ********** public definitions ********** +#define DEFAULT_TARGET_FILL_FLOW_RATE_LPM 0.8 ///< Default target fill flow rate in L/min. + // TODO remove the #defines #define DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during treatment. #define FILL_RESERVOIR_TO_VOLUME_ML 1700 ///< Fill reservoir to this volume (in mL) during treatment. #define FILL_RESERVOIR_TO_VOLUME_LOW_FLOW_ML 1300 ///< Fill reservoir to this volume (in mL) during treatment if dialysate flow is slow. #define SLOW_DIALYSATE_FLOW_ML_MIN 250 ///< Threshold for slow dialysate flow designation. -/// Dialysate flow meter data struct. +/// DG Concentrate ratios data structure. typedef struct { + F32 acidMixingRatio; ///< Acid mixing ratio + F32 bicarbMixingRatio; ///< Bicarb mixing ratio + U32 fillPrepTimeMS; ///< Fill prepare time in milliseconds +} DG_MIXING_RATIOS_T; + +/// Dialysate flow meter data structure. +typedef struct +{ F32 measuredDialysateFlowRate; ///< Dialysate flow meter rate average measurement } DIALYSATE_FLOW_METER_DATA_T; @@ -128,6 +138,7 @@ F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ); F32 getDialysateTemperature( void ); DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ); +DG_MIXING_RATIOS_T getDGMixingRatios( void ); void setDGOpMode( U32 opMode, U32 subMode ); void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ); @@ -136,13 +147,14 @@ void setDialysateFlowData( F32 flowRate ); void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); void setDGDisinfectsStates( DG_DISINFECT_UI_STATES_T states ); +void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ); void cmdSetDGDialysateTargetTemps( F32 primaryHtrTemp, F32 trimmerHtrTemp ); void cmdStartDG( void ); void cmdStopDG( void ); void cmdSetDGActiveReservoir( DG_RESERVOIR_ID_T resID ); void cmdChangeDGValveSetting( DG_VALVE_SETTING_ID_T valveSettingID ); -void cmdStartDGFill( U32 fillToVolMl ); +void cmdStartDGFill( U32 fillToVolMl, F32 targetFlowLPM ); void cmdStopDGFill( void ); void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell, BOOL rinse, BOOL start ); void cmdStartDGTrimmerHeater( void ); @@ -154,6 +166,7 @@ void cmdStopDGHeatDisinfect( void ); void cmdStartDGChemicalDisinfect( void ); void cmdStopDGChemicalDisinfect( void ); +void cmdRequestDGMixingRatios( void ); void handleDGCommandResponse( DG_CMD_RESPONSE_T *dgCmdRespPtr ); BOOL getDGCommandResponse( U32 commandID, DG_CMD_RESPONSE_T *cmdRespPtr ); Index: firmware/App/Modes/ConsumableSelfTest.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Modes/ConsumableSelfTest.c (.../ConsumableSelfTest.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ConsumableSelfTest.c (.../ConsumableSelfTest.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -93,7 +93,7 @@ if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { currentConsumableSelfTestState = CONSUMABLE_SELF_TESTS_WATER_QUALITY_CHECK_STATE; - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML ); + cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); } break; Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -946,16 +946,16 @@ { if ( DG_RESERVOIR_1 == getDGInactiveReservoir() ) { - cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML ); + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); } else { - cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML ); + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); } } else { - cmdStartDGFill( PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML ); + cmdStartDGFill( PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML, DEFAULT_TARGET_FILL_FLOW_RATE_LPM ); } } Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -139,6 +139,9 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); + // Request the concentrate pumps mixing ratios and the DG fill mode prepare time + cmdRequestDGMixingRatios(); + return currentTreatmentParamsState; } Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r549119eae64732f124d22df66de4fc88c56193c0 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 549119eae64732f124d22df66de4fc88c56193c0) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -2,55 +2,73 @@ // TODO the copyright will be added automatically +#include + #include "DGInterface.h" #include "Dialysis.h" #include "DialInFlow.h" #include "MessageSupport.h" +#include "ModeTreatment.h" #include "OperationModes.h" #include "Reservoirs.h" #include "TaskGeneral.h" #include "Timers.h" // ********** private definitions ********** -#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Allocated time to settle the filled reservoir in milliseconds. +#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Allocated time to settle the filled reservoir in milliseconds. -#define MAX_RESERVOIR_VOLUME_ML 1950.0 ///< Maximum allowed fluid in a reservoir in milliliters. -#define MAX_RESERVOIR_DILUTION 0.15 ///< Maximum reservoir dilution limit. -#define MAX_RESERVOIR_RECIRCULATION 0.1 ///< Maximum reservoir recirculation limit. +#define MAX_RESERVOIR_VOLUME_ML 1950.0 ///< Maximum allowed fluid in a reservoir in milliliters. +#define MAX_RESERVOIR_DILUTION 0.15 ///< Maximum reservoir dilution limit. +#define MAX_RESERVOIR_RECIRCULATION 0.1 ///< Maximum reservoir recirculation limit. -#define MAX_RESERVOIR_DEPLETION_TIME_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Maximum allowed depletion time in milliseconds. -#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define MAX_RESERVOIR_DEPLETION_TIME_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Maximum allowed depletion time in milliseconds. +#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define DIALYSATE_FLOW_RATE_100_ML_PER_MIN 0.1 ///< Dialysate flow rate 100 mL/min. +#define DIALYSATE_FLOW_RATE_350_ML_PER_MIN 0.35 ///< Dialysate flow rate 350 mL/min. +#define DIALYSATE_FLOW_RATE_400_ML_PER_MIN 0.4 ///< Dialysate flow rate 400 mL/min. +#define DIALYSATE_FLOW_RATE_500_ML_PER_MIN 0.5 ///< Dialysate flow rate 500 mL/min. +#define DIALYSATE_FLOW_RATE_550_ML_PER_MIN 0.55 ///< Dialysate flow rate 550 mL/min. +#define DIALYSATE_FLOW_RATE_600_ML_PER_MIN 0.6 ///< Dialysate flow rate 600 mL/min. +#define TGT_FILL_FLOW_FOR_DIA_FLOW_100_TO_350_ML_PER_MIN 0.5 ///< Target fill flow rate for dialysate flow rates in between 100 to 350 mL/min. +#define TGT_FILL_FLOW_FOR_DIA_FLOW_550_TO_600_ML_PER_MIN 0.8 ///< Target fill flow rate for dialysate flow rates in between 500 to 600 mL/min. + +#define DIA_FLOW_TO_FILL_FLOW_SECOND_ORDER_COEFF 10.0 ///< Dialysate flow rate to fill flow rate second order coefficient. +#define DIA_FLOW_TO_FILL_FLOW_FIRST_ORDER_COEFF 7.5 ///< Dialysate flow rate to fill flow rate first order coefficient. +#define DIA_FLOW_TO_FILL_FLOW_CONSTANT 2.0 ///< Dialysate flow rate to fill flow rate constant. + // ********** private data ********** /// States of the treatment reservoir management state machine. typedef enum TreatmentReservoirMgmt_States { - TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< Treatment reservoir management start state. - TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE, ///< Treatment reservoir management drain reservoir state. - TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE, ///< Treatment reservoir management wait to fill state. - TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE, ///< Treatment reservoir management fill state. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE, ///< Treatment reservoir management wait for fill to settle state. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Treatment reservoir management wait for switch to settles state. - NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir management states. + TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< Treatment reservoir management start state. + TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE, ///< Treatment reservoir management drain reservoir state. + TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE, ///< Treatment reservoir management wait to fill state. + TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE, ///< Treatment reservoir management fill state. + TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE, ///< Treatment reservoir management wait for fill to settle state. + TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Treatment reservoir management wait for switch to settles state. + NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir management states. } TREATMENT_RESERVOIR_MGMT_STATE_T; // TODO update the init function with all the newest variables -static TREATMENT_RESERVOIR_MGMT_STATE_T reservoirsState; ///< Treatment mode's reservoirs state. -static U32 timeStartMS = 0; ///< Active reservoir start time in milliseconds. -static U32 timeDepletionMS = 0; ///< Active reservoir depletion time in milliseconds. -static F32 volTotalML = 0.0; ///< Active reservoir total volume in milliliters. -static F32 volSpentML = 0.0; ///< Active reservoir spent volume in milliliters. -static U32 reservoirPublicationCounter = 0; ///< Reservoirs data publication timer counter. +static TREATMENT_RESERVOIR_MGMT_STATE_T reservoirsState; ///< Treatment mode's reservoirs state. +static U32 timeStartMS = 0; ///< Active reservoir start time in milliseconds. +static U32 timeDepleteMS = 0; ///< Active reservoir depletion time in milliseconds. +static F32 volTotalML = 0.0; ///< Active reservoir total volume in milliliters. +static F32 volSpentML = 0.0; ///< Active reservoir spent volume in milliliters. +static U32 reservoirPublicationCounter = 0; ///< Reservoirs data publication timer counter. static F32 dilutionLevel = 0.0; static DG_OP_MODE_T dgOpMode = DG_MODE_INIT; static U32 dgSubMode = 0; static U32 timeReservoirInUseMS = 0; static F32 volSpentUFML = 0.0; static DG_RESERVOIR_ID_T activeReservoir; static F32 recirculationLevelPct = 0.0; -static U32 reservoirSwitchTimer = 0; +static U32 reservoirSwitchStartTime = 0; +static U32 timeFillReservoirMS = 0; +static U32 timeWaitToFillMS = 0; // TODO set the reservoirs alarms properties in the alarmsDefs.h so the alarms will be recoverable @@ -59,6 +77,8 @@ // Reservoir management functions static void checkReservoirDepletionTime( void ); static void checkReservoirMaxVolume( void ); +static F32 getTargetFillFlowRateLPM( void ); +static U32 getFillTimeMS( void ); static void publishReservoirData( void ); static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtStartState( void ); @@ -79,9 +99,10 @@ *************************************************************************/ void initReservoirs( void ) { + // TODO don't forget to update the variables and the doxygen reservoirsState = TREATMENT_RESERVOIR_MGMT_START_STATE; timeStartMS = 0; - timeDepletionMS = 0; + timeDepleteMS = 0; volTotalML = 0.0; volSpentML = 0.0; reservoirPublicationCounter = 0; @@ -144,7 +165,7 @@ break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TREATMENT_RESERVOIR_MANAGEMENT_STATE, (U32)reservoirsState ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TREATMENT_RESERVOIR_MANAGEMENT_STATE, (U32)reservoirsState ) reservoirsState = TREATMENT_RESERVOIR_MGMT_START_STATE; } @@ -191,6 +212,62 @@ /*********************************************************************//** * @brief + * The getTargetFillFlowRateLPM function sets the target fill flow rate for DG + * based on the target dialysate flow rate. + * @details Inputs: none + * @details Outputs: none + * @return target fill flow rate + *************************************************************************/ +static F32 getTargetFillFlowRateLPM( void ) +{ + F32 fillFlowRate = 0.0; + + F32 dialysateFlow = getDGDialysateFlowRateLMin(); + + if ( ( dialysateFlow >= DIALYSATE_FLOW_RATE_100_ML_PER_MIN ) && ( dialysateFlow <= DIALYSATE_FLOW_RATE_350_ML_PER_MIN ) ) + { + fillFlowRate = TGT_FILL_FLOW_FOR_DIA_FLOW_100_TO_350_ML_PER_MIN; + } + else if ( ( dialysateFlow >= DIALYSATE_FLOW_RATE_400_ML_PER_MIN ) && ( dialysateFlow <= DIALYSATE_FLOW_RATE_500_ML_PER_MIN ) ) + { + fillFlowRate = pow( dialysateFlow, 2 ) * DIA_FLOW_TO_FILL_FLOW_SECOND_ORDER_COEFF - + dialysateFlow * DIA_FLOW_TO_FILL_FLOW_FIRST_ORDER_COEFF + DIA_FLOW_TO_FILL_FLOW_CONSTANT; + } + else if ( ( dialysateFlow >= DIALYSATE_FLOW_RATE_550_ML_PER_MIN ) && ( dialysateFlow <= DIALYSATE_FLOW_RATE_600_ML_PER_MIN ) ) + { + fillFlowRate = TGT_FILL_FLOW_FOR_DIA_FLOW_550_TO_600_ML_PER_MIN; + } + else + { + // TODO fault if the flow is not in range? + } + + return fillFlowRate; +} + +/*********************************************************************//** + * @brief + * The getFillTimeMS function calculates the fill time in milliseconds. + * @details Inputs: none + * @details Outputs: none + * @return target fill flow rate + *************************************************************************/ +static U32 getFillTimeMS( void ) +{ + DG_MIXING_RATIOS_T ratios = getDGMixingRatios(); + F32 targetFillFlowRate = getTargetFillFlowRateLPM(); + F32 totalTargetFillFlow = targetFillFlowRate + ( targetFillFlowRate * ratios.acidMixingRatio ) + + ( targetFillFlowRate * ratios.bicarbMixingRatio ); + + U32 timeFillMS = ( FILL_RESERVOIR_TO_VOLUME_ML / ( ML_PER_LITER * totalTargetFillFlow ) ) * SEC_PER_MIN * MS_PER_SECOND; + + U32 timeTotalFillMS = timeFillMS + ratios.fillPrepTimeMS; + + return timeTotalFillMS; +} + +/*********************************************************************//** + * @brief * The publishReservoirData function publishes reservoirs data during treatment. * @details Inputs: reservoirsPublicationCounter * @details Outputs: reservoirsPublicationCounter @@ -278,26 +355,27 @@ { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML ); + cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, getTargetFillFlowRateLPM() ); } state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; } else { - F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; - F32 timeFreshRemaining = volFreshML / ( getDGDialysateFlowRateLMin() * 1000 ); - F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; - volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); - F32 volRemainingUF = volMaxUFML - volSpentUFML; - F32 timeDepleteRemaining = volRemainingUF / ( volSpentUFML / SEC_PER_MIN ); + F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; + F32 timeFreshRemainingMS = volFreshML / ( getDGDialysateFlowRateLMin() * 1000.0 ); + F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; + volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); + F32 volRemainingUFML = volMaxUFML - volSpentUFML; + F32 timeDepleteRemainingMS = ( volRemainingUFML / getCurrentUFSetRate() ) * SEC_PER_MIN * MS_PER_SECOND; + timeDepleteMS = MIN( timeFreshRemainingMS, timeDepleteRemainingMS ); + timeWaitToFillMS = timeFillReservoirMS - reservoirSwitchStartTime; - timeDepletionMS = MIN( timeFreshRemaining, timeDepleteRemaining ); + if ( timeDepleteMS >= timeWaitToFillMS ) + { + cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, getTargetFillFlowRateLPM() ); + } - // TODO what is twait? - - // TODO add the if condition to whether fill should be triggered or not - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML ); state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; } @@ -325,17 +403,14 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_RECIRCULATION_OUT_OF_RANGE, recirculationLevelPct ) } - // TODO check maximum vfill here shouldn't we do it in the mode fill in DG? - // TODO check fill timeout? - if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) { // Clear any of the recoverable conditions in case they were raised during the fill or wait to fill clearAlarmCondition( ALARM_ID_HD_ACTIVE_RESERVOIR_RECIRCULATION_OUT_OF_RANGE ); clearAlarmCondition( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT ); clearAlarmCondition( ALARM_ID_HD_ACTIVE_RESERVOIR_WEIGHT_OUT_OF_RANGE ); - reservoirSwitchTimer = getMSTimerCount(); + reservoirSwitchStartTime = getMSTimerCount(); state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; } @@ -355,7 +430,7 @@ TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; // Wait for the reservoir to settle and then send the commands to switch the active reservoir - if ( TRUE == didTimeout( reservoirSwitchTimer, RESERVOIR_SETTLE_TIME_MS ) ) + if ( TRUE == didTimeout( reservoirSwitchStartTime, RESERVOIR_SETTLE_TIME_MS ) ) { DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); @@ -371,8 +446,10 @@ // Get ready for the next delivery volSpentML = 0.0; + timeFillReservoirMS = getFillTimeMS(); + // Wait for used reservoir to settle - reservoirSwitchTimer = getMSTimerCount(); + reservoirSwitchStartTime = getMSTimerCount(); state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; } @@ -392,7 +469,7 @@ { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; - if ( TRUE == didTimeout( reservoirSwitchTimer, RESERVOIR_SETTLE_TIME_MS ) ) + if ( TRUE == didTimeout( reservoirSwitchStartTime, RESERVOIR_SETTLE_TIME_MS ) ) { // Signal dialysis sub-mode to capture final volume of prior reservoir after settling. setFinalReservoirVolume(); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -1304,6 +1304,10 @@ handleStopHDRTCClock( message ); break; + case MSG_ID_DG_CONCENTRATE_MIXING_RATIOS_DATA: + handleDGMixingRatios( message ); + break; + // NOTE: this always must be the last case case MSG_ID_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -1461,10 +1461,11 @@ * @details Inputs: none * @details Outputs: DG fill command msg constructed and queued. * @param cmd start or stop fill command - * @param fillToVolumeMl volume (in mL) to fill inactive reservoir to + * @param fillToVolumeMl volume (in mL) to fill inactive reservoir to + * @param targetFlowLRatePM target fill flow rate in L/min * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl ) +BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl, F32 targetFlowRateLPM ) { BOOL result; MESSAGE_T msg; @@ -1473,11 +1474,13 @@ // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_FILL_CMD; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( F32 ); memcpy( payloadPtr, &fillToVolumeMl, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &cmd, sizeof( U32 ) ); + memcpy( payloadPtr, &cmd, sizeof( U32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &targetFlowRateLPM, sizeof( F32 ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_DG, ACK_REQUIRED ); @@ -1935,6 +1938,31 @@ return result; } +/*********************************************************************//** + * @brief + * The sendDGConcentrateMixingRatiosRequest function constructs a request msg + * to the DG to request the concentrate ratios and queues the msg for transmit + * on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG POST result request msg constructed and queued. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendDGConcentrateMixingRatiosRequest( void ) +{ + BOOL result; + MESSAGE_T msg; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_REQUEST_DG_CONCENTRATE_MIXING_RATIOS; + msg.hdr.payloadLen = 0; + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_DG, ACK_REQUIRED ); + + return result; +} + #ifdef EMC_TEST_BUILD BOOL broadcastCANErrorCount( U32 count ) { @@ -6730,7 +6758,6 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } - /*********************************************************************//** * @brief * The handleStopHDRTCClock function handles a request to stop the RTC clock. @@ -6752,4 +6779,23 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleDGMixingRatios function handles a concentrate mixing ratios and + * prepare fill time broadcast from DG. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDGMixingRatios( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof( DG_MIXING_RATIOS_T ) ) + { + DG_MIXING_RATIOS_T payload; + + memcpy( &payload, message->payload, sizeof( DG_MIXING_RATIOS_T ) ); + } +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r9a45dcbdfae33fc06479d99b8d52bada8f682194 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 9a45dcbdfae33fc06479d99b8d52bada8f682194) @@ -308,7 +308,7 @@ // MSG_ID_HD_DISPOSABLE_REMOVAL_CONFIRM_RESPONSE BOOL sendDisposableRemovalConfirmResponse( BOOL accepted, U32 reason ); -// MSG_ID_UI_TREATMENT_LOG_DATA_REQUEST +// MSG_ID_UI_TREATMENT_LOG_DATA_REQUESTsendDGPOSTResultRequest void handleUITreatmentLogDataRequest( MESSAGE_T *message ); // MSG_ID_HD_TREATMENT_LOG_DATA_RESPONSE @@ -359,7 +359,7 @@ BOOL sendDGChangeValveSettingCommand( U32 valveSettingCmd ); // MSG_ID_DG_FILL_CMD -BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl ); +BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl, F32 targetFlowRateLPM ); // MSG_ID_DG_DRAIN_CMD BOOL sendDGDrainCommand( DRAIN_RESERVOIR_CMD_PAYLOAD_T *drainCmdPtr ); @@ -400,9 +400,12 @@ // MSG_ID_HD_SEND_SYSTEM_RECORD BOOL sendHDSystemRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* sysRcrdAddress ); -// MSG_ID_Hd_SEND_SERVICE_RECORD +// MSG_ID_HD_SEND_SERVICE_RECORD BOOL sendHDServiceRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* srvcRcrdAddress ); +// MSG_ID_DG_REQUEST_CONCENTRATE_RATIOS +BOOL sendDGConcentrateMixingRatiosRequest( void ); + #ifdef EMC_TEST_BUILD // MSG_ID_CAN_ERROR_COUNT BOOL broadcastCANErrorCount( U32 count ); @@ -763,6 +766,9 @@ // MSG_ID_HD_STOP_RTC_CLOCK void handleStopHDRTCClock( MESSAGE_T *message ); +// MSG_ID_DG_CONCENTRATE_MIXING_RATIOS_DATA +void handleDGMixingRatios( MESSAGE_T *message ); + /**@}*/ #endif