Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r7278aeac8fdd894067a05c3bd3a177d38c0b0803 -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 7278aeac8fdd894067a05c3bd3a177d38c0b0803) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -34,6 +34,7 @@ #include "TDInterface.h" #include "Temperature.h" #include "TestSupport.h" +#include "Timers.h" #include "Valves.h" /** @@ -64,6 +65,10 @@ #define COMP_SLOPE -0.000376F ///< Balancing chamber temperature compensation slope factor #define COMP_INTERCEPT 1.007269F ///< Balancing chamber temperature compensation intercept factor +#define BC_SS_VOL_DISCARD_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Discard doses for 10 min before averaging. +#define BC_SS_VOL_WINDOW_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Averaging window length (2 min). +#define BC_SS_VOL_MATCH_PCT 0.05F ///< Two consecutive window avgs must match within ±5%. + /// Payload record structure for balancing chamber switch only request typedef struct { @@ -116,6 +121,18 @@ // Balancing chamber state change tracker static BAL_CHAMBER_EXEC_STATE_T prevBalChamberState; ///< Balancing chamber Previous State tracking variable +// Steady-state bicarb dose volume (survives initBalanceChamber / PreGen→GenD): +// discard 10 min, then consecutive 2-min averages until two match within ±5%. +static BOOL ssBicarbVolActive; ///< TRUE while collecting (until SS confirmed) +static U32 ssBicarbVolStartTimeMS; ///< Collection start time (ms) — discard gate +static U32 ssBicarbVolWindowStartMS; ///< Current 2-min window start (ms) +static F32 ssBicarbVolSampleSum; ///< Dose sum in current window +static U32 ssBicarbVolSampleCount; ///< Dose count in current window +static F32 ssBicarbVolPrevAvg; ///< Previous 2-min window average (mL) +static BOOL ssBicarbVolHavePrev; ///< TRUE after first completed window +static F32 ssBicarbVolSteadyState; ///< Confirmed steady-state dose volume (mL) +static BOOL ssBicarbVolValid; ///< TRUE when steady-state is confirmed + // ********** private function prototypes ********** static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1FillStart( void ); @@ -134,6 +151,7 @@ static BOOL isBalChamberTimeBasedSwitching( void ); static void scheduleFirstCycleRelaxAfterQdApply( void ); static void calculateBalancingChamberError( void ); +static void recordSteadyStateBicarbVolDoseSample( F32 bicarbVolume ); /*********************************************************************//** * @brief @@ -264,6 +282,156 @@ /*********************************************************************//** * @brief + * The recordSteadyStateBicarbVolDoseSample function accumulates bicarb dose + * samples after the discard interval while SS volume is still being collected. + * @details \b Inputs: bicarbVolume, ssBicarbVolActive, ssBicarbVolValid, + * ssBicarbVolStartTimeMS + * @details \b Outputs: ssBicarbVolSampleSum, ssBicarbVolSampleCount + * @param bicarbVolume Bicarb dose volume at BC dose start (mL) + * @return none + *************************************************************************/ +static void recordSteadyStateBicarbVolDoseSample( F32 bicarbVolume ) +{ + if ( ( TRUE == ssBicarbVolActive ) && + ( FALSE == ssBicarbVolValid ) && + ( TRUE == didTimeout( ssBicarbVolStartTimeMS, BC_SS_VOL_DISCARD_MS ) ) ) + { + ssBicarbVolSampleSum += bicarbVolume; + ssBicarbVolSampleCount++; + } +} + +/*********************************************************************//** + * @brief + * The notifySteadyStateBicarbVolCalStart function starts steady-state bicarb + * volume collection. Keeps an already confirmed steady-state value. + * @details \b Inputs: TEST_CONFIG_DD_DISABLE_DRY_BICARB, ssBicarbVolValid + * @details \b Outputs: ssBicarbVolActive, ssBicarbVolValid, ssBicarbVolSteadyState, + * ssBicarbVolPrevAvg, ssBicarbVolHavePrev, ssBicarbVolSampleSum, + * ssBicarbVolSampleCount, ssBicarbVolStartTimeMS, ssBicarbVolWindowStartMS + * @return none + *************************************************************************/ +void notifySteadyStateBicarbVolCalStart( void ) +{ + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && + ( FALSE == ssBicarbVolValid ) ) + { + ssBicarbVolActive = TRUE; + ssBicarbVolValid = FALSE; + ssBicarbVolSteadyState = 0.0F; + ssBicarbVolPrevAvg = 0.0F; + ssBicarbVolHavePrev = FALSE; + ssBicarbVolSampleSum = 0.0F; + ssBicarbVolSampleCount = 0; + ssBicarbVolStartTimeMS = getMSTimerCount(); + ssBicarbVolWindowStartMS = 0; + } +} + +/*********************************************************************//** + * @brief + * The serviceSteadyStateBicarbVolCal function finishes consecutive 2-min + * dose averages after discard; when two consecutive averages match within + * ±5%, the latest average is stored as the steady-state volume. + * @details \b Inputs: ssBicarbVolActive, ssBicarbVolValid, ssBicarbVolStartTimeMS, + * ssBicarbVolWindowStartMS, ssBicarbVolSampleSum, ssBicarbVolSampleCount, + * ssBicarbVolHavePrev, ssBicarbVolPrevAvg + * @details \b Outputs: ssBicarbVolSteadyState, ssBicarbVolValid, ssBicarbVolActive, + * ssBicarbVolPrevAvg, ssBicarbVolHavePrev, ssBicarbVolSampleSum, + * ssBicarbVolSampleCount, ssBicarbVolWindowStartMS + * @return none + *************************************************************************/ +void serviceSteadyStateBicarbVolCal( void ) +{ + F32 windowAvg = 0.0F; + F32 delta = 0.0F; + BOOL matched = FALSE; + + if ( ( TRUE == ssBicarbVolActive ) && ( FALSE == ssBicarbVolValid ) ) + { + if ( TRUE == didTimeout( ssBicarbVolStartTimeMS, BC_SS_VOL_DISCARD_MS ) ) + { + // Start first averaging window when discard ends + if ( 0 == ssBicarbVolWindowStartMS ) + { + ssBicarbVolSampleSum = 0.0F; + ssBicarbVolSampleCount = 0; + ssBicarbVolHavePrev = FALSE; + ssBicarbVolWindowStartMS = getMSTimerCount(); + } + else if ( TRUE == didTimeout( ssBicarbVolWindowStartMS, BC_SS_VOL_WINDOW_MS ) ) + { + if ( ssBicarbVolSampleCount > 0 ) + { + windowAvg = ssBicarbVolSampleSum / (F32)ssBicarbVolSampleCount; + } + + if ( ( TRUE == ssBicarbVolHavePrev ) && ( ssBicarbVolPrevAvg > 0.0F ) ) + { + delta = windowAvg - ssBicarbVolPrevAvg; + if ( delta < 0.0F ) + { + delta = -delta; + } + + if ( delta <= ( ssBicarbVolPrevAvg * BC_SS_VOL_MATCH_PCT ) ) + { + matched = TRUE; + } + } + + if ( TRUE == matched ) + { + ssBicarbVolSteadyState = windowAvg; + ssBicarbVolValid = TRUE; + ssBicarbVolActive = FALSE; + } + else + { + // Slide window: previous = current, start next 2 min + ssBicarbVolPrevAvg = windowAvg; + ssBicarbVolHavePrev = TRUE; + ssBicarbVolSampleSum = 0.0F; + ssBicarbVolSampleCount = 0; + ssBicarbVolWindowStartMS = getMSTimerCount(); + } + } + } + } +} + +/*********************************************************************//** + * @brief + * The isSteadyStateBicarbVolumeValid function reports whether steady-state + * bicarb volume has been confirmed. + * @details \b Inputs: ssBicarbVolValid + * @details \b Outputs: none + * @return TRUE when steady-state bicarb volume is valid + *************************************************************************/ +BOOL isSteadyStateBicarbVolumeValid( void ) +{ + BOOL result = ssBicarbVolValid; + + return result; +} + +/*********************************************************************//** + * @brief + * The getSteadyStateBicarbVolume function returns the confirmed steady-state + * bicarb dose volume. + * @details \b Inputs: ssBicarbVolSteadyState + * @details \b Outputs: none + * @return Confirmed steady-state bicarb dose volume (mL) + *************************************************************************/ +F32 getSteadyStateBicarbVolume( void ) +{ + F32 result = ssBicarbVolSteadyState; + + return result; +} + +/*********************************************************************//** + * @brief * The getAcidDoseVol function gets acid mix volume * @details \b Inputs: acidDoseVolume * @details \b Outputs: none @@ -707,6 +875,7 @@ // start acid and bicarb pump with the expected quantity setConcentratePumpTargetSpeed( D11_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, acidVolume ); setConcentratePumpTargetSpeed( D10_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, bicarbVolume ); + recordSteadyStateBicarbVolDoseSample( bicarbVolume ); requestConcentratePumpOn( D11_PUMP ); requestConcentratePumpOn( D10_PUMP ); } @@ -1024,6 +1193,7 @@ // start acid and bicarb pump with the expected quantity setConcentratePumpTargetSpeed( D11_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, acidVolume ); setConcentratePumpTargetSpeed( D10_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, bicarbVolume ); + recordSteadyStateBicarbVolDoseSample( bicarbVolume ); requestConcentratePumpOn( D11_PUMP ); requestConcentratePumpOn( D10_PUMP ); } Index: firmware/App/Controllers/BalancingChamber.h =================================================================== diff -u -r4237cbced773b985ff69a8c2af8287dbd5457f24 -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision 4237cbced773b985ff69a8c2af8287dbd5457f24) +++ firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -75,6 +75,10 @@ F32 getBalancingChamberError( void ); // Get balancing chamber error to adjust UF rate. F32 getBicarbDoseVol( void ); // Get liquid bicarb dose volume F32 getAcidDoseVol( void ); // Get acid dose volume +void notifySteadyStateBicarbVolCalStart( void ); // Start SS bicarb vol cal (10 min discard + 2-min avgs) +void serviceSteadyStateBicarbVolCal( void ); // Service SS bicarb vol cal (match consecutive 2-min avgs) +BOOL isSteadyStateBicarbVolumeValid( void ); // TRUE when steady-state bicarb volume has been confirmed +F32 getSteadyStateBicarbVolume( void ); // Confirmed steady-state bicarb dose volume (mL) BOOL testDDBalChamberDataPublishIntervalOverride( MESSAGE_T *message ); // To override the balancing chamber data publish interval BOOL testBalChamberSwFreqOverride( MESSAGE_T *message ); // To override the balancing chamber switching frequency Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r590c4b129a1b8fced97b8f653fb58e97fdf64a28 -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 590c4b129a1b8fced97b8f653fb58e97fdf64a28) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -60,8 +60,9 @@ #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 DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_PERCENT 5.0F ///< Dialysate conductivity out of target tolerance percent. -#define DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Dialysate conductivity out of target timeout in milliseconds. +#define DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate conductivity out of target timeout in milliseconds. #define DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate conductivity clear persistence timeout. +#define BICARBONATE_CARTRIDGE_LOW_LEVEL_FACTOR 1.25F ///< Bicarb mix volume vs steady-state factor for cartridge low. #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. @@ -112,6 +113,7 @@ static void updateDialysateToDialyzerFlowRate( void ); static void checkDialysateTemperature( void ); static void checkDialysateConductivity( void ); +static void checkBicarbonateCartridgeLevelLow( void ); static void monitorChamberLevelStatus( void ); static void publishGenDialysateModeData( void ); static U32 getFreshDialPumpInitialRpm( void ); @@ -167,6 +169,7 @@ initPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CARTRIDGE_LOW_LEVEL, DIALYSATE_CONDUCTIVITY_CLEAR_TIMEOUT_MS, DIALYSATE_CONDUCTIVITY_OUT_OF_TARGET_TIMEOUT_MS ); } /*********************************************************************//** @@ -517,6 +520,11 @@ // Update any dynamic treatment parameter changes updateTreatmentSettings(); + // Advance steady-state bicarb volume calibration (continues from PreGen) + serviceSteadyStateBicarbVolCal(); + + checkBicarbonateCartridgeLevelLow(); + #ifdef ENABLE_ALARM_2 //Check dialysate temperature high/low alarms checkDialysateTemperature(); @@ -1300,6 +1308,46 @@ /*********************************************************************//** * @brief + * The checkBicarbonateCartridgeLevelLow function checks bicarbonate mix + * volume against confirmed steady-state volume for cartridge low (alarm 243). + * Triggered when Bicarbonate Volume > Steady State Bicarbonate Volume + 25% + * for continuous 10 sec (±150 ms) while in Bypass or Delivery. + * @details \b Inputs: getBicarbMixVol, getSteadyStateBicarbVolume, genDialysateState + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_BICARBONATE_CARTRIDGE_LOW_LEVEL when + * getBicarbMixVol() > getSteadyStateBicarbVolume() * 1.25F + * @return none + *************************************************************************/ +static void checkBicarbonateCartridgeLevelLow( void ) +{ + F32 currentBicarbVol = getBicarbMixVol(); + F32 steadyStateVol = getSteadyStateBicarbVolume(); + F32 threshold = steadyStateVol * BICARBONATE_CARTRIDGE_LOW_LEVEL_FACTOR; + BOOL outOfRange = FALSE; + + if ( ( FALSE == isSteadyStateBicarbVolumeValid() ) || + ( steadyStateVol <= 0.0F ) || + ( ( DD_GEND_DIALYSATE_BYPASS_STATE != genDialysateState ) && + ( DD_GEND_DIALYSATE_DELIVERY_STATE != genDialysateState ) ) ) + { + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CARTRIDGE_LOW_LEVEL, FALSE, currentBicarbVol, steadyStateVol ); + } + else + { + outOfRange = ( currentBicarbVol > threshold ? TRUE : FALSE ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_BICARBONATE_CARTRIDGE_LOW_LEVEL ) ) + { + // Clear when volume returns to at or below threshold + outOfRange = ( currentBicarbVol <= threshold ? FALSE : TRUE ); + } + + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CARTRIDGE_LOW_LEVEL, outOfRange, currentBicarbVol, steadyStateVol ); + } +} + +/*********************************************************************//** + * @brief * The publishGenDialysateModeData function broadcasts the generate dialysate * mode data at defined interval. * @details \b Inputs: genDialysateDataPublicationTimerCounter Index: firmware/App/Modes/ModePreGenDialysate.c =================================================================== diff -u -rbd522c8ffdf75130571e5b6a79d1b1d6acd78b1c -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Modes/ModePreGenDialysate.c (.../ModePreGenDialysate.c) (revision bd522c8ffdf75130571e5b6a79d1b1d6acd78b1c) +++ firmware/App/Modes/ModePreGenDialysate.c (.../ModePreGenDialysate.c) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -17,16 +17,21 @@ #include "BalancingChamber.h" #include "ConcentratePumps.h" +#include "Conductivity.h" #include "DialysatePumps.h" #include "DryBiCart.h" #include "Heaters.h" +#include "MixingControl.h" #include "ModePreGenDialysate.h" #include "ModeGenDialysate.h" #include "ModeFault.h" #include "Messaging.h" #include "OperationModes.h" +#include "PersistentAlarm.h" #include "Pressure.h" #include "TaskGeneral.h" +#include "TDInterface.h" +#include "TestSupport.h" #include "Timers.h" #include "Utilities.h" #include "Valves.h" @@ -42,6 +47,12 @@ #define PRE_GEN_DIALYSATE_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the pre-gen dialysate mode data published. #define HYD_CHAMBER_PRES_CHECK_TIME_OUT ( 30 * MS_PER_SECOND ) ///< Time out period when hydraulics chamber pressure check initiated #define NEG_PRES_PERSISTENCE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Persistence time for Hydraulics chamber negative degassing pressure check. +#define PRE_GEN_CONDUCTIVITY_ALARM_ARM_MS ( 600 * MS_PER_SECOND ) ///< Arm conductivity alarms after this production runtime. +#define PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Conductivity alarm set persistence timeout. +#define PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Conductivity alarm clear persistence timeout. +#define PRE_GEN_COND_TOL_RX_NOT_ENTERED_PCT 15.0F ///< Dial/acid conductivity tolerance before Rx entered. +#define PRE_GEN_COND_TOL_RX_ENTERED_PCT 5.0F ///< Dial/acid conductivity tolerance after Rx entered. +#define PRE_GEN_BICARB_COND_TOL_PCT 5.0F ///< Bicarb conductivity tolerance percent. // ********** private data ********** @@ -53,13 +64,15 @@ static BOOL pendingStopDDPreGenDialRequest; ///< Flag indicating TD has requested DD stop the pre generation dialysate. static U32 preGenDialysatePublishTimerCounter; ///< Pre-Gen Dialysate data broadcast timer counter used to schedule when to transmit data. static OVERRIDE_U32_T preGenDialysateModePublishInterval; ///< Interval (in task intervals) at which to publish pre-gen dialysate mode data to CAN bus. +static U32 preGenModeEntryTimeMS; ///< PreGen mode entry time for conductivity alarm arming (ms). // ********** private function prototypes ********** static void publishPreGenDialysateState( void ); static DD_PRE_GEN_DIALYSATE_STATE_T handlePreGenDialysateFillCompleteCheckState( void ); static DD_PRE_GEN_DIALYSATE_STATE_T handlePreGenWetSelfTestState( void ); static DD_PRE_GEN_DIALYSATE_STATE_T handleDryBicartInitialFillState( void ); +static void checkDialysateConductivity( void ); //Wet Self test static void setModePreGenWetSelfStateTransition( DD_WET_SELF_TEST_STATE_T state ); @@ -87,6 +100,15 @@ preGenDialysateModePublishInterval.ovData = PRE_GEN_DIALYSATE_DATA_PUB_INTERVAL; preGenDialysateModePublishInterval.ovInitData = 0; preGenDialysateModePublishInterval.override = OVERRIDE_RESET; + preGenModeEntryTimeMS = getMSTimerCount(); + + // Same conductivity persistent-alarm pattern as Gen Dialysate mode + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, PRE_GEN_CONDUCTIVITY_CLEAR_TIMEOUT_MS, PRE_GEN_CONDUCTIVITY_SET_TIMEOUT_MS ); } /*********************************************************************//** @@ -124,6 +146,9 @@ //Manage Inlet water control hydChamberWaterInletControl(); + // Same GenD-style conductivity checks (armed after 600 s in PreGen mode) + checkDialysateConductivity(); + //TODO: To be placed in correct states once states defined. if ( TRUE == pendingStartDDGenDialRequest ) { @@ -134,6 +159,7 @@ else if ( TRUE == pendingStopDDPreGenDialRequest ) { pendingStopDDPreGenDialRequest = FALSE; + requestBalChamberSwitching( FALSE ); requestNewOperationMode( DD_MODE_STAN ); } else @@ -154,7 +180,7 @@ break; case DD_PRE_GEN_DIALYSATE_WAIT_FOR_GEND: - // TODO : handle wait for Gen dialysate + // Wait for Dialin/TD Gen Dialysate start command break; default: @@ -293,6 +319,122 @@ /*********************************************************************//** * @brief + * The checkDialysateConductivity function checks dialysate, acid, and + * bicarbonate concentrate conductivity against theoretical values. + * Mirrors Gen Dialysate mode checking, with PreGen-specific arming and + * Rx-based dialysate/acid tolerances. + * @details \b Inputs: filtered conductivity sensor readings, theoretical values + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED / + * HIGH_DETECTED, ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW / HIGH, + * ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW / HIGH + * @return none + *************************************************************************/ +static void checkDialysateConductivity( void ) +{ + F32 measuredBicarbConductivity = getFilteredConductivity( D74_COND ); + F32 measuredDialysateConductivity = getFilteredConductivity( D29_COND ); + F32 measuredAcidConductivity = measuredDialysateConductivity - measuredBicarbConductivity; + F32 theoreticalBicarbConductivity = getBicarbConductivityPre(); + F32 theoreticalAcidConductivity = getAcidConducivityPost(); + F32 theoreticalDialysateConductivity = getTotalConductivity(); + F32 dialAcidTolerancePct = PRE_GEN_COND_TOL_RX_NOT_ENTERED_PCT; + F32 dialAcidPercentFactor = 0.0F; + F32 bicarbPercentFactor = ( PRE_GEN_BICARB_COND_TOL_PCT / 100.0F ); + F32 bicarbLowThreshold = 0.0F; + F32 bicarbHighThreshold = 0.0F; + F32 acidLowThreshold = 0.0F; + F32 acidHighThreshold = 0.0F; + F32 dialysateLowThreshold = 0.0F; + F32 dialysateHighThreshold = 0.0F; + BOOL isBicarbCondBelowTarget = FALSE; + BOOL isBicarbCondAboveTarget = FALSE; + BOOL isAcidCondBelowTarget = FALSE; + BOOL isAcidCondAboveTarget = FALSE; + BOOL isDialysateCondBelowTarget = FALSE; + BOOL isDialysateCondAboveTarget = FALSE; + BOOL alarmsArmed = FALSE; + + if ( TRUE == getTDRxEntered() ) + { + dialAcidTolerancePct = PRE_GEN_COND_TOL_RX_ENTERED_PCT; + } + + dialAcidPercentFactor = ( dialAcidTolerancePct / 100.0F ); + bicarbLowThreshold = theoreticalBicarbConductivity * ( 1.0F - bicarbPercentFactor ); + bicarbHighThreshold = theoreticalBicarbConductivity * ( 1.0F + bicarbPercentFactor ); + acidLowThreshold = theoreticalAcidConductivity * ( 1.0F - dialAcidPercentFactor ); + acidHighThreshold = theoreticalAcidConductivity * ( 1.0F + dialAcidPercentFactor ); + dialysateLowThreshold = theoreticalDialysateConductivity * ( 1.0F - dialAcidPercentFactor ); + dialysateHighThreshold = theoreticalDialysateConductivity * ( 1.0F + dialAcidPercentFactor ); + isBicarbCondBelowTarget = ( measuredBicarbConductivity < bicarbLowThreshold ? TRUE : FALSE ); + isBicarbCondAboveTarget = ( measuredBicarbConductivity > bicarbHighThreshold ? TRUE : FALSE ); + isAcidCondBelowTarget = ( measuredAcidConductivity < acidLowThreshold ? TRUE : FALSE ); + isAcidCondAboveTarget = ( measuredAcidConductivity > acidHighThreshold ? TRUE : FALSE ); + isDialysateCondBelowTarget = ( measuredDialysateConductivity < dialysateLowThreshold ? TRUE : FALSE ); + isDialysateCondAboveTarget = ( measuredDialysateConductivity > dialysateHighThreshold ? TRUE : FALSE ); + + // Arm after 600 sec in PreGen mode (GenD itself is started by Dialin/TD command) + if ( TRUE == didTimeout( preGenModeEntryTimeMS, PRE_GEN_CONDUCTIVITY_ALARM_ARM_MS ) ) + { + alarmsArmed = TRUE; + } + + if ( ( FALSE == alarmsArmed ) || + ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_CONDUCTIVITY_ALARMS ) ) || + ( theoreticalBicarbConductivity <= 0.0F ) || + ( theoreticalAcidConductivity <= 0.0F ) || + ( theoreticalDialysateConductivity <= 0.0F ) ) + { + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, FALSE, measuredBicarbConductivity, theoreticalBicarbConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, FALSE, measuredAcidConductivity, theoreticalAcidConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, FALSE, measuredDialysateConductivity, theoreticalDialysateConductivity ); + } + else + { + if ( TRUE == isAlarmActive( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW ) ) + { + isBicarbCondBelowTarget = ( measuredBicarbConductivity >= bicarbLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_LOW, isBicarbCondBelowTarget, measuredBicarbConductivity, theoreticalBicarbConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH ) ) + { + isBicarbCondAboveTarget = ( measuredBicarbConductivity <= bicarbHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_BICARBONATE_CONDUCTIVITY_HIGH, isBicarbCondAboveTarget, measuredBicarbConductivity, theoreticalBicarbConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW ) ) + { + isAcidCondBelowTarget = ( measuredAcidConductivity >= acidLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_LOW, isAcidCondBelowTarget, measuredAcidConductivity, theoreticalAcidConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH ) ) + { + isAcidCondAboveTarget = ( measuredAcidConductivity <= acidHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_ACID_CONCENTRATE_CONDUCTIVITY_HIGH, isAcidCondAboveTarget, measuredAcidConductivity, theoreticalAcidConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED ) ) + { + isDialysateCondBelowTarget = ( measuredDialysateConductivity >= dialysateLowThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_LOW_DETECTED, isDialysateCondBelowTarget, measuredDialysateConductivity, theoreticalDialysateConductivity ); + + if ( TRUE == isAlarmActive( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED ) ) + { + isDialysateCondAboveTarget = ( measuredDialysateConductivity <= dialysateHighThreshold ? FALSE : TRUE ); + } + checkPersistentAlarm( ALARM_ID_DD_DIALYSATE_CONDUCTIVITY_HIGH_DETECTED, isDialysateCondAboveTarget, measuredDialysateConductivity, theoreticalDialysateConductivity ); + } +} + +/*********************************************************************//** + * @brief * The setModePreGenWetSelfStateTransition function sets the actuators and variables * for the state transition in pre-gen WetSlef test mode. * @details Inputs: Valve states, Pump speed Index: firmware/App/Services/TDInterface.c =================================================================== diff -u -rbd522c8ffdf75130571e5b6a79d1b1d6acd78b1c -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Services/TDInterface.c (.../TDInterface.c) (revision bd522c8ffdf75130571e5b6a79d1b1d6acd78b1c) +++ firmware/App/Services/TDInterface.c (.../TDInterface.c) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -95,6 +95,7 @@ static U32 tdSubMode; ///< Current state (sub-mode) of current TD operation mode. static BOOL tdDialyzerBypass; ///< TD dialyzer bypass static BOOL tdOpModeDataFreshFlag = FALSE; ///< Flag to signal/process fresh TD op mode data +static BOOL tdRxEntered; ///< TRUE when TD has entered treatment Rx (dialysate delivery params) static OVERRIDE_F32_T tdDialysateFlowrate; ///< TD Dialysate flow rate static OVERRIDE_F32_T tdUFRate; ///< TD ultrafiltration rate @@ -123,6 +124,7 @@ tdSubMode = 0U; tdDialyzerBypass = FALSE; tdOpModeDataFreshFlag = FALSE; + tdRxEntered = FALSE; // Initialize treatment parameters from TD tdDialysateFlowrate.data = 0.0F; @@ -320,6 +322,20 @@ /*********************************************************************//** * @brief + * The setTDRxEntered function records whether TD has entered treatment Rx + * parameters (used for PreGen conductivity tolerance bands). + * @details \b Inputs: rxEntered + * @details \b Outputs: tdRxEntered + * @param rxEntered TRUE when treatment Rx has been entered + * @return none + *************************************************************************/ +void setTDRxEntered( BOOL rxEntered ) +{ + tdRxEntered = rxEntered; +} + +/*********************************************************************//** + * @brief * The setTDAcidAndBicarbType function sets the acid and bicarb types to be * used in dialysate generation. * @details \b Inputs: none @@ -400,6 +416,21 @@ return tdDialyzerBypass; } +/*********************************************************************//** + * @brief + * The getTDRxEntered function reports whether TD has entered treatment Rx + * parameters. + * @details \b Inputs: tdRxEntered + * @details \b Outputs: none + * @return TRUE when treatment Rx has been entered + *************************************************************************/ +BOOL getTDRxEntered( void ) +{ + BOOL result = tdRxEntered; + + return result; +} + /****************************************************************************** * @brief * The getTDAcidConversionFactor function gets the latest Acid concentrate @@ -564,6 +595,7 @@ setTDDialyzerBypass( startTxRequest.bypassDialyzer ); tdSubstitutionFlowRate.data = startTxRequest.substitutionRate; setSubstitutionPumpTargetRate( D92_PUMP, getTDSubstitutionFlowRate() ); + setTDRxEntered( TRUE ); // start dialysate generation result = requestDDGenDialStart(); @@ -595,6 +627,7 @@ setTDDialyzerBypass( startTxRequest.bypassDialyzer ); tdSubstitutionFlowRate.data = startTxRequest.substitutionRate; setSubstitutionPumpTargetRate( D92_PUMP, getTDSubstitutionFlowRate() ); + setTDRxEntered( TRUE ); // Signal to update treatement parameters setTreatmentParamUpdate(); Index: firmware/App/Services/TDInterface.h =================================================================== diff -u -rc992ffdef2060d3d534abd2538bfb31dd25b9fbc -re5c384741feb64828c1f4c32ff6daca07b20f46e --- firmware/App/Services/TDInterface.h (.../TDInterface.h) (revision c992ffdef2060d3d534abd2538bfb31dd25b9fbc) +++ firmware/App/Services/TDInterface.h (.../TDInterface.h) (revision e5c384741feb64828c1f4c32ff6daca07b20f46e) @@ -47,11 +47,13 @@ void setTDTargetDialysateTemperature( F32 dialTemperature ); void setTDDialyzerBypass( BOOL dialBypass ); void setTDAcidAndBicarbType( F32 acidConvFactor, F32 bicarbConvFactor, U32 sodium, U32 bicarbonate ); +void setTDRxEntered( BOOL rxEntered ); U32 getTDSubMode( void ); F32 getTDDialysateFlowrate( void ); F32 getTDUFRate( void ); F32 getTDTargetDialysateTemperature( void ); BOOL getTDDialyzerBypass( void ); +BOOL getTDRxEntered( void ); F32 getTDAcidConversionFactor( void ); F32 getTDBicarbConversionFactor( void ); U32 getTDSodiumConcentration( void );