Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r57dd20557f066bf5d790ce25dd11c97bb93e3cde -r0139acdc51e41aa77efe9dd1478f88ae597d3be1 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 57dd20557f066bf5d790ce25dd11c97bb93e3cde) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 0139acdc51e41aa77efe9dd1478f88ae597d3be1) @@ -22,14 +22,18 @@ #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" +#include "Messaging.h" #include "ModeGenDialysate.h" #include "ModeStandby.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "Pressure.h" +#include "SpentChamberFill.h" #include "TaskGeneral.h" #include "TDInterface.h" #include "Temperature.h" #include "Timers.h" +#include "Ultrafiltration.h" #include "Valves.h" /** @@ -39,43 +43,64 @@ // ********** private definitions ********** -#define FRESH_DIAL_PUMP_INITIAL_RPM 2500 ///< Nominal RPM target for fresh dialysate pump to maintain required pressure. -#define SPENT_DIAL_PUMP_INITIAL_RPM 2000 ///< Nominal RPM target for spent dialysate pump to maintain required pressure. -#define HYD_CHAMBER_FLUID_TEMP_C_MIN 35.0F ///< Minimum hydraulics fluid temperature in deg celcius -#define HYD_CHAMBER_PRES_CHECK_TIME_OUT ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when hydraulics chamber pressure check initiated -#define SPENT_DIAL_PRES_CHECK_TIME_OUT ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when spent dialysate pressure check initiated -//TODO : Needs further finetuning. currently max negative pressure reaches around 11.5 psi +/- 5% values defined for now -//#define HYD_CHAMBER_TARGET_NEG_PRESS_MIN_PSI (-11.7877F) ///< Hydraulics chamber minimum negative pressure(D9/PHo) in psi. -//#define HYD_CHAMBER_TARGET_NEG_PRESS_MAX_PSI (-12.2789F) ///< Hydraulics chamber maximum negative pressure(D9/PHo) in psi. -#define HYD_CHAMBER_TARGET_NEG_PRESS_MIN_PSI (-10.000F) ///< Hydraulics chamber minimum negative pressure(D9/PHo) in psi. -#define HYD_CHAMBER_TARGET_NEG_PRESS_MAX_PSI (-12.075F) ///< Hydraulics chamber maximum negative pressure(D9/PHo) in psi. -#define GEN_DIALYSATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen dialysate mode data published. +#define HYD_CHAMBER_FLUID_TEMP_C_MIN 35.0F ///< Minimum hydraulics fluid temperature in deg celcius +#define GEN_DIALYSATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen dialysate mode data published. +#define DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C 2.0F ///< Dialysate temperature clear alarm tolerance C +#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 4.0F ///< Dialysate temperature out of target tolerance C. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 90 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. +#define DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C 46.0F ///< Dialysate upper bound maximum temperature limit in C. +#define DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature upper bound maximum safety timeout in milliseconds. +#define DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C 42.0F ///< Dialysate upper bound safety temperature limit in C. +#define DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C 33.0F ///< Dialysate lower bound safety temperature limit in C. +#define DIALYSATE_TEMP_CLEAR_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature clear persistence timeout. +#define QUAD_FIRST_COEFFICIENT 0.0006F ///< First coefficient used in adjusted dialysate temperature quadratic calculation for low Qds +#define QUAD_SECOND_COEFFICIENT -0.1743F ///< Second coefficient used in adjusted dialysate temperature quadratic calculation for low Qds +#define QUAD_THIRD_COEFFICIENT 17.3F ///< Third coefficient used in adjusted dialysate temperature quadratic calculation for low Qds +#define LINEAR_SLOPE_FACTOR -0.0029F ///< Slope factor used in adjusted dialysate temperature linear calculation for high Qds +#define LINEAR_INTERCEPT_FACTOR 3.47F ///< Intercept factor used in adjusted dialysate temperature linear calculation for high Qds +#define LOW_DIAL_FLOW_RATE 150.0F ///< Dialysate flow rate lesser than 150 considered to be low Qds. +#define SPENT_CHAMBER_FILL_MAX_COUNT 15 ///< Total number of spent chamber fill allowed. +#define BICARB_CHAMBER_FILL_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Bicarb chamber fill timeout. +//Testing +#define DELAY_BC_SWITCHING_AT_START_UP ( 10 * MS_PER_SECOND ) ///< Provide a balancing chamber switching start up delay to stabilize pump speed etc., +/// Payload record structure for Gen dialysate execution state set request +typedef struct +{ + U32 execStateSet; ///< Gen dialysate execution state machine set request +} GEND_EXEC_STATE_SET_CMD_PAYLOAD_T; // ********** private data ********** -static DD_GEND_MODE_STATE_T genDialysateState = DD_GEND_STATE_START; ///< Currently active gen dialysate state. +static DD_GEND_MODE_STATE_T genDialysateState; ///< Currently active gen dialysate state. static OVERRIDE_F32_T targetHydChamberFluidTemp; ///< Target hydraulics chamber fluid temperature. -static U32 hydChamberPressureCheckStartTimeMS; ///< Current time when hydraulics chamber pressure check satrted in milliseconds. -static U32 spentDialPressureCheckStartTimeMS; ///< Current time when spent dialysate pressure check started in milliseconds. static OVERRIDE_U32_T isDialDeliveryInProgress; ///< To indicate dialysate started delivering to dialyzer for treatment (overrideable) static OVERRIDE_U32_T isDialysateGoodtoDeliver; ///< Flag indicating whether ready to deliver dialysate or not. +static BOOL pendingSpentChamberFill; ///< Flag indicating spent chamber fill process to be initiated. +static BOOL pendingBicarbChamberFill; ///< Flag indicating bicarb chamber fill process to be initiated. +static BOOL pendingStopDDGenDialRequest; ///< Flag indicating TD has requested DD stop the generate dialysate. static U32 genDialysateDataPublicationTimerCounter; ///< Used to schedule generate dialysate data publication to CAN bus. static OVERRIDE_U32_T genDialysateDataPublishInterval; ///< Generate dialysate mode data publish interval. -static F32 lastDialTargetTemperatureSet; ///< last dialysate target temperature set for heater control -static BOOL isTreatementParamUpdated; ///< To indicate change in treatment parameters +static BOOL isTreatmentParamUpdated; ///< To indicate change in treatment parameters +static U32 bicarbFillStartTimeMS; ///< Bicarb fill start time to check the timeout for filling process. +//Testing +static U32 bypassStateDelayStartTimeMS; ///< Delay balancing chamber switching for a second to preapre pump steady state. +static BOOL delayBypassStateFlag; ///< To indicate change in treatment parameters +static F32 dialysateToDialyzerFlowRate; ///< Current dialysate to dialyzer flow rate (ml/min) // ********** private function prototypes ********** static void setModeGenDStateTransition( DD_GEND_MODE_STATE_T state ); -static BOOL hydChamberWaterInletControl( void ); -static DD_GEND_MODE_STATE_T handleGenDHydraulicsChamberWaterInletCheckState( void ); -static DD_GEND_MODE_STATE_T handleGenDHydChamberPressureCheckState( void ); -static DD_GEND_MODE_STATE_T handleGenDFreshDialysatePressureCheckState( void ); -static DD_GEND_MODE_STATE_T handleGenDSpentDialysatePressureCheckState( void ); -static DD_GEND_MODE_STATE_T handleGenDProduceDialysateState( void ); +static DD_GEND_MODE_STATE_T handleGenDDialysateBypassState( void ); static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryState( void ); static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryPauseState( void ); -static F32 getGenDilaysateTargetTemperature( void ); +static DD_GEND_MODE_STATE_T handleGenDSpentChamberFillState(void); +static DD_GEND_MODE_STATE_T handleGenDBicarbChamberFillState( void ); +static DD_GEND_MODE_STATE_T handleGenDIsolatedUFState( void ); +static F32 getGenDialysateTargetTemperature( void ); +static void calculateTargetDialysateTemp( void ); +static void updateDialysateToDialyzerFlowRate( void ); +static void checkDialysateTemperature( void ); +static void monitorChamberLevelStatus( void ); static void publishGenDialysateModeData( void ); /*********************************************************************//** @@ -100,18 +125,27 @@ isDialDeliveryInProgress.ovData = FALSE; isDialDeliveryInProgress.ovInitData = FALSE; isDialDeliveryInProgress.override = OVERRIDE_RESET; - hydChamberPressureCheckStartTimeMS = 0; - spentDialPressureCheckStartTimeMS = 0; + pendingStopDDGenDialRequest = FALSE; genDialysateDataPublishInterval.data = GEN_DIALYSATE_DATA_PUBLISH_INTERVAL; genDialysateDataPublishInterval.ovData = GEN_DIALYSATE_DATA_PUBLISH_INTERVAL; genDialysateDataPublishInterval.ovInitData = 0; genDialysateDataPublishInterval.override = OVERRIDE_RESET; genDialysateDataPublicationTimerCounter = 0; - lastDialTargetTemperatureSet = 0.0F; - isTreatementParamUpdated = FALSE; + isTreatmentParamUpdated = FALSE; + bicarbFillStartTimeMS = 0; + pendingSpentChamberFill = FALSE; + pendingBicarbChamberFill = FALSE; + //Testing + bypassStateDelayStartTimeMS = 0; + delayBypassStateFlag = TRUE; + dialysateToDialyzerFlowRate = 0.0F; //Initialize balancing chamber module initBalanceChamber(); + + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ); } /*********************************************************************//** @@ -126,6 +160,7 @@ { initGenDialysateMode(); setCurrentSubState( NO_SUB_STATE ); + transitionToUltrafiltration(); return genDialysateState; } @@ -140,7 +175,7 @@ *************************************************************************/ void execGenDialysateMonitor( void ) { - // Read temperature and conducitivity + // Read temperature and conductivity //F32 hydChamberTemperature = getTemperatureValue( D4_TEMP ); //F32 biCarbConductivity = getConductivityValue( D17_COND ); //F32 acidBicarbMixConductivity = getConductivityValue( D29_COND ); @@ -173,81 +208,114 @@ // Do nothing break; - case DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE: - // Close all balancing chamber and hydraulics valves - valveControlForBCClosedState(); - setHydValvesStatetoClosedState(); - setUFValvesStatetoClosedState(); - setValveState( M4_VALV, VALVE_STATE_OPEN ); //M4 + case DD_GEND_DIALYSATE_BYPASS_STATE: + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); + setValveState( D14_VALV, VALVE_STATE_OPEN ); + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve + setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI + setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO + setValveState( D47_VALV, VALVE_STATE_CLOSED ); // spent chamber purge valve + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve - // Get the target temperature from TD - targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); - // Turn on the primary heater - setHeaterTargetTemperature( D5_HEAT, getGenDilaysateTargetTemperature() ); + calculateTargetDialysateTemp(); + setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); + setD28TempFeedbackControl( TRUE ); startHeater( D5_HEAT ); - lastDialTargetTemperatureSet = getGenDilaysateTargetTemperature(); - break; - case DD_GEND_HYD_CHAMBER_PRESSURE_CHECK_STATE: - // Open up VHo valve - setValveState( D14_VALV, VALVE_STATE_OPEN ); //D14 - // Start timer for hyd chamber negative pressure check state - hydChamberPressureCheckStartTimeMS = getMSTimerCount(); - // Start D12/DGP pump - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM ); - break; + //Testing : Enable close loop once testing is complete + //setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, FALSE ); + setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); + setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); - case DD_GEND_FRESH_DIALYSATE_PRESSURE_CHECK_STATE: - // Lets be DGP continue running since pressure relief valve was set/ tuned part of priming process - hydChamberPressureCheckStartTimeMS = getMSTimerCount(); + transitionToBalChamberFill(); + + //Testing + bypassStateDelayStartTimeMS = getMSTimerCount(); + delayBypassStateFlag = TRUE; break; - case DD_GEND_SPENT_DIALYSATE_PRESSURE_CHECK_STATE: - // Start the timer for spent dialysate pressure check - spentDialPressureCheckStartTimeMS = getMSTimerCount(); + case DD_GEND_DIALYSATE_DELIVERY_STATE: + //Previous state + setValveState( D47_VALV, VALVE_STATE_CLOSED ); // spent chamber purge valve + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); + setValveState( D14_VALV, VALVE_STATE_OPEN ); + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve - // Open all balancing chamber valves for free flow - //valveControlForBCOpenState(); + // Turn on the primary heater + calculateTargetDialysateTemp(); + setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); + setD28TempFeedbackControl( TRUE ); + startHeater( D5_HEAT ); - // Open fresh balancing chamber valves D19,D20,D21,D22 - setValveState( D19_VALV, VALVE_STATE_OPEN ); - setValveState( D20_VALV, VALVE_STATE_OPEN ); - setValveState( D21_VALV, VALVE_STATE_OPEN ); - setValveState( D22_VALV, VALVE_STATE_OPEN ); + //setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, FALSE ); + setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); + setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); - // Close spent side valves D23,D24,D25,D26 - setValveState( D23_VALV, VALVE_STATE_CLOSED ); - setValveState( D25_VALV, VALVE_STATE_CLOSED ); - setValveState( D24_VALV, VALVE_STATE_CLOSED ); - setValveState( D26_VALV, VALVE_STATE_CLOSED ); + // Disable bypass valve + setValveState( D34_VALV, VALVE_STATE_CLOSED ); // Bypass valve + setValveState( D35_VALV, VALVE_STATE_OPEN ); // VDI + setValveState( D40_VALV, VALVE_STATE_OPEN ); // VDO + break; + case DD_GEND_SPENT_CHAMBER_FILL_STATE: + //Set valves and actuators + setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI + setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO - // Make sure valves are in correct position - setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve : D53 - setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI - setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO - setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); + setValveState( D14_VALV, VALVE_STATE_OPEN ); + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve + setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve + setValveState( D47_VALV, VALVE_STATE_OPEN ); // Spent chamber purge valve - // Start D48/SDP pump - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM ); + requestConcentratePumpOff( D76_PUMP, FALSE ); + requestConcentratePumpOff( D11_PUMP, FALSE ); + requestConcentratePumpOff( D10_PUMP, FALSE ); + + // Turn on the primary heater + calculateTargetDialysateTemp(); + setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); + setD28TempFeedbackControl( TRUE ); + startHeater( D5_HEAT ); + + setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_FILL_RPM, TRUE ); + + //Transition to spent chamber fill + transitionToSpentChamberFill(); break; - case DD_GEND_PRODUCE_DIALYSATE_STATE: - //Close previously opened BC valves - valveControlForBCClosedState(); + case DD_GEND_BICARB_CHAMBER_FILL_STATE: + requestConcentratePumpOff( D11_PUMP, FALSE ); + requestConcentratePumpOff( D10_PUMP, FALSE ); + requestConcentratePumpOff( D76_PUMP, FALSE ); - // Make sure bypass valve open condition + //Set valves and actuators + setValveState( D47_VALV, VALVE_STATE_CLOSED ); // spent chamber purge valve setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO + setValveState( D14_VALV, VALVE_STATE_CLOSED ); + + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve - break; + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); // Bicarb chamber purge valve + bicarbFillStartTimeMS = getMSTimerCount(); - case DD_GEND_DIALYSATE_DELIVERY_STATE: - // Disable bypass valve - setValveState( D34_VALV, VALVE_STATE_CLOSED ); // Bypass valve - setValveState( D35_VALV, VALVE_STATE_OPEN ); // VDI - setValveState( D40_VALV, VALVE_STATE_OPEN ); // VDO + // Turn on the primary heater + calculateTargetDialysateTemp(); + setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); + //Disable the D28 based temp control as fluid dispense being stopped by balancing chamber. + setD28TempFeedbackControl( FALSE ); + startHeater( D5_HEAT ); + + setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); break; case DD_GEND_DIALYSATE_DELIVERY_PAUSE: @@ -256,13 +324,21 @@ signalDialysatePumpHardStop( D48_PUMP ); requestConcentratePumpOff( D11_PUMP, FALSE ); requestConcentratePumpOff( D10_PUMP, FALSE ); + requestConcentratePumpOff( D76_PUMP, FALSE ); stopHeater( D5_HEAT ); stopHeater( D45_HEAT ); - //close the DD - water inlet and drain valves? + //Enable bypass valve + setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI + setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO + setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve break; + case DD_GEND_ISOLATED_UF_STATE: + //TODO : define actuators states + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_GEND_MODE_INVALID_EXEC_STATE1, state ) break; @@ -272,77 +348,78 @@ /*********************************************************************//** * @brief * The execGenDialysateMode function executes the Gen dialysate mode state machine. - * @details \b Inputs: none + * @details \b Inputs: pendingStopDDGenDialRequest,genDialysateState * @details \b Outputs: Gen dialysate mode state machine executed * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when wrong gen dialysate state invoked. * @return current state. *************************************************************************/ U32 execGenDialysateMode( void ) { - // Continuous water inlet pressure check - if ( genDialysateState != DD_GEND_DIALYSATE_DELIVERY_PAUSE ) - { - if ( TRUE == areInletWaterConditionsAlarmsActive() ) // Check RO alarms as required - { - setModeGenDStateTransition( DD_GEND_DIALYSATE_DELIVERY_PAUSE ); - genDialysateState = DD_GEND_DIALYSATE_DELIVERY_PAUSE; - } - } + // Manage water level control + hydChamberWaterInletControl(); - // Manage water inlet temperature - if ( genDialysateState > DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE ) - { - hydChamberWaterInletControl(); - } - // Update any dynamic treatment parameter changes - if ( TRUE == isTreatementParamUpdated ) + updateTreatmentSettings(); + +#ifdef ENABLE_ALARM_2 + //Check dialysate temperature high/low alarms + checkDialysateTemperature(); +#endif + + // Update dialysate flow rate only when in the Dialysate Delivery state + updateDialysateToDialyzerFlowRate(); + + //Check temperature drift between D30 and D28 + checkDialysateTemperatureSensors(); + + //Monitor spent and bicarb chamber level + monitorChamberLevelStatus(); + + //TODO: Transition to post gen dialysate then standby. + if ( TRUE == pendingStopDDGenDialRequest ) { - updateTreatementSettings(); - //reset the flag - isTreatementParamUpdated = FALSE; + pendingStopDDGenDialRequest = FALSE; + requestNewOperationMode( DD_MODE_STAN ); } - - // execute current gen dialysate state - switch ( genDialysateState ) + else { - case DD_GEND_STATE_START: - setModeGenDStateTransition( DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE ); - genDialysateState = DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE; - break; + // execute current gen dialysate state + switch ( genDialysateState ) + { + case DD_GEND_STATE_START: + setModeGenDStateTransition( DD_GEND_DIALYSATE_BYPASS_STATE ); + genDialysateState = DD_GEND_DIALYSATE_BYPASS_STATE; + break; - case DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE: - genDialysateState = handleGenDHydraulicsChamberWaterInletCheckState(); - break; + case DD_GEND_DIALYSATE_BYPASS_STATE: + genDialysateState = handleGenDDialysateBypassState(); + break; - case DD_GEND_HYD_CHAMBER_PRESSURE_CHECK_STATE: - genDialysateState = handleGenDHydChamberPressureCheckState(); - break; + case DD_GEND_DIALYSATE_DELIVERY_STATE: + genDialysateState = handleGenDDialysateDeliveryState(); + break; - case DD_GEND_FRESH_DIALYSATE_PRESSURE_CHECK_STATE: - genDialysateState = handleGenDFreshDialysatePressureCheckState(); - break; + case DD_GEND_SPENT_CHAMBER_FILL_STATE: + genDialysateState = handleGenDSpentChamberFillState(); + break; - case DD_GEND_SPENT_DIALYSATE_PRESSURE_CHECK_STATE: - genDialysateState = handleGenDSpentDialysatePressureCheckState(); - break; + case DD_GEND_BICARB_CHAMBER_FILL_STATE: + genDialysateState = handleGenDBicarbChamberFillState(); + break; - case DD_GEND_PRODUCE_DIALYSATE_STATE: - genDialysateState = handleGenDProduceDialysateState(); - break; + case DD_GEND_DIALYSATE_DELIVERY_PAUSE: + genDialysateState = handleGenDDialysateDeliveryPauseState(); + break; - case DD_GEND_DIALYSATE_DELIVERY_STATE: - genDialysateState = handleGenDDialysateDeliveryState(); - break; + case DD_GEND_ISOLATED_UF_STATE: + genDialysateState = handleGenDIsolatedUFState(); + break; - case DD_GEND_DIALYSATE_DELIVERY_PAUSE: - genDialysateState = handleGenDDialysateDeliveryPauseState(); - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_GEND_MODE_INVALID_EXEC_STATE, genDialysateState ) - genDialysateState = DD_GEND_STATE_START; - break; + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_GEND_MODE_INVALID_EXEC_STATE, genDialysateState ) + genDialysateState = DD_GEND_STATE_START; + break; + } } //Publish Gen dialysate mode data @@ -359,32 +436,21 @@ * @details \b Outputs: none * @return the current state of gen dialysate mode *************************************************************************/ -static BOOL hydChamberWaterInletControl( void ) +BOOL hydChamberWaterInletControl( void ) { // Read floater switch BOOL result = FALSE; LEVEL_STATE_T floaterLevel = getLevelStatus( D6_LEVL ); - //LEVEL_STATE_T spentDialLevel = getLevelStatus( D46_LEVL ); - // Get the target temperature from TD - targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); + //Make sure Water Inlet Valve is open + setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); // High level is met if ( LEVEL_STATE_HIGH == floaterLevel ) { - // Get the target dialysate temperature - F32 targetTemperature = getGenDilaysateTargetTemperature(); - //turn off inlet water valve setValveState( D3_VALV, VALVE_STATE_CLOSED ); - if ( lastDialTargetTemperatureSet != targetTemperature ) - { - // Update the target temperature for heater control - setHeaterTargetTemperature( D5_HEAT, targetTemperature ); - lastDialTargetTemperatureSet = targetTemperature; - } - // Water level reached high. result = TRUE; } @@ -399,175 +465,284 @@ /*********************************************************************//** * @brief - * The handleGenDHydraulicsChamberWaterInletCheckState function checks the - * water level and allow the water into hydraulics for dialysate generation. - * @details \b Inputs: floater levels. + * The monitorChamberLevelStatus function checks the spent chamber and bicarb + * chamber level status and updates the corrosponding flags. + * @details \b Inputs: Spent and bicarb chamber levels. * @details \b Outputs: none - * @return the current state of gen dialysate mode + * @return none *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDHydraulicsChamberWaterInletCheckState( void ) +static void monitorChamberLevelStatus( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_HYD_CHAMBER_WATER_INLET_CHECK_STATE; + LEVEL_STATE_T spentChamberLevel = getLevelStatus( D46_LEVL ); + LEVEL_STATE_T bicarbChamberLevel = getLevelStatus( D63_LEVL ); - // Allow water inlet to hydraulics chamber - if ( TRUE == hydChamberWaterInletControl() ) + if ( LEVEL_STATE_LOW == spentChamberLevel ) { - // if water level is met, move to pressure check state - setModeGenDStateTransition( DD_GEND_HYD_CHAMBER_PRESSURE_CHECK_STATE ); - state = DD_GEND_HYD_CHAMBER_PRESSURE_CHECK_STATE; + pendingSpentChamberFill = TRUE; } - return state; + if ( LEVEL_STATE_LOW == bicarbChamberLevel ) + { + pendingBicarbChamberFill = TRUE; + } } /*********************************************************************//** * @brief - * The handleGenDHydChamberPressureCheckState function checks the - * hydraulics chamber pressure at chamber 4 of hydraulics. - * @details \b Inputs: pressure sensor readings, hydChamberPressureCheckStartTimeMS - * @details \b Outputs: none - * @return the current state of gen dialysate mode + * The calculateTargetDialysateTemp function calculate the delta temperature + * required for dialysate temperature to meet the set temperature at dialyzer. + * @details \b Inputs: Qd and target temperature. + * @details \b Outputs: Adjusted Target temperature + * @return none. *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDHydChamberPressureCheckState( void ) +static void calculateTargetDialysateTemp( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_HYD_CHAMBER_PRESSURE_CHECK_STATE; - F32 hydPressure = getFilteredPressure( D9_PRES ); + // Get the dialysate flow rate from TD + F32 dialFlowrate = getTDDialysateFlowrate(); + F32 deltaTemp = 0.0F; - // Hydraulics chamber negative pressure is in range ( -24 to -25 inHg ) - if ( ( hydPressure <= HYD_CHAMBER_TARGET_NEG_PRESS_MIN_PSI ) && ( hydPressure >= HYD_CHAMBER_TARGET_NEG_PRESS_MAX_PSI ) ) + if ( dialFlowrate >= LOW_DIAL_FLOW_RATE ) { - // Proceed to next state - setModeGenDStateTransition( DD_GEND_FRESH_DIALYSATE_PRESSURE_CHECK_STATE ); - state = DD_GEND_FRESH_DIALYSATE_PRESSURE_CHECK_STATE; + // linear releationship seen against high dialysate flowrate Vs DeltaTemp + // deltaTemp = (-0.0029 * Qd) + 3.47 + deltaTemp = ( LINEAR_SLOPE_FACTOR * dialFlowrate ) + LINEAR_INTERCEPT_FACTOR; } - else if ( TRUE == didTimeout( hydChamberPressureCheckStartTimeMS, HYD_CHAMBER_PRES_CHECK_TIME_OUT ) ) + else { - // time out alarm and pause the dialysate generation? - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DD_GEND_HYD_CHAMBER_PRESS_OUT_OF_RANGE, hydPressure ); - state = DD_GEND_DIALYSATE_DELIVERY_PAUSE; + // deltaTemp = (0.0006 * Qd * Qd)-(0.1743*Qd) + 17.3 + deltaTemp = ( QUAD_FIRST_COEFFICIENT * dialFlowrate * dialFlowrate ) + + ( QUAD_SECOND_COEFFICIENT * dialFlowrate ) + QUAD_THIRD_COEFFICIENT; } - return state; + // Adjust the D4 target temperature + targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature() + deltaTemp; } /*********************************************************************//** * @brief - * The handleGenDFreshDialysatePressureCheckState function checks the - * positive pressure level ( chamber 5) of hydraulics chamber or fresh - * dialysate side. - * @details \b Inputs: pressure sensor readings,hydChamberPressureCheckStartTimeMS + * The handleGenDDialysateIsolatedUFState function performs the + * Isolated ultrafiltration operations. + * @details \b Inputs: none. * @details \b Outputs: none * @return the current state of gen dialysate mode *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDFreshDialysatePressureCheckState( void ) +static DD_GEND_MODE_STATE_T handleGenDIsolatedUFState( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_FRESH_DIALYSATE_PRESSURE_CHECK_STATE; - F32 hydPressure = getFilteredPressure( D18_PRES ); + DD_GEND_MODE_STATE_T state = DD_GEND_ISOLATED_UF_STATE; - // Hydraulics chamber postive pressure is in range - if ( ( hydPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( hydPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) + //TODO: define isoalted ultrafiltration. + + return state; +} + +/*********************************************************************//** + * @brief + * The handleGenDDialysateBypassState function produces dialysate + * by executing balancing chamber and decides to pass the dialysate + * to dialyzer for treatment. + * @details \b Inputs: none + * @details \b Outputs: balancing chamber state. + * @return the current state of gen dialysate mode + *************************************************************************/ +static DD_GEND_MODE_STATE_T handleGenDDialysateBypassState( void ) +{ + DD_GEND_MODE_STATE_T state = DD_GEND_DIALYSATE_BYPASS_STATE; + BOOL balancingChambFillInProgress = getBalancingChamberFillinProgressStatus(); + + //Testing + if ( TRUE == delayBypassStateFlag ) { - // Proceed to next state - setModeGenDStateTransition( DD_GEND_SPENT_DIALYSATE_PRESSURE_CHECK_STATE ); - state = DD_GEND_SPENT_DIALYSATE_PRESSURE_CHECK_STATE; + if ( TRUE == didTimeout( bypassStateDelayStartTimeMS, DELAY_BC_SWITCHING_AT_START_UP ) ) + { + delayBypassStateFlag = FALSE; + } } - else if ( TRUE == didTimeout( hydChamberPressureCheckStartTimeMS, HYD_CHAMBER_PRES_CHECK_TIME_OUT ) ) + else { - // time out alarm and pause the dialysate generation? - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DD_GEND_FRESH_DIAL_PRESS_OUT_OF_RANGE, hydPressure ); - state = DD_GEND_DIALYSATE_DELIVERY_PAUSE; + //Execute balancing chamber + execBalancingChamberControl(); } +#ifdef __SPENT_CHAMBER_FILL__ + if ( ( TRUE == pendingSpentChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) + { + setModeGenDStateTransition( DD_GEND_SPENT_CHAMBER_FILL_STATE ); + pendingSpentChamberFill = FALSE; + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_SPENT_CHAMBER_FILL_STATE; + } +#endif +#ifdef __BICARB_CHAMBER_FILL__ + if ( ( TRUE == pendingBicarbChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) + { + setModeGenDStateTransition( DD_GEND_BICARB_CHAMBER_FILL_STATE ); + pendingBicarbChamberFill = FALSE; + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_BICARB_CHAMBER_FILL_STATE; + } +#endif + //if the produced dialysate is good and TD asks for dialysate delivery + //move to next state + if ( ( TRUE == getDialGoodToDeliverStatus() ) && ( FALSE == getTDDialyzerBypass() ) ) + { + setModeGenDStateTransition( DD_GEND_DIALYSATE_DELIVERY_STATE ); + isDialDeliveryInProgress.data = TRUE; + state = DD_GEND_DIALYSATE_DELIVERY_STATE; + } + return state; } /*********************************************************************//** * @brief - * The handleGenDSpentDialysatePressureCheckState function checks the - * spent dialyaste pressure is in range to begin balancing chamber dialysate - * delivery. - * @details \b Inputs: pressure sensor readings,spentDialPressureCheckStartTimeMS. - * @details \b Outputs: none + * The handleGenDDialysateDeliveryState function performing dialysate + * delivery by executing balancing chamber. + * @details \b Inputs: none + * @details \b Outputs: balancing chamber state. * @return the current state of gen dialysate mode *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDSpentDialysatePressureCheckState( void ) +static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryState( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_SPENT_DIALYSATE_PRESSURE_CHECK_STATE; - F32 spentdialPressure = getFilteredPressure( D51_PRES ); + DD_GEND_MODE_STATE_T state = DD_GEND_DIALYSATE_DELIVERY_STATE; + LEVEL_STATE_T spentChamberLevel = getLevelStatus( D46_LEVL ); + LEVEL_STATE_T bicarbChamberLevel = getLevelStatus( D63_LEVL ); - // Spent dialysate pressure is in range - if ( ( spentdialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) && ( spentdialPressure <= SPENT_DIAL_PRESSURE_MAX_PSIG ) ) + // if TD asks for bypass or dialysate is not good to deliver + //transition to bypass dialystate state + if ( ( FALSE == getDialGoodToDeliverStatus() ) || ( TRUE == getTDDialyzerBypass() ) ) { - // Proceed to next state - transitionToBalChamberFill(); - setModeGenDStateTransition( DD_GEND_PRODUCE_DIALYSATE_STATE ); - state = DD_GEND_PRODUCE_DIALYSATE_STATE; + setModeGenDStateTransition( DD_GEND_DIALYSATE_BYPASS_STATE ); + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_DIALYSATE_BYPASS_STATE; } - else if ( TRUE == didTimeout( spentDialPressureCheckStartTimeMS, SPENT_DIAL_PRES_CHECK_TIME_OUT ) ) +#ifdef __SPENT_CHAMBER_FILL__ + else if ( ( TRUE == pendingSpentChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) { - // time out alarm and pause the dialysate generation? - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DD_GEND_SPENT_DIAL_PRESS_OUT_OF_RANGE, spentdialPressure ); - state = DD_GEND_DIALYSATE_DELIVERY_PAUSE; + setModeGenDStateTransition( DD_GEND_SPENT_CHAMBER_FILL_STATE ); + pendingSpentChamberFill = FALSE; + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_SPENT_CHAMBER_FILL_STATE; } +#endif +#ifdef __BICARB_CHAMBER_FILL__ + else if ( ( TRUE == pendingBicarbChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) + { + setModeGenDStateTransition( DD_GEND_BICARB_CHAMBER_FILL_STATE ); + pendingBicarbChamberFill = FALSE; + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_BICARB_CHAMBER_FILL_STATE; + } +#endif + else + { + //Execute balancing chamber + execBalancingChamberControl(); + //Execute ultrafiltration + execUFControl(); + } + return state; } /*********************************************************************//** * @brief - * The handleGenDProduceDialysateState function produces dialysate - * by executing balancing chamber and decides to pass the dialysate - * for treatment. - * @details \b Inputs: none + * The handleGenDSpentChamberFillState function performing spent + * chamber filling/degassing by executing balancing chamber. + * @details \b Inputs: D46 level. * @details \b Outputs: balancing chamber state. * @return the current state of gen dialysate mode *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDProduceDialysateState( void ) +static DD_GEND_MODE_STATE_T handleGenDSpentChamberFillState( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_PRODUCE_DIALYSATE_STATE; + DD_GEND_MODE_STATE_T state = DD_GEND_SPENT_CHAMBER_FILL_STATE; - //Execute balancing chamber - execBalancingChamberControl(); + LEVEL_STATE_T spentChamberLevel = getLevelStatus( D46_LEVL ); + U32 totalSpentChamberFill = getTotalSpentChamberFillCounts(); - //if the produced dialysate is good and TD asks for dialysate delivery - // move to next state - if ( ( TRUE == getDialGoodToDeliverStatus() ) && ( FALSE == getTDDialyzerBypass() ) ) + // High level is met or total fill count exceeded + if ( ( LEVEL_STATE_HIGH == spentChamberLevel ) || + ( totalSpentChamberFill >= SPENT_CHAMBER_FILL_MAX_COUNT ) ) { - setModeGenDStateTransition( DD_GEND_DIALYSATE_DELIVERY_STATE ); - state = DD_GEND_DIALYSATE_DELIVERY_STATE; + setModeGenDStateTransition( DD_GEND_DIALYSATE_BYPASS_STATE ); + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_DIALYSATE_BYPASS_STATE; + + //Trigger alarm if count exceeded + if ( totalSpentChamberFill >= SPENT_CHAMBER_FILL_MAX_COUNT ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SC_FILL_TIMEOUT_FAULT, SPENT_CHAMBER_FILL_MAX_COUNT, 0 ) + } } + else + { + //Execute Spent chamber fill + execSpentChamberFillControl(); + } return state; } /*********************************************************************//** * @brief - * The handleGenDDialysateDeliveryState function performing dialysate - * delivery by executing balancing chamber. - * @details \b Inputs: none - * @details \b Outputs: balancing chamber state. + * The handleGenDBicarbChamberFillState function performing Bicarb + * chamber filling/degassing by opening up the purge valve which is connected + * to negative pressure chamber D of Hydraulics chamber. + * @details \b Inputs: D63 level. + * @details \b Outputs: isBicarbFillTimeout,valves actuation. * @return the current state of gen dialysate mode *************************************************************************/ -static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryState( void ) +static DD_GEND_MODE_STATE_T handleGenDBicarbChamberFillState( void ) { - DD_GEND_MODE_STATE_T state = DD_GEND_DIALYSATE_DELIVERY_STATE; + DD_GEND_MODE_STATE_T state = DD_GEND_BICARB_CHAMBER_FILL_STATE; - //Execute balancing chamber - execBalancingChamberControl(); + LEVEL_STATE_T bicarbChamberLevel = getLevelStatus( D63_LEVL ); + BOOL isBicarbFillTimeout = FALSE; - // if TD asks for bypass or dialysate is not good to deliver - //transition to produce dialystate state - if ( ( FALSE == getDialGoodToDeliverStatus() ) || ( TRUE == getTDDialyzerBypass() ) ) + if ( TRUE == didTimeout( bicarbFillStartTimeMS, BICARB_CHAMBER_FILL_TIMEOUT ) ) { - setModeGenDStateTransition( DD_GEND_PRODUCE_DIALYSATE_STATE ); - state = DD_GEND_PRODUCE_DIALYSATE_STATE; + isBicarbFillTimeout = TRUE; + // Raise alarm for bicarb fill timeout + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_BICARB_FILL_TIMEOUT_FAULT, BICARB_CHAMBER_FILL_TIMEOUT, 0 ) } + // High level is met or fill timeout + if ( ( LEVEL_STATE_HIGH == bicarbChamberLevel ) || ( TRUE == isBicarbFillTimeout ) ) + { + setValveState( D64_VALV, VALVE_STATE_CLOSED ); // Close Bicarb chamber purge valve + bicarbFillStartTimeMS = 0; + + setModeGenDStateTransition( DD_GEND_DIALYSATE_BYPASS_STATE ); + isDialDeliveryInProgress.data = FALSE; + state = DD_GEND_DIALYSATE_BYPASS_STATE; + } + return state; } /*********************************************************************//** * @brief + * The requestDDGenDialyasteStop function handles an TD request to stop + * generation dialysis mode. + * @details \b Inputs: Generation dialysate mode / state + * @details \b Outputs: mode pendingStopDDGenDialRequest + * @return TRUE if request accepted, FALSE if not. + *************************************************************************/ +BOOL requestDDGenDialyasteStop( void ) +{ + BOOL status = FALSE; + + if ( DD_MODE_GEND == getCurrentOperationMode() ) + { + pendingStopDDGenDialRequest = TRUE; + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief * The handleGenDDialysateDeliveryPauseState function pause the dialysate * delivery due to alarms conditions or some control asked to be in * paused state. @@ -599,34 +774,74 @@ /*********************************************************************//** * @brief - * The setTreatementParamUpdate function sets the flag to indicate one or more + * The setTreatmentParamUpdate function sets the flag to indicate one or more * treatement parameters updated. * gen dialysate mode. * @details \b Inputs: none - * @details \b Outputs: isTreatementParamUpdated + * @details \b Outputs: isTreatmentParamUpdated * @return none *************************************************************************/ -void setTreatementParamUpdate( void ) +void setTreatmentParamUpdate( void ) { - isTreatementParamUpdated = TRUE; + isTreatmentParamUpdated = TRUE; } /*********************************************************************//** * @brief - * The updateTreatementSettings function updates the switching rate post the + * The updateTreatmentSettings function updates the switching rate post the * treatement parameters updated during treatement. - * @details \b Inputs: none - * @details \b Outputs: balChamberSwitchingPeriod. + * @details \b Inputs: isTreatmentParamUpdated + * @details \b Outputs: balChamberSwitchingPeriod,isTreatmentParamUpdated. * @return none *************************************************************************/ -void updateTreatementSettings( void ) +void updateTreatmentSettings( void ) { - // Update the Balancing chamber switching rate based on dialysis rate - updateBalChamberSwitchingPeriod(); + // Update any dynamic treatment parameter changes + if ( TRUE == isTreatmentParamUpdated ) + { + // Update the balancing chamber switching rate based on dialysis rate + updateBalChamberSwitchingPeriod(); - //TODO: update others parameters setting as needed. + // Get the target temperature from TD + //targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); + calculateTargetDialysateTemp(); + //Reset flag + signaltoResetPrimaryHeaterAdjustedTargetTemp(); + + // Update the target temperature for heater control + setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); + + //TODO: update others parameters setting as needed. + signalUFRateUpdate(); + + //reset the flag + isTreatmentParamUpdated = FALSE; + } } +/*********************************************************************//** + * @brief + * The updateDialysateToDialyzerFlowRate function updates the current dialysate + * to dialyzer flow rate only when in the dialysate delivery state, otherwise + * the flow rate is set to zero + * @details \b Inputs: genDialysateState + * @details \b Outputs: dialysateToDialyzerFlowRate + * @return none + *************************************************************************/ +void updateDialysateToDialyzerFlowRate( void ) +{ + // Check the current Gen Dialysate Mode state + if ( DD_GEND_DIALYSATE_DELIVERY_STATE == genDialysateState ) + { + // Update the dialysate flow rate to the TD request + dialysateToDialyzerFlowRate = getTDDialysateFlowrate(); + } + else + { + // Set the dialysate flow rate to zero + dialysateToDialyzerFlowRate = 0.0F; + } +} /*********************************************************************//** * @brief @@ -638,13 +853,8 @@ *************************************************************************/ U32 getDialGoodToDeliverStatus( void ) { - U32 result = isDialysateGoodtoDeliver.data; + U32 result = getU32OverrideValue( &isDialysateGoodtoDeliver ); - if ( OVERRIDE_KEY == isDialysateGoodtoDeliver.override ) - { - result = isDialysateGoodtoDeliver.ovData; - } - return result; } @@ -658,13 +868,8 @@ *************************************************************************/ U32 getDialDeliveryProgressStatus( void ) { - U32 result = isDialDeliveryInProgress.data; + U32 result = getU32OverrideValue( &isDialDeliveryInProgress ); - if ( OVERRIDE_KEY == isDialDeliveryInProgress.override ) - { - result = isDialDeliveryInProgress.ovData; - } - return result; } @@ -678,34 +883,81 @@ *************************************************************************/ static U32 getGenDilaysateDataPublishInterval( void ) { - U32 result = genDialysateDataPublishInterval.data; + U32 result = getU32OverrideValue( &genDialysateDataPublishInterval ); - if ( OVERRIDE_KEY == genDialysateDataPublishInterval.override ) - { - result = genDialysateDataPublishInterval.ovData; - } - return result; } /*********************************************************************//** * @brief - * The getGenDilaysateTargetTemperature function gets the target dialysate + * The getGenDialysateTargetTemperature function gets the target dialysate * temperature. - * @details \b Inputs: getGenDilaysateTargetTemperature + * @details \b Inputs: getGenDialysateTargetTemperature * @details \b Outputs: none * @return the target dialysate temperature for the treatment. *************************************************************************/ -static F32 getGenDilaysateTargetTemperature( void ) +static F32 getGenDialysateTargetTemperature( void ) { - F32 result = targetHydChamberFluidTemp.data; + F32 temp = getF32OverrideValue( &targetHydChamberFluidTemp ); - if ( OVERRIDE_KEY == targetHydChamberFluidTemp.override ) + return temp; +} + +/*********************************************************************//** + * @brief + * The checkDialysateTemperature function checks the dialysate temperature + * against the target temperature and alarm if temperature is out of range. + * @details \b Inputs: targetTemp, dialysateTemp + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP when + * dialysate temp goes beyound high safety temperature limit + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP when + * dialysate temp goes beyound high temperature limit + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP when + * dialysate temp goes beyound low temperature limit + * @return none + *************************************************************************/ +static void checkDialysateTemperature( void ) +{ + F32 dialysateTemp = getConductivityTemperatureValue( D29_COND ); // Assuming the closest temp sensor to dialyzer + F32 targetTemp = getTDTargetDialysateTemperature(); + BOOL isDialTempAboveHighSafety = ( dialysateTemp >= DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isDialTempAboveLowSafety = ( dialysateTemp > DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isDialTempBelowLowSafety = ( dialysateTemp < DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ? TRUE : FALSE ); + F32 dialHigh = targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isDialTempAboveDialysateTarget = ( dialysateTemp > dialHigh ? TRUE : FALSE ); + F32 dialLow = targetTemp - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isDialTempBelowDialysateTarget = ( dialysateTemp < dialLow ? TRUE : FALSE ); + BOOL isTempBelowTrigger = (BOOL)( isDialTempBelowLowSafety || isDialTempBelowDialysateTarget ); + BOOL isTempAboveTrigger = (BOOL)( isDialTempAboveLowSafety || isDialTempAboveDialysateTarget ); + + if ( DD_GEND_DIALYSATE_DELIVERY_STATE == genDialysateState ) { - result = targetHydChamberFluidTemp.ovData; - } + // check clear condition first + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ) ) + { + isDialTempAboveHighSafety = ( dialysateTemp <= ( targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, isDialTempAboveHighSafety, dialysateTemp, targetTemp ); - return result; + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ) ) + { + isTempAboveTrigger = ( dialysateTemp <= ( targetTemp + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTempAboveTrigger, dialysateTemp, targetTemp ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ) ) + { + isTempBelowTrigger = ( dialysateTemp >= ( targetTemp - DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); + } + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTempBelowTrigger, dialysateTemp, targetTemp ); + } + else + { + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, FALSE, dialysateTemp, targetTemp ); + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, FALSE, dialysateTemp, targetTemp ); + checkPersistentAlarm(ALARM_ID_DD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, FALSE, dialysateTemp, targetTemp ); + } } /*********************************************************************//** @@ -733,6 +985,7 @@ data.d18Pressure = getFilteredPressure( D18_PRES ); data.d51Pressure = getFilteredPressure( D51_PRES ); data.isDialysateGoodtoDeliver = (BOOL)getDialGoodToDeliverStatus(); + data.currentQd = dialysateToDialyzerFlowRate; broadcastData( MSG_ID_DD_GEN_DIALYSATE_MODE_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( GEN_DIALYSATE_MODE_DATA_T ) ); @@ -807,10 +1060,52 @@ * value of the hydraulics chamber fluid temperature. * @return TRUE if override successful, FALSE if not *************************************************************************/ -//BOOL testGenDHydChamberFluidTempOverride( MESSAGE_T *message ) -//{ -// BOOL result = f32Override( message, &targetHydChamberFluidTemp ); -// -// return result; -//} +BOOL testGenDHydChamberFluidTempOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &targetHydChamberFluidTemp ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testGenDExecStateOverride function sets the Gen dialysate execution state + * machine to given state. + * @details \b Inputs: tester logged in, execStateSet + * @details \b Outputs: genDialysateState + * @param message set message from Dialin which includes the generate dialysate + * execution state to be set. + * @return TRUE if set request is successful, FALSE if not + *************************************************************************/ +BOOL testGenDExecStateOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify tester has logged in with DD + if ( TRUE == isTestingActivated() ) + { + // Verify payload length is valid + if ( sizeof( GEND_EXEC_STATE_SET_CMD_PAYLOAD_T ) == message->hdr.payloadLen ) + { + GEND_EXEC_STATE_SET_CMD_PAYLOAD_T payload; + + memcpy( &payload, message->payload, sizeof(GEND_EXEC_STATE_SET_CMD_PAYLOAD_T) ); + + // Validate the state to be set + if ( payload.execStateSet < NUM_OF_DD_GEND_MODE_STATES ) + { + //set the GenD exec state machine + DD_GEND_MODE_STATE_T state = (DD_GEND_MODE_STATE_T)payload.execStateSet; + + setModeGenDStateTransition( state ); + genDialysateState = state; + + result = TRUE; + } + } + } + + return result; +} + /**@}*/