Fisheye: Tag 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f refers to a dead (removed) revision in file `firmware/App/Modes/BloodPrime.c'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f refers to a dead (removed) revision in file `firmware/App/Modes/BloodPrime.h'. Fisheye: No comparison available. Pass `N' to diff? Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rb824ef4b479578c5aa702abd9147aef505a6fb04 -r2fe1bfe77e53e5b92dae1b89c726c59b7b95939f --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision b824ef4b479578c5aa702abd9147aef505a6fb04) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f) @@ -183,7 +183,7 @@ // Initialize treatment mode each time we transition to it initTreatmentMode(); // Initialize treatment sub-modes each time we transition to treatment mode -// initBloodPrime(); + initBloodPrime(); initDialysis(); initTreatmentPaused(); // initRinseback(); @@ -316,6 +316,35 @@ /*********************************************************************//** * @brief + * The setBloodIsPrimed function sets that flag indicating whether the + * blood-side circuit has been primed with blood. Call this function with + * TRUE when blood prime operation is completed. Call this function with + * FALSE at start of treatment or start of rinseback operation. + * @details Inputs: none + * @details Outputs: bloodIsPrimed + * @param flag TRUE if blood side circuit is primed with blood, FALSE if not + * @return none + *************************************************************************/ +void setBloodIsPrimed( BOOL flag ) +{ + bloodIsPrimed = flag; +} + +/*********************************************************************//** + * @brief + * The getBloodIsPrimed function determines whether the blood-side circuit + * has been primed with blood (indicating blood-side circuit should be primarily blood). + * @details Inputs: bloodIsPrimed + * @details Outputs: none + * @return bloodIsPrimed + *************************************************************************/ +BOOL getBloodIsPrimed( void ) +{ + return bloodIsPrimed; +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToTreatmentMode function executes the given alarm action * as appropriate while in Treatment Mode. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if invalid alarm action given. @@ -329,7 +358,7 @@ switch( action ) { case ALARM_ACTION_STOP: - // Stop signal actively polled by mode/sub-mode/state + // signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: @@ -369,9 +398,22 @@ /*********************************************************************//** * @brief + * The signalBloodPrimeToDialysis function signals that blood prime has + * completed and it is time to move on to dialysis. + * @details Inputs: none + * @details Outputs: bloodPrimeToDialysisRequest + * @return none + *************************************************************************/ +void signalBloodPrimeToDialysis( void ) +{ + bloodPrimeToDialysisRequest = TRUE; +} + +/*********************************************************************//** + * @brief * The execTreatmentMode function executes the Treatment Mode state machine. - * @details \b Alarm: ALARM_ID_TD_TREATMENT_STOPPED_BY_USER if user presses - * the stop button + * @details \b Alarm: ALARM_ID_TD_TREATMENT_PED_BY_USER if user presses + * the button * @details \b Inputs: currentTreatmentState * @details \b Outputs: currentTreatmentState, resumeBlockedByAlarm * @return current state (sub-mode) @@ -380,7 +422,7 @@ { BOOL stop = isStopButtonPressed(); - // Trigger user stop alarm at any time in treatment mode when user presses stop button + // Trigger user alarm at any time in treatment mode when user presses button if ( TRUE == stop ) { activateAlarmNoData( ALARM_ID_TD_TREATMENT_STOPPED_BY_USER ); @@ -480,7 +522,7 @@ TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; lastTreatmentTimeStamp = getMSTimerCount(); - //transitionToBloodPrime(); // TODO + transitionToBloodPrime(); setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); // TODO - remove later return result; @@ -500,19 +542,19 @@ // setRinsebackIsCompleted( FALSE ); -// // Handle alarm stoppage -// if ( TRUE == doesAlarmStatusIndicateStop() ) -// { -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; -// } -// else -// { -// execBloodPrime(); -// -// // Handle signals from blood prime sub-mode -// if ( TRUE == bloodPrimeToDialysisRequest ) -// { + // Handle alarm page + if ( TRUE == doesAlarmStatusIndicate() ) + { + transitionToTreatmentPaused(); + result = TREATMENT_PAUSED_STATE; + } + else + { + execBloodPrime(); + + // Handle signals from blood prime sub-mode + if ( TRUE == bloodPrimeToDialysisRequest ) + { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); @@ -567,8 +609,8 @@ else { execDialysis(); - // Handle alarm stoppage - if ( TRUE == doesAlarmStatusIndicateStop() ) + // Handle alarm page + if ( TRUE == doesAlarmStatusIndicate() ) { transitionToTreatmentPaused(); result = TREATMENT_PAUSED_STATE; @@ -596,18 +638,18 @@ { resumeTreatmentAlarmResponseRequest = FALSE; -// if ( TRUE == getBloodIsPrimed() ) + if ( TRUE == getBloodIsPrimed() ) { lastTreatmentTimeStamp = getMSTimerCount(); transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } -// else -// { -// transitionToBloodPrime(); -// result = TREATMENT_BLOOD_PRIME_STATE; -// } -// signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + else + { + transitionToBloodPrime(); + result = TREATMENT_BLOOD_PRIME_STATE; + } + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } // If user requests rinseback, go to rinseback // else if ( TRUE == initiateRinsebackAlarmResponseRequest ) @@ -631,7 +673,7 @@ // If leaving treatment paused state, zero alarm countdown timer for UI // if ( TRUE == leavingTreatmentPausedState ) // { -// TREATMENT_STOP_PAYLOAD_T data; +// TREATMENT_PAUSED_PAYLOAD_T data; // // data.timeout = 0; // data.countdown = 0; @@ -646,7 +688,7 @@ * The handleTreatmentRinsebackState function executes the rinseback state of the * Treatment Mode state machine. * @details \b Inputs: endTreatmentAlarmResponseRequest, resumeTreatmentAlarmResponseRequest, - * rinsebackToRecircRequest, rinsebackToStoppedRequest, endTreatmentRequest + * rinsebackToRecircRequest, rinsebackTopedRequest, endTreatmentRequest * @details \b Outputs: treatment rinseback sub-mode executed, sendLastTreatmentPeriodicData * @return next treatment mode state *************************************************************************/ @@ -679,10 +721,10 @@ // transitionToTreatmentRecirc(); // result = TREATMENT_RECIRC_STATE; // } -// else if ( TRUE == rinsebackToStoppedRequest ) +// else if ( TRUE == rinsebackTopedRequest ) // { -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; +// transitionToTreatment(); +// result = TREATMENT_PAUSED_STATE; // } // else if ( TRUE == endTreatmentRequest ) // { @@ -696,7 +738,7 @@ * @brief * The handleTreatmentRecircState function executes the re-circulate state of the * Treatment Mode state machine. - * @details \b Inputs: endTreatmentAlarmResponseRequest, rinsebackToStoppedRequest, + * @details \b Inputs: endTreatmentAlarmResponseRequest, rinsebackTopedRequest, * endTreatmentRequest * @details \b Outputs: sendLastTreatmentPeriodicData * @return next treatment mode state @@ -718,11 +760,11 @@ // } // // // Handle signals from treatment re-circ sub-mode -// if ( TRUE == rinsebackToStoppedRequest ) +// if ( TRUE == rinsebackTopedRequest ) // { -// stopDialysis(); -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; +// Dialysis(); +// transitionToTreatment(); +// result = TREATMENT__STATE; // } // else if ( TRUE == endTreatmentRequest ) // { @@ -829,10 +871,10 @@ treatmentStateBroadcastTimerCtr = 0; payload.treatmentSubMode = (U32)currentTreatmentState; - payload.bldPrimeState = 0; // getCurrentBloodPrimeState(); + payload.bldPrimeState = getCurrentBloodPrimeState(); payload.dialysisState = getDialysisState(); payload.isoUFState = 0; - payload.txStopState = getCurrentTreatmentPausedState(); + payload.txPausedState = getCurrentTreatmentPausedState(); payload.rinsebackState = 0; // getCurrentRinsebackState(); payload.txRecircState = 0; // getCurrentTreatmentRecircState(); payload.txEndState = 0; // getCurrentTreatmentEndState(); @@ -1000,7 +1042,7 @@ *************************************************************************/ static void resetSignalFlags( void ) { -// rinsebackToStoppedRequest = FALSE; +// rinsebackTopedRequest = FALSE; endTreatmentRequest = FALSE; // rinsebackToRecircRequest = FALSE; bloodPrimeToDialysisRequest = FALSE; Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -rb824ef4b479578c5aa702abd9147aef505a6fb04 -r2fe1bfe77e53e5b92dae1b89c726c59b7b95939f --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision b824ef4b479578c5aa702abd9147aef505a6fb04) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f) @@ -51,7 +51,7 @@ U32 bldPrimeState; ///< Blood prime state. U32 dialysisState; ///< Dialysis state. U32 isoUFState; ///< Isolated ultrafiltration state. - U32 txStopState; ///< Treatment stop state. + U32 txPausedState; ///< Treatment paused state. U32 rinsebackState; ///< Rinse back state. U32 txRecircState; ///< Treatment recirc state. U32 txEndState; ///< Treatment end state. @@ -100,6 +100,7 @@ void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for treatment mode void signalEndTreatment( void ); // Requesting transition to post-treatment mode +void signalBloodPrimeToDialysis( void ); // Blood prime sub-mode is signaling to move on to dialysis sub-mode void broadcastTreatmentTimeAndState( void ); // Broadcast the times and states of this treatment @@ -108,6 +109,8 @@ BOOL isTreatmentResumeBlocked( void ); // Determine whether the treatment is not allowed to be resumed. U32 getTreatmentTimeRemainingSecs( void ); // Determine number of seconds remaining in the treatment U32 getActualTreatmentTimeSecs( void ); // Determine the actual treatment duration in seconds +void setBloodIsPrimed( BOOL flag ); // Set whether the blood-side circuit of the dialyzer has been primed with blood (F causes Tx start/resume to do blood prime first) +BOOL getBloodIsPrimed( void ); // Determine whether the blood-side circuit of the dialyzer has been primed with blood U32 getTreatmentStartTimeStamp( void ); // Get the treatment start time stamp U32 getTreatmentEndTimeStamp( void ); // Get the treatment end time stamp Index: firmware/App/Modes/StateTxBloodPrime.c =================================================================== diff -u --- firmware/App/Modes/StateTxBloodPrime.c (revision 0) +++ firmware/App/Modes/StateTxBloodPrime.c (revision 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f) @@ -0,0 +1,364 @@ +/************************************************************************** +* +* Copyright (c) 2021-2025 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 BloodPrime.c +* +* @author (last) Varshini Nagabooshanam +* @date (last) 26-Dec-2025 +* +* @author (original) Varshini Nagabooshanam +* @date (original) 22-Dec-2025 +* +***************************************************************************/ + +#include +#include "AirTrap.h" +#include "BloodFlow.h" +#include "ModeTreatment.h" +#include "ModeTxParams.h" +#include "OperationModes.h" +#include "TaskGeneral.h" +#include "Utilities.h" +#include "Valves.h" + +/** + * @addtogroup StateTxBloodPrime + * @{ + */ + +// ********** private definitiions *********** + +///< Minimum ramp time for blood prime (in seconds) +#define MIN_RAMP_TIME_SEC 60 + +/// Initial flow rate for blood pump when starting blood prime operation. +#define BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN 250 + +/// Interval at which blood prime ramping is controlled. +static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + +/// Interval at which blood prime progress is to be published to UI. +#define BLOOD_PRIME_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +/// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. +static const F32 BLOOD_PRIME_FLOW_INTEGRATOR = 1.0F / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + +// ********** private data ********** + +static BLOOD_PRIME_STATE_T bloodPrimeState; ///< Current state of the blood prime sub-mode. + +static F32 bloodPrimeRampFlowRate_mL_min; ///< Current blood pump ramp flow rate. +static F32 bloodPrimeRampStep_mL; ///< Blood pump volume step size for ramping. +static F32 bloodPrimeTargetVolume_mL; ///< Calculated target blood prime volume (based on selected dialyzer and fixed tubing volume). + +static U32 bloodPrimeRampControlTimerCtr; ///< Timer counter for determining interval for controlling BP ramp. +static U32 bloodPrimePublishTimerCtr; ///< Timer counter for determining interval for blood prime status to be published. + +/// Interval (in task intervals) at which to publish blood prime data to CAN bus. +static OVERRIDE_U32_T bloodPrimePublishInterval = { BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, 0 }; + +static OVERRIDE_F32_T cumulativeBloodPrimeVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative blood prime volume (in mL) from measured blood flow rate. + +// ********** private function prototypes ********** + +static void resetBloodPrimeFlags( void ); +static F32 getBloodPrimeVolume( void ); +static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ); +static void publishBloodPrimeData( void ); + +/*********************************************************************//** + * @brief + * The initBloodPrime function initializes the Blood Prime sub-mode + * module. Calling this function will reset blood prime and therefore should + * only be called when a new blood prime is due to begin. + * @details Inputs: none + * @details Outputs: Blood prime sub-mode module initialized. + * @return none + *************************************************************************/ +void initBloodPrime( void ) +{ + S32 setBPRate = (S32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); + F32 rampRateSpan = 0.0F; + F32 estRampSeconds = 0.0F; + + bloodPrimeState = BLOOD_PRIME_RAMP_STATE; + bloodPrimeRampControlTimerCtr = 0; + bloodPrimePublishTimerCtr = BLOOD_PRIME_DATA_PUBLISH_INTERVAL - 2; // setup so publish will occur time after next + cumulativeBloodPrimeVolume_mL.data = 0.0; + resetBloodPrimeFlags(); + + bloodPrimeTargetVolume_mL = (F32)getTreatmentParameterU32( TUBING_BLOOD_PRIME_VOLUME_ML ) + getDialyzerBloodVolume( getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ); + bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; + + // Calculate BP ramp step size + rampRateSpan = (F32)( setBPRate - BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ); + estRampSeconds = ( ( bloodPrimeTargetVolume_mL / (F32)setBPRate + bloodPrimeTargetVolume_mL / (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN ) / 2.0 ) * (F32)SEC_PER_MIN; + + if ( estRampSeconds < (F32)MIN_RAMP_TIME_SEC ) + { + estRampSeconds = (F32)MIN_RAMP_TIME_SEC; + } + bloodPrimeRampStep_mL = rampRateSpan / estRampSeconds; +} + +/*********************************************************************//** + * @brief + * The transitionToBloodPrime function prepares for transition to blood prime + * sub-mode. This function will reset only what is required for resuming a + * blood prime that was paused (alarm) so if a blood prime is being restarted, + * call the initialize function first to reset everything. + * @details Inputs: none + * @details Outputs: actuators set for initial state of blood prime sub-mode + * @return none + *************************************************************************/ +void transitionToBloodPrime( void ) +{ + doorClosedRequired( TRUE, TRUE ); + + // Set valves + setValvePosition( H1_VALV, VALVE_POSITION_B_OPEN ); // set arterial valve to pump blood from patient + setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); // set venous valve to open, allowing blood to return to patient + + // Start air trap control + startAirTrapControl(); + + // Set valves + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + + + // Ensure dialysate outlet and Heparin pumps are stopped + //signalDialOutPumpHardStop(); + //stopSyringePump(); + + // start blood and dialysate inlet pumps + setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setCurrentSubState( (U32)bloodPrimeState ); + + + // Set user alarm recovery actions allowed in this sub-mode + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); +} + +/*********************************************************************//** + * @brief + * The resetBloodPrimeFlags function resets the blood prime request flags. + * @details Inputs: none + * @details Outputs: Blood prime request flags reset to FALSE. + * @return none + *************************************************************************/ +static void resetBloodPrimeFlags( void ) +{ + // No flags for now +} + +/*********************************************************************//** + * @brief + * The getBloodPrimeVolume function gets the calculated blood prime volume + * delivered. + * @details Inputs: cumulativeBloodPrimeVolume_mL + * @details Outputs: none + * @return the current blood prime volume delivered (in mL). + *************************************************************************/ +static F32 getBloodPrimeVolume( void ) +{ + F32 result = cumulativeBloodPrimeVolume_mL.data; + + if ( OVERRIDE_KEY == cumulativeBloodPrimeVolume_mL.override ) + { + result = cumulativeBloodPrimeVolume_mL.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The execBloodPrime function executes the Blood Prime sub-mode state machine. + * @details Inputs: bloodPrimeState + * @details Outputs: bloodPrimeState + * @return none + *************************************************************************/ +void execBloodPrime( void ) +{ + switch ( bloodPrimeState ) + { + case BLOOD_PRIME_RAMP_STATE: + bloodPrimeState = handleBloodPrimeRampState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_PRIME_INVALID_STATE, bloodPrimeState ); + break; + } + + // Blood prime flags should be handled by now - reset in case not handled by current state + resetBloodPrimeFlags(); + + // Publish blood prime progress while in blood prime sub-mode + publishBloodPrimeData(); +} + +/*********************************************************************//** + * @brief + * The handleBloodPrimeRampState function handles the blood prime ramp + * state operations. + * @details Inputs: flags + * @details Outputs: flags handled + * @return next blood prime state + *************************************************************************/ +static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ) +{ + BLOOD_PRIME_STATE_T result = BLOOD_PRIME_RAMP_STATE; + + // Update blood prime volume delivered so far + cumulativeBloodPrimeVolume_mL.data += ( getMeasuredBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_SKIP_BLOOD_PRIME ) ) + { + // If the skip blood prime is enabled, set the cumulative volume to the target blood prime volume + cumulativeBloodPrimeVolume_mL.data = bloodPrimeTargetVolume_mL; + } + + // Has blood prime completed? + if ( getBloodPrimeVolume() >= bloodPrimeTargetVolume_mL ) + { + initBloodPrime(); // Reset blood prime so that we start anew next time we transition to this sub-mode + setBloodIsPrimed( TRUE ); // Signal treatment mode that blood prime is completed + signalBloodPrimeToDialysis(); // Signal treatment mode that it's time to start dialysis + } + else + { + // ramp blood pump on ramp interval + if ( ++bloodPrimeRampControlTimerCtr >= BLOOD_PRIME_RAMPING_INTERVAL ) + { + U32 setBPRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); + + bloodPrimeRampControlTimerCtr = 0; + bloodPrimeRampFlowRate_mL_min += bloodPrimeRampStep_mL; + setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getCurrentBloodPrimeState function returns the current state of the + * blood prime sub-mode. + * @details Inputs: bloodPrimeState + * @details Outputs: none + * @return bloodPrimeState + *************************************************************************/ +BLOOD_PRIME_STATE_T getCurrentBloodPrimeState( void ) +{ + return bloodPrimeState; +} + +/*********************************************************************//** + * @brief + * The publishBloodPrimeData function publishes blood prime progress to UI + * at 1 Hz interval. + * @details Inputs: bloodPrimePublishTimerCtr + * @details Outputs: rinseback data published + * @return none + *************************************************************************/ +static void publishBloodPrimeData( void ) +{ + if ( ++bloodPrimePublishTimerCtr >= getU32OverrideValue( &bloodPrimePublishInterval ) ) + { + BLOOD_PRIME_DATA_PAYLOAD_T data; + + bloodPrimePublishTimerCtr = 0; + data.targetBloodPrimeVolumeMl = bloodPrimeTargetVolume_mL; + data.deliveredBloodPrimeVolumeMl = MAX( 0.0, getBloodPrimeVolume() ); + broadcastData( MSG_ID_TD_BLOOD_PRIME_PROGRESS_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetBloodPrimeVolumeOverride function sets or resets the override + * of calculated blood prime volume. + * @details Inputs: none + * @details Outputs: cumulativeBloodPrimeVolume_mL + * @param message Override message from Dialin + * @return TRUE if override request is successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodPrimeVolumeOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + BOOL enable = FALSE; + F32 volume = 0.0F; + + if ( ( TRUE == isTestingActivated() ) && ( ( sizeof( BOOL ) + sizeof( F32 ) ) == message->hdr.payloadLen ) ) + { + result = TRUE; + memcpy( &enable, message->payload, sizeof( BOOL ) ); + memcpy( &volume, &message->payload[ sizeof( BOOL ) ], sizeof( F32 ) ); + + if ( TRUE == enable ) + { + cumulativeBloodPrimeVolume_mL.ovData = volume; + cumulativeBloodPrimeVolume_mL.override = OVERRIDE_KEY; + } + else + { + cumulativeBloodPrimeVolume_mL.override = OVERRIDE_RESET; + cumulativeBloodPrimeVolume_mL.ovData = cumulativeBloodPrimeVolume_mL.ovInitData; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetBloodPrimePublishIntervalOverride function sets or resets the + * override of blood prime data publish interval. + * @details Inputs: none + * @details Outputs: bloodPrimePublishInterval + * @param message Override message from Dialin + * @return TRUE if override request is successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodPrimePublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + BOOL enable = FALSE; + U32 intervalMs = 0U; + + if ( ( TRUE == isTestingActivated() ) && ( ( sizeof( BOOL ) + sizeof( U32 ) ) == message->hdr.payloadLen ) ) + { + result = TRUE; + memcpy( &enable, message->payload, sizeof( BOOL ) ); + memcpy( &intervalMs, &message->payload[ sizeof( BOOL ) ], sizeof( U32 ) ); + + if ( TRUE == enable ) + { + bloodPrimePublishInterval.ovData = intervalMs / TASK_GENERAL_INTERVAL; + bloodPrimePublishInterval.override = OVERRIDE_KEY; + } + else + { + bloodPrimePublishInterval.override = OVERRIDE_RESET; + bloodPrimePublishInterval.ovData = bloodPrimePublishInterval.ovInitData; + } + } + + return result; +} + +/**@}*/ Index: firmware/App/Modes/StateTxBloodPrime.h =================================================================== diff -u --- firmware/App/Modes/StateTxBloodPrime.h (revision 0) +++ firmware/App/Modes/StateTxBloodPrime.h (revision 2fe1bfe77e53e5b92dae1b89c726c59b7b95939f) @@ -0,0 +1,61 @@ +/************************************************************************** +* +* Copyright (c) 2021-2025 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 BloodPrime.h +* +* @author (last) Varshini Nagabooshanam +* @date (last) 26-Dec-2025 +* +* @author (original) Varshini Nagabooshanam +* @date (original) 22-Dec-2025 +* +***************************************************************************/ + +#ifndef __BLOOD_PRIME_H__ +#define __BLOOD_PRIME_H__ + +#include "TDCommon.h" +#include "TDDefs.h" + +/** + * @defgroup BloodPrime BloodPrime + * @brief Blood prime sub-mode of treatment mode. + * The blood prime state is where we go when treatment is first started or + * when returning to treatment after a rinseback. + * In this state, there is no Heparin delivery nor ultrafiltration. + * In this state, treatment timer is not running. No dialysis. Dialyzer is bypassed. + * In this state, blood pump is slowly ramped to set rate until the prime volume is delivered. + * + * @addtogroup StateTxBloodPrime + * @{ + */ + +// ********** public definitions ****************** + +#define TUBING_BLOOD_PRIME_VOLUME_ML 106.6F ///< Tubing portion of blood prime volume to prime the blood side circuit (in mL). + +/// Payload record structure for a blood prime data broadcast message. +typedef struct +{ + F32 targetBloodPrimeVolumeMl; ///< Target blood prime volume in mL. + F32 deliveredBloodPrimeVolumeMl; ///< Delivered blood prime volume in mL. +} BLOOD_PRIME_DATA_PAYLOAD_T; + +// ********** public function prototypes ********** + +void initBloodPrime( void ); // Initialize this unit +void transitionToBloodPrime( void ); // Prepares for transition to treatment blood prime sub-mode +void execBloodPrime( void ); // Execute the blood prime sub-mode state machine + +BLOOD_PRIME_STATE_T getCurrentBloodPrimeState( void ); // Get the current treatment sub-mode state + +BOOL testSetBloodPrimeVolumeOverride( MESSAGE_T *message ); +BOOL testSetBloodPrimePublishIntervalOverride( MESSAGE_T *message ); + +/**@}*/ + +#endif