Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r6982379266891326c9d45aecd7d54ad5c85ea69f -r7c73db9d00db93c5374fc0fbbe61117e589e95a2 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 6982379266891326c9d45aecd7d54ad5c85ea69f) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 7c73db9d00db93c5374fc0fbbe61117e589e95a2) @@ -10,33 +10,35 @@ #include "MessageSupport.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" +#include "NVDataMgmt.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_CYCLE_EXTRA_MARGIN_TIME_MS 8000 ///< Reservoir extra time in during the cycle for error in milliseconds. +#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Allocated time to settle the filled reservoir in milliseconds. +#define RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS 8000 ///< Reservoir extra time in during the cycle for error 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 1.1 ///< Maximum reservoir recirculation limit. +#define MAX_RESERVOIR_DILUTION 0.15F ///< Maximum reservoir dilution limit. +#define MAX_RESERVOIR_RECIRCULATION 1.1F ///< 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 RESERVOIR_DEPLETION_INTERVAL ( MAX_RESERVOIR_DEPLETION_TIME_MS / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) for maximum allowed depletion time. -#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 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 DIALYSATE_FLOW_RATE_350_ML_PER_MIN 0.35F ///< Dialysate flow rate 350 mL/min. +#define DIALYSATE_FLOW_RATE_400_ML_PER_MIN 0.4F ///< Dialysate flow rate 400 mL/min. +#define DIALYSATE_FLOW_RATE_500_ML_PER_MIN 0.5F ///< Dialysate flow rate 500 mL/min. +#define DIALYSATE_FLOW_RATE_550_ML_PER_MIN 0.55F ///< Dialysate flow rate 550 mL/min. +#define TGT_FILL_FLOW_FOR_DIA_FLOW_100_TO_350_ML_PER_MIN 0.5F ///< 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.8F ///< 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. +#define DIA_FLOW_TO_FILL_FLOW_SECOND_ORDER_COEFF 10.0F ///< Dialysate flow rate to fill flow rate second order coefficient. +#define DIA_FLOW_TO_FILL_FLOW_FIRST_ORDER_COEFF 7.5F ///< Dialysate flow rate to fill flow rate first order coefficient. +#define DIA_FLOW_TO_FILL_FLOW_CONSTANT 2.0F ///< Dialysate flow rate to fill flow rate constant. // ********** private data ********** @@ -60,7 +62,7 @@ static F32 dilutionLevelPct = 0.0; ///< Reservoir dilution level. static DG_OP_MODE_T dgOpMode = DG_MODE_INIT; ///< DG operation mode. static U32 dgSubMode = 0; ///< DG operation submode. -static U32 timeReservoirInUseMS = 0; ///< Reservoir time in use in milliseconds. +static U32 timeReservoirInUse = 0; ///< Reservoir time in use in milliseconds. static F32 volSpentUFML = 0.0; ///< Ultrafiltration volume in milliliters. static DG_RESERVOIR_ID_T activeReservoir; ///< Active reservoir. static F32 recirculationLevelPct = 0.0; ///< Recirculation level in percent. @@ -71,8 +73,13 @@ static F32 previousUFFlowMLP = 0.0; ///< Previous ultrafiltration flow rate in mL/min. static DG_MIXING_RATIOS_T ratios; ///< Mixing ratios and fill prep time in milliseconds structure. -static const F32 RESERVOIR_DILUTION_RATIO = MAX_RESERVOIR_DILUTION / ( 1.0 - MAX_RESERVOIR_DILUTION ); +static const F32 RESERVOIR_DILUTION_RATIO = MAX_RESERVOIR_DILUTION / ( 1.0 - MAX_RESERVOIR_DILUTION ); ///< Reservoir dilution ratio. +// TODO remove +// FALSE for reservoir 1 and TRUE for reservoir 2 +static BOOL test = TRUE; +// TODO remove + // ********** private function prototypes ********** // Reservoir management functions @@ -97,7 +104,7 @@ * @details Inputs: none * @details Outputs: reservoirsState, timeStartMS, timeDepletionMS, volTotalMl, * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, - * timeReservoirInUseMS, volSpentUFML, activeReservoir, recirculationLevelPct, + * timeReservoirInUse, volSpentUFML, activeReservoir, recirculationLevelPct, * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM, ratios * previousDialysateFlowRate * @return none @@ -113,7 +120,7 @@ dilutionLevelPct = 0.0; dgOpMode = DG_MODE_INIT; dgSubMode = 0; - timeReservoirInUseMS = 0; + timeReservoirInUse = 0; volSpentUFML = 0.0; activeReservoir = DG_RESERVOIR_1; recirculationLevelPct = 0.0; @@ -168,7 +175,14 @@ if ( getSalineBolusState() != SALINE_BOLUS_STATE_IN_PROGRESS ) { volSpentML += ( flowRateMLPerMS * msSinceLastVolumeCalc ); + + if ( TREATMENT_DIALYSIS_STATE == getTreatmentState()) + { + + ++timeReservoirInUse; + } } + // Update the reservoir start time timeStartMS = getMSTimerCount(); @@ -201,6 +215,7 @@ default: 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; + break; } publishReservoirData(); @@ -233,11 +248,14 @@ static void checkReservoirDepletionTime( void ) { // Check if the time that the reservoir has been use has exceeded the limit - if ( TRUE == didTimeout( timeReservoirInUseMS, MAX_RESERVOIR_DEPLETION_TIME_MS ) ) + if ( timeReservoirInUse >= RESERVOIR_DEPLETION_INTERVAL ) { -#ifndef SKIP_RESERVOIR_ALARMS - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT, calcTimeSince( timeReservoirInUseMS ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RESERVOIRS_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT, (timeReservoirInUse * TASK_GENERAL_INTERVAL) ) + } } } @@ -462,7 +480,8 @@ dilutionLevelPct = volSpentUFML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; // Check if the dilution level has exceeded the limit or the spent volume is more than the amount of volume in the reservoir - // If it has, trigger the fill command + // If it has, trigger the fill command. This if should not happen and the predictive dilution level should trigger just in time + // in advance if ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) @@ -504,7 +523,9 @@ timeWaitToFillMS = timeDepleteMS - ( getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS ); // If the wait time has elapsed, trigger a fill command - if ( timeWaitToFillMS <= 0 ) + // TODO uncomment + //if ( timeWaitToFillMS <= 0 ) + // TODO uncomment { cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); } @@ -541,9 +562,13 @@ // diluted to much if ( recirculationLevelPct >= MAX_RESERVOIR_RECIRCULATION ) { -#ifndef SKIP_RESERVOIR_ALARMS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_RECIRCULATION_OUT_OF_RANGE, recirculationLevelPct ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RESERVOIRS_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_RECIRCULATION_OUT_OF_RANGE, recirculationLevelPct ) + } + } // Check if DG has moved out of the fill mode @@ -565,35 +590,52 @@ * @brief * The handleReservoirMgmtWaitForFillSettleState function executes the reservoir * management wait for fill to settle state. - * @details Inputs: reservoirSwitchTimer + * @details Inputs: reservoirSwitchTimer, volSpentML * @details Outputs: reservoirSwitchTimer, volSpentML * @return next reservoir management state of the state machine *************************************************************************/ static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtWaitForFillSettleState( void ) { 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( reservoirSwitchStartTimeMS, RESERVOIR_SETTLE_TIME_MS ) ) + // Wait for the reservoir to settle and then send the commands to switch the active reservoir TODO - restore #define below + if ( ( TRUE == didTimeout( reservoirSwitchStartTimeMS, 15000 /*RESERVOIR_SETTLE_TIME_MS*/ ) ) && + ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) ) { DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); - // Signal dialysis sub-mode to capture baseline volume for next reservoir. - setStartReservoirVolume( inactiveRes ); + // TODO test code remove + //if ( TRUE == test ) // TODO comment the if statement + { + // Signal dialysis sub-mode to capture baseline volume for next reservoir. + setStartReservoirVolume( inactiveRes ); - // Command DG to switch reservoirs - cmdSetDGActiveReservoir( inactiveRes ); + // Command DG to switch reservoirs + cmdSetDGActiveReservoir( inactiveRes ); - // Signal dialysis sub-mode to switch reservoirs - signalReservoirsSwitched(); + // Signal dialysis sub-mode to switch reservoirs + signalReservoirsSwitched(); + } + // TODO test code // Get ready for the next delivery volSpentML = 0.0; // Wait for used reservoir to settle reservoirSwitchStartTimeMS = getMSTimerCount(); - state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; + // TODO test code + // For reservoir test, it should go back to start state + /*if ( FALSE == test ) + { + state = TREATMENT_RESERVOIR_MGMT_START_STATE; + } + else*/ // TODO comment the code above it is test code + { + state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; + test = FALSE; + } + // TODO test code } return state; @@ -617,7 +659,7 @@ setFinalReservoirVolume(); // Switched the active reservoir so reset the reservoir in use timer - timeReservoirInUseMS = getMSTimerCount(); + timeReservoirInUse = 0; // Reset to start state to restart drain, fill, switch process. state = TREATMENT_RESERVOIR_MGMT_START_STATE;