Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r8aa885b17330f096934f175d35912c3c95825039 -r145fd716a856f864f39fb0f9884865f6e45b9256 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 8aa885b17330f096934f175d35912c3c95825039) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 145fd716a856f864f39fb0f9884865f6e45b9256) @@ -7,13 +7,14 @@ * * @file ModeGenDialysate.c * -* @author (last) Dara Navaei -* @date (last) 18-Mar-2026 +* @author (last) Sameer Kalliadan Poyil +* @date (last) 15-Jun-2026 * * @author (original) Vinayakam Mani * @date (original) 06-Nov-2024 * ***************************************************************************/ + #include // For ceilf #include "BalancingChamber.h" @@ -23,6 +24,7 @@ #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" +#include "MessagePayloads.h" #include "Messaging.h" #include "ModeGenDialysate.h" #include "ModeStandby.h" @@ -56,15 +58,10 @@ #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 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). @@ -108,7 +105,6 @@ 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 ); @@ -175,7 +171,8 @@ initGenDialysateMode(); setCurrentSubState( NO_SUB_STATE ); - //calculateD48PumpSpeedForBCFill(); + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); initialD48PumpSpeed = getCalculatedD48PumpSpeedForBCFill(); setD48PumpSpeedForBCFill( initialD48PumpSpeed ); transitionToUltrafiltration(); @@ -243,7 +240,8 @@ switch( state ) { case DD_GEND_STATE_START: - // Do nothing + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); break; case DD_GEND_DIALYSATE_BYPASS_STATE: @@ -259,7 +257,7 @@ setValveState( D85_VALV, VALVE_STATE_CLOSED ); setValveState( D31_VALV, VALVE_STATE_CLOSED ); - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve setValveState( D64_VALV, VALVE_STATE_CLOSED ); @@ -272,7 +270,14 @@ startHeater( D5_HEAT ); //Turn on Trimmer heater - setHeaterTargetTemperature( D45_HEAT, getD4AverageTemperature() ); + 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 @@ -285,13 +290,18 @@ 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( D8_VALV, VALVE_STATE_CLOSED ); @@ -309,7 +319,14 @@ startHeater( D5_HEAT ); //Turn on Trimmer heater - setHeaterTargetTemperature( D45_HEAT, getD4AverageTemperature() ); + 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 ); @@ -325,14 +342,17 @@ setValveState( D35_VALV, VALVE_STATE_OPEN ); // VDI setValveState( D40_VALV, VALVE_STATE_OPEN ); // VDO - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { 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 @@ -345,7 +365,7 @@ 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 ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve setValveState( D64_VALV, VALVE_STATE_CLOSED ); @@ -376,6 +396,9 @@ 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 ); @@ -389,7 +412,7 @@ 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 ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { setValveState( D80_VALV, VALVE_STATE_OPEN ); // Bicarb valve setValveState( D64_VALV, VALVE_STATE_OPEN ); // Bicarb chamber purge valve @@ -412,6 +435,8 @@ break; case DD_GEND_DIALYSATE_DELIVERY_PAUSE: + // Deactivate Balancing Chamber Switching + requestBalChamberSwitching( FALSE ); setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); signalDialysatePumpHardStop( D48_PUMP ); requestConcentratePumpOff( D11_PUMP, FALSE ); @@ -445,14 +470,16 @@ setValveState( D34_VALV, VALVE_STATE_OPEN ); setValveState( D53_VALV, VALVE_STATE_OPEN ); - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == FALSE ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { 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; @@ -557,19 +584,19 @@ { // Read floater switch BOOL result = FALSE; - LEVEL_STATE_T floaterLevel = getLevelStatus( D6_LEVL ); + LVL_STATE_T floaterLevel = getFloaterStatus( D6_LEVL ); BOOL balancingChambFillInProgress = getBalancingChamberFillinProgressStatus(); // 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 if ( LEVEL_STATE_LOW == floaterLevel || TRUE != balancingChambFillInProgress ) + 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 ); @@ -629,46 +656,14 @@ /*********************************************************************//** * @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. - *************************************************************************/ -static void calculateTargetDialysateTemp( void ) -{ - // Get the dialysate flow rate from TD - F32 dialFlowrate = getTDDialysateFlowrate(); - F32 deltaTemp = 0.0F; - - if ( dialFlowrate >= LOW_DIAL_FLOW_RATE ) - { - // linear relationship seen against high dialysate flowrate Vs DeltaTemp - // deltaTemp = (-0.0029 * Qd) + 3.47 - deltaTemp = ( LINEAR_SLOPE_FACTOR * dialFlowrate ) + LINEAR_INTERCEPT_FACTOR; - } - else - { - // deltaTemp = (0.0006 * Qd * Qd)-(0.1743*Qd) + 17.3 - deltaTemp = ( QUAD_FIRST_COEFFICIENT * dialFlowrate * dialFlowrate ) + - ( QUAD_SECOND_COEFFICIENT * dialFlowrate ) + QUAD_THIRD_COEFFICIENT; - } - - // Adjust the D4 target temperature - targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature() + deltaTemp; -} - -/*********************************************************************//** - * @brief - * 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. + * The getD48PumpSpeed function returns the ceiled D48 pump speed. + * @details \b Inputs: Active flow rate(Qd), pump test config. * @details \b Outputs: none - * @return Calculated D48 pump speed in RPM (Diener 1000 or 2000 formula per test config). + * @return Ceiled D48 pump speed in RPM . *************************************************************************/ -U32 getCalculatedD48PumpSpeedForBCFill( void ) +U32 getD48PumpSpeed( void ) { - F32 dialFlowrate = getTDDialysateFlowrate(); + F32 dialFlowrate = getBalChamberActiveDialysateFlowrate(); F32 slope; F32 intercept; F32 calculatedSpeed; @@ -685,10 +680,8 @@ intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000; } - // 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; @@ -701,6 +694,30 @@ /*********************************************************************//** * @brief + * The getCalculatedD48PumpSpeedForBCFill function returns the D48 pump speed + * for balancing chamber fill after applying the low-speed clamp. + * @details \b Inputs: Active BC Qd (or TD Qd before BC period init), pump test config. + * @details \b Outputs: none + * @return D48 pump speed in RPM for BC fill (Diener formula with low-speed floor). + *************************************************************************/ +U32 getCalculatedD48PumpSpeedForBCFill( void ) +{ + U32 rpm; + U32 nominalRpm; + + nominalRpm = getD48PumpSpeed(); + rpm = nominalRpm; + + if ( nominalRpm <= BAL_CHAMBER_TIME_BASED_D48_SPEED_RPM ) + { + rpm = BAL_CHAMBER_TIME_BASED_D48_SPEED_RPM; + } + + return rpm; +} + +/*********************************************************************//** + * @brief * The handleGenDDialysateIsolatedUFState function performs the * Isolated ultrafiltration operations. * @details \b Inputs: none. @@ -741,11 +758,6 @@ delayBypassStateFlag = FALSE; } } - else - { - //Execute balancing chamber - execBalancingChamberControl(); - } if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_SPENT_CHAMBER_H_FILL ) == TRUE ) { @@ -822,9 +834,6 @@ #endif else { - //Execute balancing chamber - execBalancingChamberControl(); - //Execute ultrafiltration execUFControl(); } @@ -980,6 +989,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 @@ -999,8 +1022,6 @@ // Get the target temperature from TD //targetHydChamberFluidTemp.data = getTDTargetDialysateTemperature(); calculateTargetDialysateTemp(); - //Reset flag - signaltoResetPrimaryHeaterAdjustedTargetTemp(); // Update the target temperature for heater control setHeaterTargetTemperature( D5_HEAT, getGenDialysateTargetTemperature() ); @@ -1009,9 +1030,9 @@ signalUFRateUpdate(); //Update D48 pump speed - //calculateD48PumpSpeedForBCFill(); initialPumpSpeed = getCalculatedD48PumpSpeedForBCFill(); setD48PumpSpeedForBCFill( initialPumpSpeed ); + setDialysatePumpTargetRPM( D48_PUMP, (U32)initialPumpSpeed, TRUE ); //reset the flag isTreatmentParamUpdated = FALSE; @@ -1213,8 +1234,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 @@ -1230,8 +1251,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