Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -ra711f7995e555b503ed8c295f98fbe7bb9e5abf5 -rd73a1020427b4c9becb65c91dd69dde3318584f5 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision a711f7995e555b503ed8c295f98fbe7bb9e5abf5) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision d73a1020427b4c9becb65c91dd69dde3318584f5) @@ -1,37 +1,42 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeGenDialysate.c * -* @author (last) Vinayakam Mani -* @date (last) 30-Oct-2024 +* @author (last) Sameer Kalliadan Poyil +* @date (last) 23-Apr-2026 * * @author (original) Vinayakam Mani -* @date (original) 30-Oct-2024 +* @date (original) 06-Nov-2024 * ***************************************************************************/ +#include // For ceilf + #include "BalancingChamber.h" #include "ConcentratePumps.h" #include "Conductivity.h" #include "DialysatePumps.h" #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" +#include "MessagePayloads.h" #include "Messaging.h" #include "ModeGenDialysate.h" #include "ModeStandby.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Pressure.h" +#include "RinsePump.h" #include "SpentChamberFill.h" #include "TaskGeneral.h" #include "TDInterface.h" #include "Temperature.h" +#include "TestSupport.h" #include "Timers.h" #include "Ultrafiltration.h" #include "Valves.h" @@ -53,16 +58,18 @@ #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. +#define ZERO_DIAL_FLOW_RATE 0.0F ///< Zero dialysate flow rate +#define SPENT_CHAMBER_FILL_MAX_COUNT 10 ///< Total number of spent chamber fill allowed. +#define BICARB_CHAMBER_FILL_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Bicarb chamber fill timeout. + +#define PUMP_SPEED_SLOPE_FACTOR_DIENER_2000 1.24F ///< D48 Diener 2000 pump speed slope (y = 1.24x + 30). +#define PUMP_SPEED_INTERCEPT_FACTOR_DIENER_2000 30.0F ///< D48 Diener 2000 pump speed intercept. +#define PUMP_SPEED_SLOPE_FACTOR_DIENER_1000 2.869F ///< D48 Diener 1000 pump speed slope (y = 2.869x + 25.956). +#define PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000 25.956F ///< D48 Diener 1000 pump speed intercept. +#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., +#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 { @@ -85,6 +92,8 @@ //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) +static U32 d48PumpSpeed; ///< Initial D48 pump speed based on the Qd. // ********** private function prototypes ********** @@ -96,10 +105,11 @@ 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 ); +static U32 getFreshDialPumpInitialRpm( void ); /*********************************************************************//** * @brief @@ -133,9 +143,11 @@ bicarbFillStartTimeMS = 0; pendingSpentChamberFill = FALSE; pendingBicarbChamberFill = FALSE; + d48PumpSpeed = getDialysatePumpMinRPM( D48_PUMP ); //Testing bypassStateDelayStartTimeMS = 0; delayBypassStateFlag = TRUE; + dialysateToDialyzerFlowRate = 0.0F; //Initialize balancing chamber module initBalanceChamber(); @@ -155,8 +167,14 @@ *************************************************************************/ U32 transitionToGenDialysateMode( void ) { + U32 initialD48PumpSpeed = 0U; + initGenDialysateMode(); setCurrentSubState( NO_SUB_STATE ); + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); + initialD48PumpSpeed = getCalculatedD48PumpSpeedForBCFill(); + setD48PumpSpeedForBCFill( initialD48PumpSpeed ); transitionToUltrafiltration(); return genDialysateState; @@ -189,6 +207,26 @@ /*********************************************************************//** * @brief + * The getFreshDialPumpInitialRpm function returns fresh dialysate pump initial + * rpm based on hardwawre configuration. + * @details Inputs: FRESH_DIAL_PUMP_INITIAL_RPM, FRESH_DIAL_PUMP_INITIAL_RPM_B1_9_B2_0 + * @details Outputs: none + * @return fresh dialysate pump initial RPM for the active hardware variant + *************************************************************************/ +static U32 getFreshDialPumpInitialRpm( void ) +{ + U32 rpm = FRESH_DIAL_PUMP_INITIAL_RPM_B1_9_B2_0; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) ) + { + rpm = FRESH_DIAL_PUMP_INITIAL_RPM; + } + + return rpm; +} + +/*********************************************************************//** + * @brief * The setModeGenDStateTransition function sets the actuators and variables * for the state transition in generate dialysis mode. * @details Inputs: Valve states, Pump speed @@ -202,72 +240,137 @@ switch( state ) { case DD_GEND_STATE_START: - // Do nothing + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); break; 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( 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 + setValveState( D8_VALV, VALVE_STATE_CLOSED ); + setValveState( D54_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_CLOSED ); + setValveState( D31_VALV, VALVE_STATE_CLOSED ); + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + { + setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + } + // Turn on the primary heater calculateTargetDialysateTemp(); setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); setD28TempFeedbackControl( TRUE ); startHeater( D5_HEAT ); + //Turn on Trimmer heater + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) == TRUE ) + { + setHeaterTargetTemperature( D45_HEAT, getFilteredTemperatureValue( D4_TEMP ) ); + } + else + { + setHeaterTargetTemperature( D45_HEAT, getFilteredTemperatureValue( D99_TEMP ) ); + } + startHeater( D45_HEAT ); + //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( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); + //Rinse pump On + setRinsePumpState( RINSE_PUMP_STATE_ON ); + transitionToBalChamberFill(); + // Activate Balancing Chamber Switching + requestBalChamberSwitching( TRUE ); //Testing bypassStateDelayStartTimeMS = getMSTimerCount(); delayBypassStateFlag = TRUE; break; case DD_GEND_DIALYSATE_DELIVERY_STATE: + // Activate Balancing Chamber Switching + requestBalChamberSwitching( TRUE ); + //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( D8_VALV, VALVE_STATE_CLOSED ); + setValveState( D54_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_CLOSED ); + setValveState( D31_VALV, VALVE_STATE_CLOSED ); setValveState( D14_VALV, VALVE_STATE_OPEN ); - setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve // Turn on the primary heater calculateTargetDialysateTemp(); setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); setD28TempFeedbackControl( TRUE ); startHeater( D5_HEAT ); + //Turn on Trimmer heater + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) == TRUE ) + { + setHeaterTargetTemperature( D45_HEAT, getFilteredTemperatureValue( D4_TEMP ) ); + } + else + { + setHeaterTargetTemperature( D45_HEAT, getFilteredTemperatureValue( D99_TEMP ) ); + } + startHeater( D45_HEAT ); + //setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); + //Rinse pump On + setRinsePumpState( RINSE_PUMP_STATE_ON ); + // 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 + + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + { + setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + } break; case DD_GEND_SPENT_CHAMBER_FILL_STATE: + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); + //Set valves and actuators setValveState( D35_VALV, VALVE_STATE_CLOSED ); // VDI setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO - - setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); + setValveState( D8_VALV, VALVE_STATE_CLOSED ); + setValveState( D54_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_CLOSED ); + setValveState( D31_VALV, VALVE_STATE_CLOSED ); setValveState( D14_VALV, VALVE_STATE_OPEN ); - setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve + + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + { + setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + } + setValveState( D47_VALV, VALVE_STATE_OPEN ); // Spent chamber purge valve requestConcentratePumpOff( D76_PUMP, FALSE ); @@ -279,15 +382,23 @@ setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); setD28TempFeedbackControl( TRUE ); startHeater( D5_HEAT ); + // Stop trimmer heater + stopHeater( D45_HEAT ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_FILL_RPM, TRUE ); + //Rinse pump On + setRinsePumpState( RINSE_PUMP_STATE_ON ); + //Transition to spent chamber fill transitionToSpentChamberFill(); break; case DD_GEND_BICARB_CHAMBER_FILL_STATE: + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); + requestConcentratePumpOff( D11_PUMP, FALSE ); requestConcentratePumpOff( D10_PUMP, FALSE ); requestConcentratePumpOff( D76_PUMP, FALSE ); @@ -298,10 +409,15 @@ setValveState( D40_VALV, VALVE_STATE_CLOSED ); // VDO setValveState( D14_VALV, VALVE_STATE_CLOSED ); - setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve + setValveState( D53_VALV, VALVE_STATE_OPEN ); // Drain valve setValveState( D34_VALV, VALVE_STATE_OPEN ); // Bypass valve - setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); - setValveState( D64_VALV, VALVE_STATE_OPEN ); // Bicarb chamber purge valve + + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + { + setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve + setValveState( D64_VALV, VALVE_STATE_OPEN ); // Bicarb chamber purge valve + } + bicarbFillStartTimeMS = getMSTimerCount(); // Turn on the primary heater @@ -311,28 +427,59 @@ setD28TempFeedbackControl( FALSE ); startHeater( D5_HEAT ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + //Rinse pump On + setRinsePumpState( RINSE_PUMP_STATE_ON ); + + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); break; case DD_GEND_DIALYSATE_DELIVERY_PAUSE: - // stop the motor during pause conditions - signalDialysatePumpHardStop( D12_PUMP ); + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); signalDialysatePumpHardStop( D48_PUMP ); requestConcentratePumpOff( D11_PUMP, FALSE ); requestConcentratePumpOff( D10_PUMP, FALSE ); requestConcentratePumpOff( D76_PUMP, FALSE ); + //Rinse pump Off + setRinsePumpState( RINSE_PUMP_STATE_OFF ); - stopHeater( D5_HEAT ); + // 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 ); stopHeater( D45_HEAT ); - //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 + //close valves + setValveState( D35_VALV, VALVE_STATE_CLOSED ); + setValveState( D40_VALV, VALVE_STATE_CLOSED ); + setValveState( D31_VALV, VALVE_STATE_CLOSED ); + setValveState( D47_VALV, VALVE_STATE_CLOSED ); + setValveState( D54_VALV, VALVE_STATE_CLOSED ); + setValveState( D14_VALV, VALVE_STATE_CLOSED ); + setValveState( D52_VALV, VALVE_STATE_CLOSED ); + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_VALV, VALVE_STATE_CLOSED ); + setValveState( D8_VALV, VALVE_STATE_CLOSED ); + //Close all balancing chamber valves + valveControlForBCClosedState(); + + setValveState( D34_VALV, VALVE_STATE_OPEN ); + setValveState( D53_VALV, VALVE_STATE_OPEN ); + + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + { + setValveState( D80_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + } break; case DD_GEND_ISOLATED_UF_STATE: + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); //TODO : define actuators states break; @@ -363,6 +510,9 @@ checkDialysateTemperature(); #endif + // Update dialysate flow rate only when in the Dialysate Delivery state + updateDialysateToDialyzerFlowRate(); + //Check temperature drift between D30 and D28 checkDialysateTemperatureSensors(); @@ -433,22 +583,20 @@ BOOL hydChamberWaterInletControl( void ) { // Read floater switch - BOOL result = FALSE; - LEVEL_STATE_T floaterLevel = getLevelStatus( D6_LEVL ); + BOOL result = FALSE; + LVL_STATE_T floaterLevel = getFloaterStatus( D6_LEVL ); + BOOL balancingChambFillInProgress = getBalancingChamberFillinProgressStatus(); - //Make sure Water Inlet Valve is open - setValveState( DD_M4_VALV, VALVE_STATE_OPEN ); - // High level is met - if ( LEVEL_STATE_HIGH == floaterLevel ) + if ( LVL_STATE_HIGH == floaterLevel ) { //turn off inlet water valve setValveState( D3_VALV, VALVE_STATE_CLOSED ); // Water level reached high. result = TRUE; } - else + else if ( LVL_STATE_LOW == floaterLevel || TRUE != balancingChambFillInProgress ) { // if level is not met,allow inlet water to hydraulics chamber setValveState( D3_VALV, VALVE_STATE_OPEN ); @@ -459,6 +607,31 @@ /*********************************************************************//** * @brief + * The getD48PumpSpeedForBCFill function returns the calculated D48 pump speed + * @details \b Inputs: d48PumpSpeed + * @details \b Outputs: none + * @return D48 pump speed. + *************************************************************************/ +U32 getD48PumpSpeedForBCFill( void ) +{ + return d48PumpSpeed; +} + +/*********************************************************************//** + * @brief + * The setD48PumpSpeedForBCFill function sets the updated D48 pump speed. + * @details \b Inputs: none + * @details \b Outputs: d48PumpSpeed + * @param pumpSpeed Dialysate pump speed + * @return none. + *************************************************************************/ +void setD48PumpSpeedForBCFill( U32 pumpSpeed ) +{ + d48PumpSpeed = pumpSpeed; +} + +/*********************************************************************//** + * @brief * 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. @@ -483,33 +656,43 @@ /*********************************************************************//** * @brief - * 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. + * The getCalculatedD48PumpSpeedForBCFill function returns the D48 pump speed + * calculated from dialysate flow rate (Qd) for continuous delivery. + * @details \b Inputs: Qd from TD, test config TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP. + * @details \b Outputs: none + * @return Calculated D48 pump speed in RPM (Diener 1000 or 2000 formula per test config). *************************************************************************/ -static void calculateTargetDialysateTemp( void ) +U32 getCalculatedD48PumpSpeedForBCFill( void ) { - // Get the dialysate flow rate from TD F32 dialFlowrate = getTDDialysateFlowrate(); - F32 deltaTemp = 0.0F; + F32 slope; + F32 intercept; + F32 calculatedSpeed; + U32 rpm; - if ( dialFlowrate >= LOW_DIAL_FLOW_RATE ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) { - // linear releationship seen against high dialysate flowrate Vs DeltaTemp - // deltaTemp = (-0.0029 * Qd) + 3.47 - deltaTemp = ( LINEAR_SLOPE_FACTOR * dialFlowrate ) + LINEAR_INTERCEPT_FACTOR; + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_2000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_2000; } else { - // deltaTemp = (0.0006 * Qd * Qd)-(0.1743*Qd) + 17.3 - deltaTemp = ( QUAD_FIRST_COEFFICIENT * dialFlowrate * dialFlowrate ) + - ( QUAD_SECOND_COEFFICIENT * dialFlowrate ) + QUAD_THIRD_COEFFICIENT; + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_1000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000; } - // Adjust the D4 target temperature - targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature() + deltaTemp; + // Calculate nominal speed from Qd. + calculatedSpeed = ( slope * dialFlowrate ) + intercept; + + // Prevent negative before converting to unsigned and round up using ceilf. + if ( calculatedSpeed < 0.0F ) + { + calculatedSpeed = 0.0F; + } + + rpm = (U32)ceilf( calculatedSpeed ); + + return rpm; } /*********************************************************************//** @@ -542,30 +725,29 @@ { DD_GEND_MODE_STATE_T state = DD_GEND_DIALYSATE_BYPASS_STATE; BOOL balancingChambFillInProgress = getBalancingChamberFillinProgressStatus(); + F32 freshDialPressure = getFilteredPressure( D18_PRES ); + F32 spentDialPressure = getFilteredPressure( D51_PRES ); - //Testing + //Testing : Wait for the fresh and spent pressure in range or timeout if ( TRUE == delayBypassStateFlag ) { - if ( TRUE == didTimeout( bypassStateDelayStartTimeMS, DELAY_BC_SWITCHING_AT_START_UP ) ) + if ( ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( spentDialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) ) || + ( TRUE == didTimeout( bypassStateDelayStartTimeMS, DELAY_BC_SWITCHING_AT_START_UP ) ) ) { delayBypassStateFlag = FALSE; } } - else - { - //Execute balancing chamber - execBalancingChamberControl(); - } -#ifdef __SPENT_CHAMBER_FILL__ - if ( ( TRUE == pendingSpentChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) + if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_SPENT_CHAMBER_H_FILL ) == TRUE ) { - setModeGenDStateTransition( DD_GEND_SPENT_CHAMBER_FILL_STATE ); - pendingSpentChamberFill = FALSE; - isDialDeliveryInProgress.data = FALSE; - state = DD_GEND_SPENT_CHAMBER_FILL_STATE; + 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 ) ) { @@ -597,9 +779,10 @@ *************************************************************************/ static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryState( void ) { - 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 ); + 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 ); + BOOL balancingChambFillInProgress = getBalancingChamberFillinProgressStatus(); // if TD asks for bypass or dialysate is not good to deliver //transition to bypass dialystate state @@ -609,15 +792,16 @@ isDialDeliveryInProgress.data = FALSE; state = DD_GEND_DIALYSATE_BYPASS_STATE; } -#ifdef __SPENT_CHAMBER_FILL__ - else if ( ( TRUE == pendingSpentChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) + else if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_SPENT_CHAMBER_H_FILL ) == TRUE ) { - setModeGenDStateTransition( DD_GEND_SPENT_CHAMBER_FILL_STATE ); - pendingSpentChamberFill = FALSE; - isDialDeliveryInProgress.data = FALSE; - state = DD_GEND_SPENT_CHAMBER_FILL_STATE; + 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__ else if ( ( TRUE == pendingBicarbChamberFill ) && ( FALSE == balancingChambFillInProgress ) ) { @@ -629,9 +813,6 @@ #endif else { - //Execute balancing chamber - execBalancingChamberControl(); - //Execute ultrafiltration execUFControl(); } @@ -747,8 +928,13 @@ static DD_GEND_MODE_STATE_T handleGenDDialysateDeliveryPauseState( void ) { DD_GEND_MODE_STATE_T state = DD_GEND_DIALYSATE_DELIVERY_PAUSE; + F32 dialFlowrate = getTDDialysateFlowrate(); - //TODO : Handle pause state. + // Resume pause when Qd is not zero + if ( dialFlowrate > ZERO_DIAL_FLOW_RATE ) + { + state = DD_GEND_DIALYSATE_BYPASS_STATE; + } return state; } @@ -782,6 +968,20 @@ /*********************************************************************//** * @brief + * The setTargetHydChamberTemp function updates the target hydraulics temperature + * for D5 heater control + * @details \b Inputs: none + * @details \b Outputs: targetHydChamberFluidTemp + * @param temperature The target temperature for D5 heater control + * @return none + *************************************************************************/ +void setTargetHydChamberTemp( F32 temperature ) +{ + targetHydChamberFluidTemp.data = temperature; +} + +/*********************************************************************//** + * @brief * The updateTreatmentSettings function updates the switching rate post the * treatement parameters updated during treatement. * @details \b Inputs: isTreatmentParamUpdated @@ -790,6 +990,8 @@ *************************************************************************/ void updateTreatmentSettings( void ) { + F32 initialPumpSpeed = 0.0F; + // Update any dynamic treatment parameter changes if ( TRUE == isTreatmentParamUpdated ) { @@ -808,13 +1010,42 @@ //TODO: update others parameters setting as needed. signalUFRateUpdate(); + //Update D48 pump speed + initialPumpSpeed = getCalculatedD48PumpSpeedForBCFill(); + setD48PumpSpeedForBCFill( initialPumpSpeed ); + setDialysatePumpTargetRPM( D48_PUMP, (U32)initialPumpSpeed, TRUE ); + //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 * The getDialGoodToDeliverStatus function gets the dialysate good to deliver * status. * @details \b Inputs: isDialysateGoodtoDeliver @@ -889,7 +1120,7 @@ *************************************************************************/ static void checkDialysateTemperature( void ) { - F32 dialysateTemp = getConductivityTemperatureValue( D29_COND ); // Assuming the closest temp sensor to dialyzer + F32 dialysateTemp = getFilteredConductivitySensorTemperature( 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 ); @@ -948,13 +1179,8 @@ data.genDialysateExecState = (U32)getCurrentGenDialysateState(); data.isDialDelInProgress = (BOOL)getDialDeliveryProgressStatus(); - data.d6Level = (U32)getLevelStatus( D6_LEVL ); - data.d63Level = (U32)getLevelStatus( D63_LEVL ); - data.d46Level = (U32)getLevelStatus( D46_LEVL ); - data.d9Pressure = getFilteredPressure( D9_PRES ); - 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 ) ); @@ -989,8 +1215,8 @@ * @brief * The testDialDeliveryInProgressOverride function sets the override value * of the dialysate delivery In progress flag. - * @details Inputs: isDialDeliveryInProgress - * @details Outputs: isDialDeliveryInProgress + * @details \b Inputs: isDialDeliveryInProgress + * @details \b Outputs: isDialDeliveryInProgress * @param message Override message from Dialin which includes the override * value to override the dialysate delivery in progress flag. * @return TRUE if override successful, FALSE if not @@ -1006,8 +1232,8 @@ * @brief * The testDialGoodToDeliverStatusOverride function sets the override value * of the dialysate good to deliver status flag. - * @details Inputs: isDialysateGoodtoDeliver - * @details Outputs: isDialysateGoodtoDeliver + * @details \b Inputs: isDialysateGoodtoDeliver + * @details \b Outputs: isDialysateGoodtoDeliver * @param message Override message from Dialin which includes the override * value to override the dialysate delivery in progress flag. * @return TRUE if override successful, FALSE if not @@ -1077,4 +1303,84 @@ return result; } +/*********************************************************************//** + * @brief + * The testValidateDDGenDialysateChangeReq function validate whether request + * operation sub mode is legal or not. + * @details \b Inputs: none + * @details \b Outputs: none + * @param newSubMode the enumerated sub state of the mode + * @return TRUE if request is legal, FALSE if not + *************************************************************************/ +BOOL testValidateDDGenDialysateChangeReq( U32 newSubMode ) +{ + BOOL result = FALSE; + + if ( newSubMode < NUM_OF_DD_GEND_MODE_STATES ) + { + switch ( newSubMode ) + { + // TODO add validate condition after checking with Vinay + case DD_GEND_STATE_START: + case DD_GEND_DIALYSATE_BYPASS_STATE: + case DD_GEND_DIALYSATE_DELIVERY_STATE: + case DD_GEND_SPENT_CHAMBER_FILL_STATE: + result = TRUE; + break; + + case DD_GEND_ISOLATED_UF_STATE: + case DD_GEND_BICARB_CHAMBER_FILL_STATE: + case DD_GEND_DIALYSATE_DELIVERY_PAUSE: + default: + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSignalNewDDGenDialysateSubMode function request transition + * to a new operation sub mode. + * @details \b Inputs: none + * @details \b Outputs: genDialysateState + * @param newSubMode the enumerated sub state of the mode + * @return none + *************************************************************************/ +void testSignalNewDDGenDialysateSubMode( U32 newSubMode ) +{ + if ( newSubMode < NUM_OF_DD_GEND_MODE_STATES ) + { + genDialysateState = (DD_GEND_MODE_STATE_T)newSubMode; + + switch ( newSubMode ) + { + // TODO add logic after checking with Vinay + // Any of these state require no special handling + + case DD_GEND_DIALYSATE_BYPASS_STATE: + isDialDeliveryInProgress.data = FALSE; + break; + + case DD_GEND_DIALYSATE_DELIVERY_STATE: + isDialDeliveryInProgress.data = TRUE; + break; + + case DD_GEND_SPENT_CHAMBER_FILL_STATE: + pendingSpentChamberFill = FALSE; + isDialDeliveryInProgress.data = FALSE; + break; + + case DD_GEND_STATE_START: + case DD_GEND_ISOLATED_UF_STATE: + case DD_GEND_BICARB_CHAMBER_FILL_STATE: + case DD_GEND_DIALYSATE_DELIVERY_PAUSE: + default: + break; + } + setModeGenDStateTransition( genDialysateState ); + } +} + /**@}*/