Index: firmware/App/Controllers/AirPump.c =================================================================== diff -u -r1b83a4555c4040a45cecfbea45b6570812ab281e -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Controllers/AirPump.c (.../AirPump.c) (revision 1b83a4555c4040a45cecfbea45b6570812ab281e) +++ firmware/App/Controllers/AirPump.c (.../AirPump.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file AirPump.c * * @author (last) Varshini Nagabooshanam -* @date (last) 18-Jun-2026 +* @date (last) 02-Jul-2026 * * @author (original) Sean Nash * @date (original) 19-Sep-2024 @@ -35,6 +35,8 @@ #define AIR_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Air pump data publish interval. #define DATA_PUBLISH_COUNTER_START_COUNT 13 ///< Air pump data publish start counter. #define AIR_PUMP_STALL_PERSISTENCE ( 150 / TASK_GENERAL_INTERVAL ) ///< Stall duration before alarm (150 ms) +#define AIR_PUMP_STALL_START_DELAY_MS 200 ///< Delay before evaluating stall condition +#define AIR_PUMP_STALL_START_DELAY_COUNT ( AIR_PUMP_STALL_START_DELAY_MS / TASK_GENERAL_INTERVAL ) ///< Air pump stall delay count interval #pragma pack(push, 1) /// Payload record structure for air pump test set command message payload. @@ -49,6 +51,7 @@ static AIR_PUMP_STATE_T currentAirPumpState; ///< Current air pump control state. static U08 airPumpStallCounter; ///< Air pump stall counter +static U08 airPumpStartDelayCounter; ///< Delay before evaluating air pump stall condition static U16 currentAirPumpRPM; ///< Current air pump RPM static F32 currentAirPumpPowerLevel; ///< Current air pump power level setting in % duty cycle (0..100%). static U32 airPumpDataPublicationTimerCounter; ///< Air pump data broadcast timer counter. @@ -80,6 +83,7 @@ currentAirPumpPowerLevel = AIR_PUMP_MOTOR_OFF; currentAirPumpRPM = 0; airPumpStallCounter = 0; + airPumpStartDelayCounter = 0; airPumpDataPublishInterval.data = AIR_PUMP_DATA_PUB_INTERVAL; airPumpDataPublishInterval.ovData = AIR_PUMP_DATA_PUB_INTERVAL; airPumpDataPublishInterval.ovInitData = AIR_PUMP_DATA_PUB_INTERVAL; @@ -243,22 +247,36 @@ *************************************************************************/ static void checkAirPumpStallCondition( void ) { - if ( ( currentAirPumpPowerLevel > 0 ) && ( currentAirPumpRPM == 0 ) ) - { - // we are commanding air pump to run but zero measured pump speed indicates it is not running - if ( ++airPumpStallCounter >= AIR_PUMP_STALL_PERSISTENCE ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_AIR_PUMP_STALL, currentAirPumpPowerLevel, currentAirPumpRPM ); - // Stop H12 air pump - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - // Stop air trap control - endAirTrapControl(); - } - } - else - { - airPumpStallCounter = 0; - } + if ( ( AIR_PUMP_STATE_ON == currentAirPumpState ) && ( currentAirPumpPowerLevel > 0 ) ) + { + // Allow RPM time to populate before evaluating stall condition + if ( airPumpStartDelayCounter < AIR_PUMP_STALL_START_DELAY_COUNT ) + { + airPumpStartDelayCounter++; + airPumpStallCounter = 0; + } + else if ( 0 == currentAirPumpRPM ) + { + // Air pump commanded on but RPM remains zero + if ( ++airPumpStallCounter >= AIR_PUMP_STALL_PERSISTENCE ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_AIR_PUMP_STALL, currentAirPumpPowerLevel, currentAirPumpRPM ); + // Stop H12 air pump + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + } + } + else + { + // RPM detected, clear stall counter + airPumpStallCounter = 0; + } + } + else + { + // Pump is off, reset counters + airPumpStartDelayCounter = 0; + airPumpStallCounter = 0; + } } /*********************************************************************//** Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file Valves.c * -* @author (last) Dara Navaei -* @date (last) 19-Dec-2025 +* @author (last) Sean Nash +* @date (last) 04-May-2026 * * @author (original) Sean Nash * @date (original) 24-Oct-2024 @@ -47,21 +47,6 @@ #define POS_C_FROM_ZERO_CNT VALVE_OFFEST_FROM_EDG_CNT ///< Position C from zero position in counts. #define POS_D_PARTIAL_CLOSE_FROM_ZERO_CNT ( POS_C_FROM_ZERO_CNT + 32 ) ///< Position D partial close from zero position in counts. -/// Valve controller states -typedef enum Valve_Control_States -{ - VALVE_STATE_WAIT_FOR_POST = 0, ///< Valve state wait for POST. - VALVE_STATE_RESET_VALVE, ///< Valve state reset valve. - VALVE_STATE_RESET_ENCODER, ///< Valve state reset encoder. - VALVE_STATE_ENABLE_VALVE, ///< Valve state enable valve. - VALVE_STATE_HOMING_NOT_STARTED, ///< Valve state homing not started. - VALVE_STATE_HOMING_FIND_ENERGIZED_EDGE, ///< Valve state homing find energized edge. - VALVE_STATE_HOMING_FIND_DEENERGIZED_EDGE, ///< Valve state homing find de-energized edge. - VALVE_STATE_IDLE, ///< Valve state idle. - VALVE_STATE_IN_TRANSITION, ///< Valve state in transition. - NUM_OF_VALVE_STATES, ///< Number of valve exec states. -} VALVE_STATE_T; - /// Valve status structure typedef struct { @@ -252,6 +237,31 @@ /*********************************************************************//** * @brief + * The getValveState function returns the current state of a given valve. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given valve is invalid. + * @details \b Inputs: currentValveStates[] + * @details \b Outputs: none + * @param valve ID of valve to get current state of + * @return Current state of the given valve + *************************************************************************/ +VALVE_STATE_T getValveState( VALVE_T valve ) +{ + VALVE_STATE_T result = VALVE_STATE_HOMING_NOT_STARTED; + + if ( valve < NUM_OF_VALVES ) + { + result = currentValveStates[ valve ].controlState; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_VALVES_INVALID_VALVE2, (U32)valve ) + } + + return result; +} + +/*********************************************************************//** + * @brief * The execValvesController function executes the valves state machine. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if a valve control state is invalid. * @details \b Inputs: currentValveStates[] Index: firmware/App/Controllers/Valves.h =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Controllers/Valves.h (.../Valves.h) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Controllers/Valves.h (.../Valves.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file Valves.h * -* @author (last) Varshini Nagabooshanam -* @date (last) 19-Jan-2026 +* @author (last) Sean Nash +* @date (last) 04-May-2026 * * @author (original) Sean Nash * @date (original) 24-Oct-2024 @@ -61,6 +61,21 @@ } TD_VALVE_DATA_T; #pragma pack(pop) +/// Valve controller states +typedef enum Valve_Control_States +{ + VALVE_STATE_WAIT_FOR_POST = 0, ///< Valve state wait for POST. + VALVE_STATE_RESET_VALVE, ///< Valve state reset valve. + VALVE_STATE_RESET_ENCODER, ///< Valve state reset encoder. + VALVE_STATE_ENABLE_VALVE, ///< Valve state enable valve. + VALVE_STATE_HOMING_NOT_STARTED, ///< Valve state homing not started. + VALVE_STATE_HOMING_FIND_ENERGIZED_EDGE, ///< Valve state homing find energized edge. + VALVE_STATE_HOMING_FIND_DEENERGIZED_EDGE, ///< Valve state homing find de-energized edge. + VALVE_STATE_IDLE, ///< Valve state idle. + VALVE_STATE_IN_TRANSITION, ///< Valve state in transition. + NUM_OF_VALVE_STATES, ///< Number of valve exec states. +} VALVE_STATE_T; + // ********** public function prototypes ********** void initValves(void); @@ -70,6 +85,7 @@ BOOL homeValve( VALVE_T valve, BOOL force, BOOL cartridge ); BOOL setValvePosition( VALVE_T valve, VALVE_POSITION_T position ); VALVE_POSITION_T getValvePosition( VALVE_T valve ); +VALVE_STATE_T getValveState( VALVE_T valve ); BOOL testValvesDataPublishIntervalOverride( MESSAGE_T *message ); BOOL testValveSetABCCmdPosition( MESSAGE_T *message ); Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r6bb89ac52fecee7db9dc69a3eb727cad0a66370e -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 6bb89ac52fecee7db9dc69a3eb727cad0a66370e) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -130,7 +130,8 @@ break; case TD_PRE_TREATMENT_TUBING_SET_INSTALL_STATE: - currentPreTreatmentState = handleInstallState(); + currentPreTreatmentState = TD_PRE_TREATMENT_HEPARIN_SETUP_STATE; + setCurrentSubState((U32)currentPreTreatmentState); break; case TD_PRE_TREATMENT_SELF_TEST_DRY_STATE: @@ -352,7 +353,7 @@ BOOL paramsValid = getValidTreatParamsReceived(); BOOL paramsConfirmed = getTreatParamsConfirmed(); BOOL heparinIsPrescribed = ( ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ) > 0.0F ) || - ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DELIVERY_RATE ) > 0.0F ) ); + ( getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DELIVERY_RATE ) > 0.0F ) ) ? TRUE : FALSE; BOOL isDialysateGoodToDeliver = TRUE; // TODO replace TRUE with getDialysateGoodToDeliverStatus() when we are ready F32 bicarbConvFactor = BICARBONATE_CONVERSION_FACTOR; F32 presUFVolumeL = 0.0F; Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r120487ddf3e3d69d1de5094d5252c037588e2ed8 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 120487ddf3e3d69d1de5094d5252c037588e2ed8) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file ModeStandby.c * -* @author (last) Arpita Srivastava -* @date (last) 18-May-2026 +* @author (last) Praneeth Bunne +* @date (last) 02-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -27,6 +27,8 @@ #include "Switches.h" #include "SystemCommTD.h" #include "TxParams.h" +#include "Valve3Way.h" +#include "Valves.h" /** * @addtogroup TDStandbyMode @@ -42,6 +44,9 @@ static TD_STANDBY_STATE_T currentStandbyState; ///< Current state (sub-mode) of standby mode. static BOOL treatStartReqReceived; ///< Flag indicates user has requested initiation of a treatment. +static BOOL homingInitiated; ///< Flag indicates actuators have been homed. +static FLUID_TYPE_T fluidType; ///< Fluid type assigned based on user selection. +static TREATMENT_TYPE_T modality; ///< Modality from the treatment initiation. // ********** private function prototypes ********** @@ -52,13 +57,16 @@ * @brief * The initStandbyMode function initializes the Standby Mode Unit. * @details \b Inputs: none - * @details \b Outputs: currentStandbyState, treatStartReqReceived + * @details \b Outputs: Standby mode variables initialized. * @return none *************************************************************************/ void initStandbyMode( void ) { currentStandbyState = STANDBY_START_STATE; treatStartReqReceived = FALSE; + homingInitiated = FALSE; + fluidType = FLUID_TYPE_UNKNOWN; + modality = TREATMENT_MODALITY_HD_SALINE_FLUID; } /*********************************************************************//** @@ -84,15 +92,22 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); // Pumps should be off -// signalBloodPumpHardStop(); + signalBloodPumpHardStop(); // stopSyringePump(); // Set valves to default positions -// setValveAirTrap( VALVE_3WAY_COMMON_TO_CLOSED_STATE ); -// setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); -// setValvePosition( H19, VALVE_POSITION_A_INSERT_EJECT ); + set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + if ( getValveState( H1_VALV ) < VALVE_STATE_IDLE ) + { + setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); + } + if ( getValveState( H19_VALV ) < VALVE_STATE_IDLE ) + { + setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); + } -// doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode + doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode // Request DD service record and usage information from DD // sendDGServiceRequestToDG(); @@ -153,23 +168,23 @@ // Wait for door to be closed so we can home actuators // if ( STATE_CLOSED == getSwitchState( H9_SWCH ) ) // { -// // If we haven't already initiated homing of actuators, initiate now -// if ( homingInitiated != TRUE ) -// { -// VALVE_T valve; -// -// // Home pumps and valves -// for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) -// { -// homeValve( valve, VALVE_NO_FORCE_HOME, VALVE_CARTRIDGE_MAY_BE_PRESENT ); -// } + // If we haven't already initiated homing of actuators, initiate now + if ( homingInitiated != TRUE ) + { + VALVE_T valve; + + // Home pumps and valves + for ( valve = FIRST_VALVE; valve < NUM_OF_VALVES; ++valve ) + { + homeValve( valve, FALSE, TRUE ); + } // homeBloodPump(); // homeDialInPump(); // homeDialOutPump(); // retractSyringePump(); -// -// homingInitiated = TRUE; -// } + + homingInitiated = TRUE; + } // else // { // // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration @@ -269,17 +284,67 @@ // Start treatment workflow with pretreatment mode requestNewOperationMode( MODE_PRET ); treatStartReqReceived = FALSE; + // Set fluid type + setFluidType( modality ); } return state; } /*********************************************************************//** * @brief + * The setFluidType function sets the fluid type based on the user's + * treatment selection from the home screen. + * @details \b Inputs: none + * @details \b Outputs: fluidType + * @param modality Treatment modality selected by the user on the home screen. + * @return none + *************************************************************************/ +void setFluidType( TREATMENT_TYPE_T modality ) +{ + if ( TREATMENT_MODALITY_HD_SALINE_FLUID == modality ) + { + fluidType = FLUID_TYPE_SALINE; + } + else + { + // For HDF and HD_ONLINE_FLUID + fluidType = FLUID_TYPE_SUBSTITUTE; + } +} + +/*********************************************************************//** + * @brief + * The getFluidType function returns the current fluid type assigned + * based on the user's treatment selection. + * @details \b Inputs: none + * @details \b Outputs: none + * @return Current fluid type (saline or substitution fluid). + *************************************************************************/ +FLUID_TYPE_T getFluidType( void ) +{ + return fluidType; +} + +/*********************************************************************//** + * @brief + * The getModality function returns the treatment modality received from + * the UI at treatment initiation. + * @details \b Inputs: modality + * @details \b Outputs: none + * @return Treatment modality selected by the user on the home screen. + *************************************************************************/ +TREATMENT_TYPE_T getModality( void ) +{ + return modality; +} + +/*********************************************************************//** + * @brief * The signalUserInitiateTreatment function handles user initiation of a * treatment. * @details \b Inputs: none - * @details \b Outputs: treatStartReqReceived + * @details \b Outputs: treatStartReqReceived, modality * @param message initiate/reject treatment workflow message from UI which * includes the command code (0=cancel, 1=initiate). * @return TRUE if signal accepted, FALSE if not @@ -290,20 +355,27 @@ U32 cmd = 0; TD_OP_MODE_T mode = getCurrentOperationMode(); REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + INITIATE_TREATMENT_REQUEST_PAYLOAD_T request; UI_RESPONSE_PAYLOAD_T response; // Verify message payload length is valid - if ( sizeof( U32 ) == message->hdr.payloadLen ) + if ( sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) == message->hdr.payloadLen ) { - memcpy( &cmd, message->payload, sizeof( U32 ) ); + memcpy( &request, message->payload, sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) ); + cmd = request.command; + if ( USER_COMMAND_INITIATE == cmd ) { // Verify TD is in standby mode waiting for treatment start request if ( ( mode != MODE_STAN ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } + else if ( request.modality >= NUM_OF_TREATMENT_MODALITY_TYPES ) + { + rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; + } #ifndef TEST_UI_ONLY // Verify DD is communicating with HD else if ( isDDCommunicating() != TRUE ) @@ -321,6 +393,8 @@ // If request to start treatment not rejected, set flag to initiate treatment workflow result = TRUE; treatStartReqReceived = TRUE; + // Save modality to set later + modality = (TREATMENT_TYPE_T)request.modality; } } else if ( USER_COMMAND_CANCEL == cmd ) Index: firmware/App/Modes/ModeStandby.h =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file ModeStandby.h * -* @author (last) Sean Nash -* @date (last) 18-Apr-2025 +* @author (last) Praneeth Bunne +* @date (last) 02-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -32,6 +32,13 @@ // ********** public definitions ********** +/// Payload record structure for a treatment initiation request +typedef struct +{ + U32 command; ///< Command code (Cancel=0, Initiate=1) + U32 modality; ///< Treatment modality selected by user (ignored on cancel) +} INITIATE_TREATMENT_REQUEST_PAYLOAD_T; + // ********** public function prototypes ********** void initStandbyMode( void ); // Initialize this unit @@ -41,6 +48,10 @@ BOOL signalUserInitiateTreatment( MESSAGE_T *message ); // User has initiated/cancelled treatment workflow void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for Standby mode +void setFluidType( TREATMENT_TYPE_T modality ); // Set a specific fluid type +FLUID_TYPE_T getFluidType( void ); // Get a specific fluid type +TREATMENT_TYPE_T getModality( void ); // Get a specific modality + /**@}*/ #endif Index: firmware/App/Modes/StatePreTxHeparinSetup.c =================================================================== diff -u -r6bb89ac52fecee7db9dc69a3eb727cad0a66370e -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/StatePreTxHeparinSetup.c (.../StatePreTxHeparinSetup.c) (revision 6bb89ac52fecee7db9dc69a3eb727cad0a66370e) +++ firmware/App/Modes/StatePreTxHeparinSetup.c (.../StatePreTxHeparinSetup.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -438,8 +438,10 @@ /*********************************************************************//** * @brief * The handlePreTxHeparinPausedState function handles the paused state. - * @details \b Inputs: none - * @details \b Outputs: Next pre-treatment heparin setup state. + * @details \b Inputs: heparinSetupResumeRequested, + * interruptedPreTxHeparinSetupState + * @details \b Outputs: Next pre-treatment heparin setup state and + * syringe pump operation. * @return Current or next pre-treatment heparin setup state. *************************************************************************/ static PRE_TX_HEPARIN_SETUP_STATE_T handlePreTxHeparinPausedState( void ) @@ -448,33 +450,32 @@ if ( TRUE == heparinSetupResumeRequested ) { - // Resume from Preload, Await Syringe Load Confirmation, or Seek by - // retracting the syringe and restarting the preload sequence. - if ( ( PRE_TX_HEPARIN_SETUP_PRELOAD_STATE == interruptedPreTxHeparinSetupState ) || - ( PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE == interruptedPreTxHeparinSetupState ) || - ( PRE_TX_HEPARIN_SETUP_SEEK_STATE == interruptedPreTxHeparinSetupState ) ) + switch ( interruptedPreTxHeparinSetupState ) { - retractSyringePump(); - state = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; - } - else - { - // Resume from the interrupted state after the alarm is cleared. - state = interruptedPreTxHeparinSetupState; + // If interrupted before Seek is complete, retract the syringe + // and restart the heparin setup sequence from Preload. + case PRE_TX_HEPARIN_SETUP_PRELOAD_STATE: + case PRE_TX_HEPARIN_SETUP_AWAIT_SYRINGE_LOAD_CONFIRMATION_STATE: + case PRE_TX_HEPARIN_SETUP_SEEK_STATE: + retractSyringePump(); + state = PRE_TX_HEPARIN_SETUP_PRELOAD_STATE; + break; - switch ( state ) - { - case PRE_TX_HEPARIN_SETUP_PRIME_STATE: - case PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE: - case PRE_TX_HEPARIN_SETUP_BOLUS_STATE: - setupPreTxHeparinState( state ); - break; + // If interrupted after Seek is complete, resume from the + // heparin setup state that was active before the alarm. + case PRE_TX_HEPARIN_SETUP_PRIME_STATE: + case PRE_TX_HEPARIN_SETUP_OCCLUSION_CHECK_STATE: + case PRE_TX_HEPARIN_SETUP_BOLUS_STATE: + state = interruptedPreTxHeparinSetupState; + setupPreTxHeparinState( state ); + break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE, interruptedPreTxHeparinSetupState ); - state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; - break; - } + // An unexpected interrupted state indicates a software fault. + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE, interruptedPreTxHeparinSetupState ); + + state = PRE_TX_HEPARIN_SETUP_PAUSED_STATE; + break; } } Index: firmware/App/Modes/StateTxBloodPrime.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file StateTxBloodPrime.c * -* @author (last) Praneeth Bunne -* @date (last) 03-Jun-2026 +* @author (last) Sean Nash +* @date (last) 01-Jul-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 09-Jan-2026 @@ -123,7 +123,7 @@ cumulativeBloodPrimeVolume_mL.data = 0.0; resetBloodPrimeFlags(); - bloodPrimeTargetVolume_mL = TUBING_BLOOD_PRIME_VOLUME_ML + (F32)( getDialyzerBloodVolume( getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ) ); + bloodPrimeTargetVolume_mL = (F32)TUBING_BLOOD_PRIME_VOLUME_ML + (F32)( getDialyzerBloodVolume( (DIALYZER_TYPE_T)getTreatmentParameterU32( TREATMENT_PARAM_DIALYZER_TYPE ) ) ); bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; // Calculate BP ramp step size Index: firmware/App/Modes/StateTxPaused.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Modes/StateTxPaused.c (.../StateTxPaused.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Modes/StateTxPaused.c (.../StateTxPaused.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file StateTxPaused.c * * @author (last) Praneeth Bunne -* @date (last) 29-May-2026 +* @date (last) 26-Jun-2026 * * @author (original) Sean Nash * @date (original) 21-Apr-2025 @@ -22,13 +22,15 @@ #include "DDInterface.h" #include "FluidBolus.h" #include "Messaging.h" +#include "ModeStandby.h" #include "ModeTreatment.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "RotaryValve.h" #include "StateTxPaused.h" #include "Switches.h" #include "TaskGeneral.h" +#include "TubeSetInstall.h" #include "TxParams.h" #include "Valves.h" #include "Valve3Way.h" @@ -65,6 +67,8 @@ static void transitionToTxPausedState( TREATMENT_PAUSED_STATE_T newState ); static void publishTreatmentPausedData( void ); +static BOOL isFluidBolusPermitted( void ); + /*********************************************************************//** * @brief * The initTreatmentPaused function initializes the Treatment Paused State unit. @@ -298,26 +302,15 @@ /*********************************************************************//** * @brief * The handleTreatmentPausedFluidBolusState function handles the fluid - * bolus sub-state of the Treatment Paused state machine. Entered either - * when an alarm fires during an active bolus in a calling state, or when - * the user requests a new bolus from the paused state. - * Monitors the permitted alarm set every tick — aborts the bolus if a - * non-permitted alarm becomes active. - * @details \b Inputs: none + * bolus sub-state of the Treatment Paused state machine. + * @details \b Inputs: pauseBolusResumeState * @details \b Outputs: currentTxPausedState * @return next treatment paused state. *************************************************************************/ static TREATMENT_PAUSED_STATE_T handleTreatmentPausedFluidBolusState( void ) { TREATMENT_PAUSED_STATE_T result = TREATMENT_PAUSED_FLUID_BOLUS_STATE; - // Monitor permitted alarms every tick - if ( ( TRUE == isFluidBolusActive() ) && ( FALSE == isBolusAllowedByActiveAlarms() ) ) - { - signalAbortFluidBolus(); - setBolusPermitted( FALSE ); - } - // Return to pre-bolus sub-state upon bolus complete or abort if ( FALSE == isFluidBolusActive() ) { @@ -332,15 +325,15 @@ * The signalPauseFluidBolusRequest function handles a fluid bolus request * while in the Treatment Paused state. Bolus request is rejected while in * Recover blood detect state. - * @details \b Inputs: currentTxPausedState + * @details \b Inputs: none * @details \b Outputs: fluidBolusRequested * @return TRUE if request is accepted, FALSE if rejected. *************************************************************************/ BOOL signalPauseTreatFluidBolusRequest( void ) { BOOL result = FALSE; - if ( TREATMENT_PAUSED_RECOVER_BLOOD_DETECT_STATE != currentTxPausedState ) + if ( TRUE == isFluidBolusPermitted() ) { fluidBolusRequested = TRUE; result = TRUE; @@ -351,6 +344,26 @@ /*********************************************************************//** * @brief + * The isFluidBolusPermitted function determines whether a fluid bolus + * is currently permitted or not. + * @details \b Inputs: none + * @details \b Outputs: none + * @return TRUE if bolus is permitted, FALSE otherwise. + *************************************************************************/ +static BOOL isFluidBolusPermitted( void ) +{ + BOOL result = FALSE; + + if ( FLUID_TYPE_SALINE == getFluidType() ) + { + result = ( TRUE != isBloodRecircBlocked() ) ? TRUE : FALSE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleTreatmentPausedBloodSittingTimer function handles the no re-circ * blood timer. It should only be called when Blood is NOT circulating. * Increments and checks for warning and alarm timeouts. @@ -542,7 +555,7 @@ } // Set if bolus is permitted or not. - setBolusPermitted( isBolusAllowedByActiveAlarms() ); + setBolusPermitted( isFluidBolusPermitted() ); } /*********************************************************************//** Index: firmware/App/Monitors/Switches.c =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Monitors/Switches.c (.../Switches.c) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Monitors/Switches.c (.../Switches.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -153,7 +153,7 @@ { if ( getSwitchState( H9_SWCH ) != STATE_CLOSED ) { - activateAlarmNoData( ALARM_ID_TD_CARTRIDGE_DOOR_OPENED ); +// activateAlarmNoData( ALARM_ID_TD_CARTRIDGE_DOOR_OPENED ); } } Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r3f032347c774cab541bd9efb143fa874f65d25e9 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 3f032347c774cab541bd9efb143fa874f65d25e9) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file AlarmMgmtSWFaults.h * -* @author (last) Vijay Pamula -* @date (last) 12-Jun-2026 +* @author (last) Praneeth Bunne +* @date (last) 02-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -197,7 +197,9 @@ SW_FAULT_ID_MODE_POST_TX_AUTO_EJECT_INVALID_STATE = 166, SW_FAULT_ID_INVALID_FLUID_BOLUS_STATE = 167, SW_FAULT_ID_PRE_TX_RECIRC_INVALID_STATE = 168, - SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE =169, + SW_FAULT_ID_TD_VALVES_INVALID_VALVE2 = 169, + SW_FAULT_ID_INVALID_TUBE_SET_TYPE = 170, + SW_FAULT_ID_TD_INVALID_PRE_TX_HEPARIN_SETUP_STATE =171, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/AlarmMgmtTD.c =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/AlarmMgmtTD.c (.../AlarmMgmtTD.c) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Services/AlarmMgmtTD.c (.../AlarmMgmtTD.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,77 +7,78 @@ * * @file AlarmMgmtTD.c * -* @author (last) Dara Navaei -* @date (last) 01-Aug-2025 +* @author (last) Santhosh Reddy +* @date (last) 06-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 * ***************************************************************************/ #define __ALARM_MGMT_TD_C__ - -#include "mibspi.h" - + +#include "mibspi.h" + #include "AlarmMgmtTD.h" #include "Bubbles.h" #include "CpldInterface.h" +#include "FluidBolus.h" #include "Messaging.h" #include "OperationModes.h" -#include "TaskGeneral.h" -#include "Timers.h" +#include "TaskGeneral.h" +#include "Timers.h" -/** - * @addtogroup AlarmManagementTD - * @{ - */ - -// ********** private definitions ********** +/** + * @addtogroup AlarmManagementTD + * @{ + */ -/// Interval to control lamp and audio and to publish alarm status data. -#define ALARM_STATUS_PUBLISH_INTERVAL ( ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) +// ********** private definitions ********** +/// Interval to control lamp and audio and to publish alarm status data. +#define ALARM_STATUS_PUBLISH_INTERVAL ( ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) + /// Interval (ms/task time) at which the alarm information is published on the CAN bus. #define ALARM_INFO_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) #define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. /// Interval (ms/task time) Alarms are blocked after the return of AC power. #define ALARM_BLOCKED_COUNT_AFTER_AC_RETURN ( 10*MS_PER_SECOND / TASK_GENERAL_INTERVAL ) - -#define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. - + +#define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. + #define LOWEST_ALARM_SUB_RANK 999 ///< Lowest alarm sub-rank that can be set. #define ALARM_NOT_BLOCKED 0 ///< Alarm blocked timer value that indicates no alarm block -#define MIN_TIME_BETWEEN_ALARM_ACTIONS_MS MS_PER_SECOND ///< Minimum time between user alarm actions (in ms). - -/// A blank alarm data record for alarms that do not include alarm data when triggered. -const ALARM_DATA_T BLANK_ALARM_DATA = { ALARM_DATA_TYPE_NONE, 0 }; - +#define MIN_TIME_BETWEEN_ALARM_ACTIONS_MS MS_PER_SECOND ///< Minimum time between user alarm actions (in ms). + +/// A blank alarm data record for alarms that do not include alarm data when triggered. +const ALARM_DATA_T BLANK_ALARM_DATA = { ALARM_DATA_TYPE_NONE, 0 }; + /// Alarm priority ranking record. typedef struct { ALARM_ID_T alarmID; ///< ID of highest priority alarm in this priority category U32 subRank; ///< Sub-rank of this alarm S32 timeSinceTriggeredMS; ///< Time (in ms) since this alarm was triggered } ALARM_PRIORITY_RANKS_T; - -// ********** private data ********** - -static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< Table - when alarm became active for each alarm (if active) or zero (if inactive) + +// ********** private data ********** + +static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< Table - when alarm became active for each alarm (if active) or zero (if inactive) static U32 alarmStatusPublicationTimerCounter = 0; ///< Used to schedule alarm status publication to CAN bus. -static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. +static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. static U32 alarmsBlockedTimer = 0; ///< Countdown timer used to temporarily block new alarms from being initiated static U32 lastUserAlarmActionReceivedTime = 0; ///< Time of last alarm action by user received from the UI (ms timestamp). - + /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T alarmStatusPublishInterval = { ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, 0 }; /// Interval (in task intervals) at which to publish alarm information to CAN bus. static OVERRIDE_U32_T alarmInfoPublishInterval = { ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, 0 }; -static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. +static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. static ALARM_PRIORITY_RANKS_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; ///< FIFO - first activated or highest sub-rank alarm in each alarm priority category. static BOOL alarmUserRecoveryActionEnabled[ NUMBER_OF_ALARM_USER_ACTIONS ]; ///< Alarm user recovery actions enabled flags. @@ -86,76 +87,76 @@ static BOOL resumeBlockedByAlarmProperty; ///< Flag indicates whether treatment resumption is currently blocked by alarm property. -// ********** private function prototypes ********** - -static void activateAlarmTD( ALARM_ID_T alarm ); +// ********** private function prototypes ********** -static void monitorAlarms( void ); -static void updateAlarmsState( void ); -static void setAlarmLamp( void ); -static void updateAlarmsSilenceStatus( void ); -static void updateAlarmsFlags( void ); +static void activateAlarmTD( ALARM_ID_T alarm ); -static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); -static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); - +static void monitorAlarms( void ); +static void updateAlarmsState( void ); +static void setAlarmLamp( void ); +static void updateAlarmsSilenceStatus( void ); +static void updateAlarmsFlags( void ); + +static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); +static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); + static U32 getAlarmStartTime( ALARM_ID_T alarmID ); static void publishAlarmInfo( void ); static BOOL broadcastAlarmStatus( COMP_ALARM_STATUS_T almStatus ); - -/*********************************************************************//** - * @brief - * The initAlarmMgmtTD function initializes the TD AlarmMgmt unit. - * @details \b Inputs: none - * @details \b Outputs: TD AlarmMgmt unit initialized. - * @return none - *************************************************************************/ -void initAlarmMgmtTD( void ) -{ - ALARM_PRIORITY_T p; + +/*********************************************************************//** + * @brief + * The initAlarmMgmtTD function initializes the TD AlarmMgmt unit. + * @details \b Inputs: none + * @details \b Outputs: TD AlarmMgmt unit initialized. + * @return none + *************************************************************************/ +void initAlarmMgmtTD( void ) +{ + ALARM_PRIORITY_T p; ALARM_ID_T a; ALARM_BUTTON_BLOCKER_T b; // Initialize common alarm mgmt unit - initAlarmMgmt(); - - // Initialize alarm states and start time stamps - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + initAlarmMgmt(); + + // Initialize alarm states and start time stamps + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { - alarmStartedAt[ a ].data = 0; - alarmStartedAt[ a ].ovData = 0; - alarmStartedAt[ a ].ovInitData = 0; - alarmStartedAt[ a ].override = OVERRIDE_RESET; - } - // Initialize alarm FIFOs - for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) - { + alarmStartedAt[ a ].data = 0; + alarmStartedAt[ a ].ovData = 0; + alarmStartedAt[ a ].ovInitData = 0; + alarmStartedAt[ a ].override = OVERRIDE_RESET; + } + // Initialize alarm FIFOs + for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) + { alarmPriorityFIFO[ p ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ p ].subRank = LOWEST_ALARM_SUB_RANK; - alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; + alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; } // Initialize alarm button blocker flags for ( b = (ALARM_BUTTON_BLOCKER_T)0; b < NUM_OF_ALARM_BUTTON_BLOCKERS; b++ ) { alarmButtonBlockers[ b ] = FALSE; - } - // Initialize composite alarm state - alarmStatus.alarmsState = ALARM_PRIORITY_NONE; - alarmStatus.alarmsSilenced = FALSE; - alarmStatus.alarmsSilenceStart = 0; + } + // Initialize composite alarm state + alarmStatus.alarmsState = ALARM_PRIORITY_NONE; + alarmStatus.alarmsSilenced = FALSE; + alarmStatus.alarmsSilenceStart = 0; alarmStatus.alarmsSilenceExpiresIn = 0; alarmStatus.alarmTop = ALARM_ID_NO_ALARM; - alarmStatus.topAlarmConditionDetected = FALSE; - alarmStatus.systemFault = FALSE; + alarmStatus.topAlarmConditionDetected = FALSE; + alarmStatus.systemFault = FALSE; alarmStatus.stop = FALSE; - alarmStatus.lampOn = FALSE; - alarmStatus.noClear = FALSE; - alarmStatus.noResume = FALSE; - alarmStatus.noRinseback = FALSE; + alarmStatus.lampOn = FALSE; + alarmStatus.noClear = FALSE; + alarmStatus.noResume = FALSE; + alarmStatus.noRinseback = FALSE; alarmStatus.noEndTreatment = FALSE; alarmStatus.noBloodRecirc = FALSE; - alarmStatus.noDialRecirc = FALSE; + alarmStatus.noDialRecirc = FALSE; alarmStatus.ok = FALSE; alarmsBlockedTimer = 0; @@ -165,24 +166,24 @@ // Initialize alarm audio and lamp initAlarmLamp(); initAlarmAudio(); -} - -/*********************************************************************//** - * @brief - * The execAlarmMgmt function executes the TD alarm management functions to be - * done periodically. The system alarm state is updated, alarm lamp and +} + +/*********************************************************************//** + * @brief + * The execAlarmMgmt function executes the TD alarm management functions to be + * done periodically. The system alarm state is updated, alarm lamp and * audio patterns are updated, and the state of the alarm system is sent out - * to the rest of the system. - * @details \b Inputs: alarmsBlockedTimer - * @details \b Outputs: alarmsBlockedTimer - * @return none - *************************************************************************/ -void execAlarmMgmt( void ) + * to the rest of the system. + * @details \b Inputs: alarmsBlockedTimer + * @details \b Outputs: alarmsBlockedTimer + * @return none + *************************************************************************/ +void execAlarmMgmt( void ) { monitorAlarms(); - updateAlarmsState(); - updateAlarmsFlags(); - updateAlarmsSilenceStatus(); + updateAlarmsState(); + updateAlarmsFlags(); + updateAlarmsSilenceStatus(); // Publish alarm status and information at interval publishAlarmInfo(); @@ -214,9 +215,9 @@ ALARM_T props = getAlarmProperties( alarm ); ALARM_T props_top = getAlarmProperties( alarmStatus.alarmTop ); - // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm + // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm if ( ( FALSE == isAlarmActive( alarm ) ) || - ( ( FALSE == isAlarmConditionDetected( alarm ) ) && ( FALSE == props.alarmConditionClearImmed ) ) ) + ( ( FALSE == isAlarmConditionDetected( alarm ) ) && ( FALSE == props.alarmConditionClearImmed ) ) ) { activateAlarm( alarm ); alarmStartedAt[ alarm ].data = getMSTimerCount(); @@ -231,31 +232,33 @@ if ( ALARM_ID_NO_ALARM == alarmStatus.alarmTop ) { alarmStatus.alarmTop = alarm; - } + } // If alarm stops, set that status immediately (don't wait for status update function) if ( TRUE == props.alarmStops ) { alarmStatus.stop = TRUE; + // Signal when alarm with stop property is triggered to fluid bolus + signalNewStopAlarmActivated(); } - // If alarm is a fault (and not in service mode), request transition to fault mode - if ( ( TRUE == props.alarmIsFault ) && ( getCurrentOperationMode() != MODE_SERV ) ) - { - requestNewOperationMode( MODE_FAUL ); - } + // If alarm is a fault (and not in service mode), request transition to fault mode + if ( ( TRUE == props.alarmIsFault ) && ( getCurrentOperationMode() != MODE_SERV ) ) + { +// requestNewOperationMode( MODE_FAUL ); + } // If alarm has stop property, signal stop now if ( TRUE == props.alarmStops ) { initiateAlarmAction( ALARM_ACTION_STOP ); - } - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE1, alarm ) + } + } } -} - + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE1, alarm ) + } +} + /*********************************************************************//** * @brief * The clearAlarmTD function clears a given alarm if it is recoverable. @@ -289,51 +292,51 @@ } } -/*********************************************************************//** - * @brief +/*********************************************************************//** + * @brief * The activateAlarmNoData function activates a given alarm. The alarm - * data that gets logged with this alarm will be blank. - * @details \b Inputs: none - * @details \b Outputs: Alarm is activated - * @param alarm ID of alarm to activate - * @return none - *************************************************************************/ -void activateAlarmNoData( ALARM_ID_T alarm ) + * data that gets logged with this alarm will be blank. + * @details \b Inputs: none + * @details \b Outputs: Alarm is activated + * @param alarm ID of alarm to activate + * @return none + *************************************************************************/ +void activateAlarmNoData( ALARM_ID_T alarm ) { - activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); -} - -/*********************************************************************//** - * @brief + activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); +} + +/*********************************************************************//** + * @brief * The activateAlarm1Data function activates a given alarm. The one given * alarm data will be logged with this alarm as well as a second blank data. - * @details \b Inputs: none - * @details \b Outputs: Alarm is activated - * @param alarm ID of alarm to activate - * @param alarmData First supporting data to include in alarm message - * @return none - *************************************************************************/ -void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) -{ + * @details \b Inputs: none + * @details \b Outputs: Alarm is activated + * @param alarm ID of alarm to activate + * @param alarmData First supporting data to include in alarm message + * @return none + *************************************************************************/ +void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) +{ activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA, FALSE ); -} - -/*********************************************************************//** - * @brief +} + +/*********************************************************************//** + * @brief * The activateAlarm2Data function activates a given alarm. The two given * alarm data will be logged with this alarm. * @details \b Message \b Sent: MSG_ID_ALARM_TRIGGERED - * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given alarm ID is invalid. - * @details \b Inputs: alarmsBlockedTimer, determines blocked alarm conditions - * @details \b Outputs: Alarm is activated - * @param alarm ID of alarm to activate - * @param alarmData1 First supporting data to include in alarm message + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given alarm ID is invalid. + * @details \b Inputs: alarmsBlockedTimer, determines blocked alarm conditions + * @details \b Outputs: Alarm is activated + * @param alarm ID of alarm to activate + * @param alarmData1 First supporting data to include in alarm message * @param alarmData2 Second supporting data to include in alarm message - * @param outside flag indicates whether alarm is originating from outside TD f/w - * @return none - *************************************************************************/ -void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) -{ + * @param outside flag indicates whether alarm is originating from outside TD f/w + * @return none + *************************************************************************/ +void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) +{ // Block if new alarms are occur during loss of AC power // if ( ( TRUE == getCPLDACPowerLossDetected() ) ) // { @@ -390,7 +393,7 @@ else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE2, alarm ) - } + } } /*********************************************************************//** @@ -679,7 +682,7 @@ ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ) { return alarmStatus.alarmsState; -} +} /*********************************************************************//** * @brief @@ -891,14 +894,14 @@ } /*********************************************************************//** - * @brief + * @brief * The getAlarmStartTime function gets the start time of a given alarm. - * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given alarm ID is invalid. - * @details \b Inputs: alarmStartedAt[] - * @details \b Outputs: none - * @param alarmID ID of alarm to get start time for - * @return The start time stamp (seconds since power up) of given alarm ID - *************************************************************************/ + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given alarm ID is invalid. + * @details \b Inputs: alarmStartedAt[] + * @details \b Outputs: none + * @param alarmID ID of alarm to get start time for + * @return The start time stamp (seconds since power up) of given alarm ID + *************************************************************************/ static U32 getAlarmStartTime( ALARM_ID_T alarmID ) { U32 result = 0; @@ -945,35 +948,35 @@ // TODO - Check current vs. expected audio output } - -/*********************************************************************//** - * @brief + +/*********************************************************************//** + * @brief * The updateAlarmsState function re-evaluates the current alarm system state * and the "top" alarm to display (highest ranking active alarm). Some of - * the properties of alarm system status are re-evaluated as well. - * @details \b Inputs: alarmStatusTable[] - * @details \b Outputs: alarmStatus, alarmPriorityFIFO[] - * @return none - *************************************************************************/ -static void updateAlarmsState( void ) -{ - ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE, p; - ALARM_ID_T a; + * the properties of alarm system status are re-evaluated as well. + * @details \b Inputs: alarmStatusTable[] + * @details \b Outputs: alarmStatus, alarmPriorityFIFO[] + * @return none + *************************************************************************/ +static void updateAlarmsState( void ) +{ + ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE, p; + ALARM_ID_T a; BOOL faultsActive = FALSE; - BOOL dialysateRecircBlocked = FALSE; + BOOL dialysateRecircBlocked = FALSE; BOOL bloodRecircBlocked = FALSE; // Reset priority FIFOs so we can re-determine them below for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) { resetAlarmPriorityFIFO( p ); } - - // Update FIFOs and sub-ranks per active alarms table - for alarm ranking purposes to determine "top" alarm - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) - { - if ( TRUE == isAlarmActive( a ) ) - { + + // Update FIFOs and sub-ranks per active alarms table - for alarm ranking purposes to determine "top" alarm + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == isAlarmActive( a ) ) + { ALARM_T props = getAlarmProperties( a ); ALARM_PRIORITY_T almPriority = props.alarmPriority; U32 subRank = props.alarmSubRank; @@ -1000,87 +1003,87 @@ alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = (S32)msSinceTriggered; } } - // Track highest priority alarm found so far of all priority categories + // Track highest priority alarm found so far of all priority categories highestPriority = MAX( almPriority, highestPriority ); - // Track whether any active faults have been found so far - if ( TRUE == props.alarmIsFault ) - { - faultsActive = TRUE; + // Track whether any active faults have been found so far + if ( TRUE == props.alarmIsFault ) + { + faultsActive = TRUE; } // Track whether any active alarms prevent dialysate re-circulation so far if ( TRUE == props.alarmNoDialysateRecirc ) { dialysateRecircBlocked = TRUE; - } + } // Track whether any active alarms prevent blood re-circulation so far if ( TRUE == props.alarmNoBloodRecirc ) { bloodRecircBlocked = TRUE; } - } - } - - // Update alarm to display per highest priority FIFO - alarmStatus.alarmsState = highestPriority; + } + } + + // Update alarm to display per highest priority FIFO + alarmStatus.alarmsState = highestPriority; alarmStatus.alarmTop = alarmPriorityFIFO[ highestPriority ].alarmID; - alarmStatus.topAlarmConditionDetected = isAlarmConditionDetected( alarmStatus.alarmTop ); + alarmStatus.topAlarmConditionDetected = isAlarmConditionDetected( alarmStatus.alarmTop ); alarmStatus.systemFault = faultsActive; alarmStatus.noBloodRecirc = bloodRecircBlocked; - alarmStatus.noDialRecirc = dialysateRecircBlocked; -} - -/*********************************************************************//** - * @brief + alarmStatus.noDialRecirc = dialysateRecircBlocked; +} + +/*********************************************************************//** + * @brief * The setAlarmLamp function sets the alarm lamp pattern according to the * current state of alarms. - * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if reported alarm state is invalid. - * @details \b Inputs: alarmStatus, ALARM_TABLE[] + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if reported alarm state is invalid. + * @details \b Inputs: alarmStatus, ALARM_TABLE[] * @details \b Outputs: alarmStatus, alarm lamp pattern set according to - * current alarms status. - * @return none - *************************************************************************/ -static void setAlarmLamp( void ) + * current alarms status. + * @return none + *************************************************************************/ +static void setAlarmLamp( void ) { - // Set alarm lamp pattern to appropriate pattern for current alarm state - if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) - { - switch ( alarmStatus.alarmsState ) - { - case ALARM_PRIORITY_NONE: - requestAlarmLampPattern( LAMP_PATTERN_OK ); - break; - - case ALARM_PRIORITY_LOW: - requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); - break; - - case ALARM_PRIORITY_MEDIUM: - requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); - break; - + // Set alarm lamp pattern to appropriate pattern for current alarm state + if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) + { + switch ( alarmStatus.alarmsState ) + { + case ALARM_PRIORITY_NONE: + requestAlarmLampPattern( LAMP_PATTERN_OK ); + break; + + case ALARM_PRIORITY_LOW: + requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); + break; + + case ALARM_PRIORITY_MEDIUM: + requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); + break; + case ALARM_PRIORITY_HIGH: - { + { ALARM_T propsTop = getAlarmProperties( alarmStatus.alarmTop ); - if ( TRUE == propsTop.alarmIsFault ) - { - requestAlarmLampPattern( LAMP_PATTERN_FAULT ); - } - else - { - requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); + if ( TRUE == propsTop.alarmIsFault ) + { + requestAlarmLampPattern( LAMP_PATTERN_FAULT ); } - } - break; - - default: - requestAlarmLampPattern( LAMP_PATTERN_FAULT ); - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) - break; + else + { + requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); + } + } + break; + + default: + requestAlarmLampPattern( LAMP_PATTERN_FAULT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) + break; } } - // Execute alarm lamp controller + // Execute alarm lamp controller execAlarmLamp(); // Set lamp on flag to match current state of alarm lamp @@ -1091,69 +1094,69 @@ else { alarmStatus.lampOn = FALSE; - } -} - -/*********************************************************************//** - * @brief - * The updateAlarmsSilenceStatus function updates the alarms silence state. - * @details \b Inputs: alarmStatus - * @details \b Outputs: alarmStatus - * @return none - *************************************************************************/ -static void updateAlarmsSilenceStatus( void ) -{ - // If alarms not silenced, reset alarms silence related properties - if ( TRUE != alarmStatus.alarmsSilenced ) - { - alarmStatus.alarmsSilenceExpiresIn = 0; - alarmStatus.alarmsSilenceStart = 0; - } - else - { - U32 timeSinceAlarmSilenceStart = calcTimeSince( alarmStatus.alarmsSilenceStart ) / MS_PER_SECOND; - - if ( timeSinceAlarmSilenceStart >= ALARM_SILENCE_EXPIRES_IN_SECS ) - { - alarmStatus.alarmsSilenceExpiresIn = 0; - } - else - { - alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; - } - // If alarms silence expires, end it - if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) - { - alarmStatus.alarmsSilenced = FALSE; - } - } -} + } +} -/*********************************************************************//** - * @brief +/*********************************************************************//** + * @brief + * The updateAlarmsSilenceStatus function updates the alarms silence state. + * @details \b Inputs: alarmStatus + * @details \b Outputs: alarmStatus + * @return none + *************************************************************************/ +static void updateAlarmsSilenceStatus( void ) +{ + // If alarms not silenced, reset alarms silence related properties + if ( TRUE != alarmStatus.alarmsSilenced ) + { + alarmStatus.alarmsSilenceExpiresIn = 0; + alarmStatus.alarmsSilenceStart = 0; + } + else + { + U32 timeSinceAlarmSilenceStart = calcTimeSince( alarmStatus.alarmsSilenceStart ) / MS_PER_SECOND; + + if ( timeSinceAlarmSilenceStart >= ALARM_SILENCE_EXPIRES_IN_SECS ) + { + alarmStatus.alarmsSilenceExpiresIn = 0; + } + else + { + alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; + } + // If alarms silence expires, end it + if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) + { + alarmStatus.alarmsSilenced = FALSE; + } + } +} + +/*********************************************************************//** + * @brief * The updateAlarmsFlags function updates the alarms status flags of the - * alarms status record. + * alarms status record. * @details \b Inputs: alarmStatus, alarmIsActive, ALARM_TABLE[], - * alarmButtonBlockers[]. alarmUserRecoveryActionEnabled[] - * @details \b Outputs: alarmStatus, alarmButtonBlockers[] - * @return none - *************************************************************************/ -static void updateAlarmsFlags( void ) -{ - BOOL systemFault = FALSE; - BOOL stop = FALSE; - BOOL noClear = FALSE; + * alarmButtonBlockers[]. alarmUserRecoveryActionEnabled[] + * @details \b Outputs: alarmStatus, alarmButtonBlockers[] + * @return none + *************************************************************************/ +static void updateAlarmsFlags( void ) +{ + BOOL systemFault = FALSE; + BOOL stop = FALSE; + BOOL noClear = FALSE; BOOL noResume = FALSE; - BOOL noResumePerAlarmPropertyOnly = FALSE; - BOOL noRinseback = FALSE; + BOOL noResumePerAlarmPropertyOnly = FALSE; + BOOL noRinseback = FALSE; BOOL noEndTreatment = FALSE; - BOOL endTxOnlyAlarmActive = FALSE; + BOOL endTxOnlyAlarmActive = FALSE; BOOL usrAckReq = FALSE; BOOL noMinimize = TRUE; TD_OP_MODE_T currentMode = getCurrentOperationMode(); ALARM_T propsTop = getAlarmProperties( alarmStatus.alarmTop ); - ALARM_ID_T a; - + ALARM_ID_T a; + // Set user alarm recovery actions allowed by state flags alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RESUME ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ? FALSE : TRUE ); alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RINSEBACK ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ? FALSE : TRUE ); @@ -1163,40 +1166,40 @@ alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] = FALSE; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] = FALSE; - // Determine alarm flags - for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) - { - if ( TRUE == isAlarmActive( a ) ) - { + // Determine alarm flags + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == isAlarmActive( a ) ) + { ALARM_T props = getAlarmProperties( a ); - systemFault = ( TRUE == props.alarmIsFault ? TRUE : systemFault ); - stop = ( TRUE == props.alarmStops ? TRUE : stop ); + systemFault = ( TRUE == props.alarmIsFault ? TRUE : systemFault ); + stop = ( TRUE == props.alarmStops ? TRUE : stop ); noClear = ( TRUE == props.alarmNoClear ? TRUE : noClear ); noResumePerAlarmPropertyOnly = ( props.alarmNoResume ? TRUE : noResumePerAlarmPropertyOnly ); // Set user alarm recovery actions allowed flags alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RESUME ] |= props.alarmNoResume; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] |= props.alarmNoRinseback; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] |= props.alarmNoEndTreatment; if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ) - { + { noResume = ( TRUE == props.alarmNoResume ? TRUE : noResume ); } else { noResume = TRUE; - } + } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ) { noRinseback = ( TRUE == props.alarmNoRinseback ? TRUE : noRinseback ); } else { noRinseback = TRUE; - } + } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_END_TREATMENT ] ) { - noEndTreatment = ( TRUE == props.alarmNoEndTreatment ? TRUE : noEndTreatment ); + noEndTreatment = ( TRUE == props.alarmNoEndTreatment ? TRUE : noEndTreatment ); } else { @@ -1208,8 +1211,8 @@ ( FALSE == props.alarmNoEndTreatment ) ) { endTxOnlyAlarmActive = TRUE; - } - } // If alarm active + } + } // If alarm active } // Alarm table loop // If top alarm condition not cleared, block resume @@ -1252,16 +1255,16 @@ noMinimize = FALSE; } - // Set updated alarm flags - alarmStatus.systemFault = systemFault; - alarmStatus.stop = stop; - alarmStatus.noClear = noClear; - alarmStatus.noResume = noResume; - alarmStatus.noRinseback = noRinseback; - alarmStatus.noEndTreatment = noEndTreatment; - alarmStatus.ok = usrAckReq; + // Set updated alarm flags + alarmStatus.systemFault = systemFault; + alarmStatus.stop = stop; + alarmStatus.noClear = noClear; + alarmStatus.noResume = noResume; + alarmStatus.noRinseback = noRinseback; + alarmStatus.noEndTreatment = noEndTreatment; + alarmStatus.ok = usrAckReq; alarmStatus.noMinimize = noMinimize; - resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; + resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; } /*********************************************************************//** @@ -1302,32 +1305,32 @@ } return result; -} - -/*********************************************************************//** - * @brief - * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm +} + +/*********************************************************************//** + * @brief + * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm * priority. - * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given priority is invalid. - * @details \b Inputs: none - * @details \b Outputs: alarmPriorityFIFO[] - * @param priority Alarm priority associated with FIFO to reset - * @return none - *************************************************************************/ -static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) -{ - // Verify priority - if ( priority < NUM_OF_ALARM_PRIORITIES ) - { + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given priority is invalid. + * @details \b Inputs: none + * @details \b Outputs: alarmPriorityFIFO[] + * @param priority Alarm priority associated with FIFO to reset + * @return none + *************************************************************************/ +static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) +{ + // Verify priority + if ( priority < NUM_OF_ALARM_PRIORITIES ) + { alarmPriorityFIFO[ priority ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ priority ].subRank = LOWEST_ALARM_SUB_RANK; - alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = -1; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) - } -} + alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = -1; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) + } +} /*********************************************************************//** * @brief @@ -1412,23 +1415,23 @@ return result; } - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ - - -/*********************************************************************//** - * @brief - * The testSetAlarmStartTimeOverride function overrides the start time for a - * given alarm with a given start time. - * @details \b Inputs: msTimerCount - * @details \b Outputs: alarmStartedAt[] + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetAlarmStartTimeOverride function overrides the start time for a + * given alarm with a given start time. + * @details \b Inputs: msTimerCount + * @details \b Outputs: alarmStartedAt[] * @param message Override message from Dialin which includes an ID of * the alarm to override start time for and a number of milliseconds the * override is seeking to make the elapsed time since the given alarm was - * triggered. - * @return TRUE if override is successful, FALSE if not + * triggered. + * @return TRUE if override is successful, FALSE if not *************************************************************************/ BOOL testSetAlarmStartTimeOverride( MESSAGE_T *message ) { @@ -1467,7 +1470,7 @@ return result; } - + /*********************************************************************//** * @brief * The testClearAllAlarms function clears all active alarms, even if they @@ -1563,4 +1566,56 @@ return result; } +/*********************************************************************//** + * @brief + * The testGetAlarmPropertiesRequest function processes a request + * to retrieve alarm properties and broadcasts the result. + * @details \b Inputs: None + * @details \b Outputs: None + * @param message Pointer to MESSAGE_T containing the alarm ID request + * @return TRUE if alarm properties were successfully broadcasted. + * FALSE if payload length is invalid or alarm ID + * is out of range + *************************************************************************/ +BOOL testGetAlarmPropertiesRequest( MESSAGE_T *message ) +{ + ALARM_ID_T alarmID; + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof( U32 ) ) + { + memcpy( &alarmID, message->payload, sizeof( ALARM_ID_T ) ); + + if ( alarmID < NUM_OF_ALARM_IDS ) + { + ALARM_PROP_T canMsg; + ALARM_T alarm = getAlarmProperties( alarmID ); + + canMsg.alarmPriority = (U08)alarm.alarmPriority; + canMsg.alarmSubRank = (U16)alarm.alarmSubRank; + canMsg.alarmSource = (U08)alarm.alarmSource; + canMsg.alarmIsFault = (U08)alarm.alarmIsFault; + canMsg.alarmIsDDFault = (U08)alarm.alarmIsDDFault; + canMsg.alarmStops = (U08)alarm.alarmStops; + canMsg.alarmConditionClearImmed = (U08)alarm.alarmConditionClearImmed; + canMsg.alarmNoClear = (U08)alarm.alarmNoClear; + canMsg.alarmNoResume = (U08)alarm.alarmNoResume; + canMsg.alarmNoRinseback = (U08)alarm.alarmNoRinseback; + canMsg.alarmNoEndTreatment = (U08)alarm.alarmNoEndTreatment; + canMsg.alarmBlockRinseback = (U08)alarm.alarmBlockRinseback; + canMsg.alarmBlockEndTx = (U08)alarm.alarmBlockEndTx; + canMsg.alarmNoBloodRecirc = (U08)alarm.alarmNoBloodRecirc; + canMsg.alarmNoDialysateRecirc = (U08)alarm.alarmNoDialysateRecirc; + canMsg.alarmAutoResume = (U08)alarm.alarmAutoResume; + canMsg.alarmClearOnly = (U08)alarm.alarmClearOnly; + canMsg.alarmTreatmentLog = (U08)alarm.alarmTreatmentLog; + canMsg.alarmID = (U16)alarm.alarmID; + + result = broadcastData( MSG_ID_TD_ALARM_PROPERTIES_RESPONSE, COMM_BUFFER_OUT_CAN_PC, (U08*)&canMsg, sizeof( ALARM_PROP_T ) ); + } + } + + return result; +} + /**@}*/ Index: firmware/App/Services/AlarmMgmtTD.h =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/AlarmMgmtTD.h (.../AlarmMgmtTD.h) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/AlarmMgmtTD.h (.../AlarmMgmtTD.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file AlarmMgmtTD.h * -* @author (last) Praneeth Bunne -* @date (last) 28-May-2026 +* @author (last) Santhosh Reddy +* @date (last) 06-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -156,6 +156,7 @@ void handleResendActiveAlarmsRequest( void ); void handleAutoResumeAlarm( ALARM_ID_T alarm ); +BOOL testGetAlarmPropertiesRequest( MESSAGE_T *message ); BOOL testSetAlarmStartTimeOverride( MESSAGE_T *message ); BOOL testClearAllAlarms( MESSAGE_T *message ); BOOL testAlarmStatusPublishIntervalOverride( MESSAGE_T *message ); Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r5cc57a6d8eb3721811a2d6ace3176b7074c52fe8 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 5cc57a6d8eb3721811a2d6ace3176b7074c52fe8) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file Messaging.c * -* @author (last) Vijay Pamula -* @date (last) 08-Jun-2026 +* @author (last) Santhosh Reddy +* @date (last) 06-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -132,6 +132,7 @@ { MSG_ID_UI_BLOOD_PRIME_CMD_REQUEST, &bloodPrimeHandleCmdRequest }, { MSG_ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_REQUEST, &bloodPrimeHandleBloodFlowChangeRequest }, { MSG_ID_UI_ADJUST_DISPOSABLES_CONFIRM_REQUEST, &handleAutoLoadRequest }, + { MSG_ID_TD_SETUP_TUBING_SET_CONNECTIONS_CONFIRM_REQUEST, &handleSetupTubingSetConnectionConfirmRequest }, { MSG_ID_UI_ADJUST_DISPOSABLES_REMOVAL_CONFIRM_REQUEST, &handleAutoEjectRequest }, { MSG_ID_FFU_SIGNAL_TD_UPDATE_AVAILABLE, &handleUpdateAvailable }, { MSG_ID_UI_FLUID_BOLUS_REQUEST, &handleFluidBolusRequest }, @@ -217,6 +218,7 @@ { MSG_ID_TD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE_REQUEST, &testSyringePumpADCReadCounterOverride }, { MSG_ID_TD_HEPARIN_BOLUS_TARGET_RATE_OVERRIDE_REQUEST, &testHeparinBolusTargetRateOverride }, { MSG_ID_TD_SYRINGE_PUMP_FORCE_SENSOR_CALIBRATION_REQUEST, &testCalibrateForceSensor }, + { MSG_ID_TD_GET_ALARM_PROPERTIES_REQUEST, &testGetAlarmPropertiesRequest }, }; /// Number of entries in the message handling function lookup table. Index: firmware/App/Services/StateServices/FluidBolus.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/FluidBolus.c (.../FluidBolus.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/StateServices/FluidBolus.c (.../FluidBolus.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file FluidBolus.c * * @author (last) Praneeth Bunne -* @date (last) 04-Jun-2026 +* @date (last) 02-Jul-2026 * * @author (original) Praneeth Bunne * @date (original) 04-Jun-2026 @@ -20,13 +20,15 @@ #include "DDInterface.h" #include "FluidBolus.h" #include "Messaging.h" -#include "Pressures.h" +#include "ModeStandby.h" #include "ModeTreatment.h" +#include "Pressures.h" #include "StateTxBloodPrime.h" #include "StateTxDialysis.h" #include "StateTxPaused.h" #include "TaskGeneral.h" #include "Timers.h" +#include "TubeSetInstall.h" #include "TxParams.h" #include "Valves.h" @@ -37,48 +39,32 @@ // ********** private definitions ********** -#define NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS 6U ///< Number of permitted alarms for fluid bolus from paused state. - static const U32 FLUID_BOLUS_DATA_PUB_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL); ///< Saline bolus data broadcast interval (ms/task time) count. // ********** private data ********** static FLUID_BOLUS_STATE_T currentFluidBolusState; ///< Current fluid bolus state -static FLUID_BOLUS_MEDIUM_T currentFluidBolusMedium; ///< Current fluid bolus medium +static FLUID_TYPE_T fluidType; ///< Fluid type for bolus static U32 fluidBolusBroadCastTimerCtr; ///< Broadcast Timer counter static BOOL fluidBolusStartRequested; ///< Flag indicates a fluid bolus start has been requested by user. static BOOL fluidBolusAbortRequested; ///< Flag indicates a fluid bolus abort has been requested by user. static BOOL pubBolusPermitted; ///< Flag indicates a bolus is permitted or not to UI (used to broadcast). +static BOOL newAlarmIndicateStop; ///< Flag indicating alarm with stop property is triggered. static U32 targetBloodFlowMLPM; ///< Blood pump flow rate (mL/min) to use for current bolus delivery. static F32 totalFluidVolumeDelivered_mL; ///< Volume (mL) in total of fluid delivered so far (cumulative for all boluses including current one). static F32 bolusFluidVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). static U32 bolusVolumeLastUpdateTimeStamp; ///< Time stamp for last bolus volume update. -// TODO: replace TRUE with getDialysateGoodToDeliverStatus() when we are ready -BOOL isDialysateGoodToDeliver = TRUE; ///< Flag indicating dialysate is good to deliver to the patient. - -///< Permitted alarm list-bolus allowed from paused state -static const ALARM_ID_T FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[ NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS ] = -{ - ALARM_ID_TD_TREATMENT_STOPPED_BY_USER, - ALARM_ID_TD_ARTERIAL_PRESSURE_HIGH, - ALARM_ID_TD_ARTERIAL_PRESSURE_LOW, - ALARM_ID_TD_VENOUS_PRESSURE_HIGH, - ALARM_ID_TD_TMP_PRESSURE_HIGH, - ALARM_ID_TD_TMP_PRESSURE_LOW -}; - // ********** private function prototypes ********** static void updateFluidBolusVolumeDelivered( void ); static void completeBolusToCumulative( void ); static FLUID_BOLUS_STATE_T handleFluidBolusIdleState( void ); static FLUID_BOLUS_STATE_T handleFluidBolusWait4Pumps2Stop( void ); -static FLUID_BOLUS_STATE_T handleFluidBolusSalineInProgressState( void ); -static FLUID_BOLUS_STATE_T handleFluidBolusSubstituteInProgressState( void ); +static FLUID_BOLUS_STATE_T handleFluidBolusInProgressState( void ); /*********************************************************************//** * @brief @@ -89,13 +75,14 @@ * @details \b Outputs: currentFluidBolusState, currentFluidBolusMedium, * fluidBolusBroadCastTimerCtr, targetBloodFlowMLPM, totalFluidVolumeDelivered_mL, * bolusFluidVolumeDelivered_mL, fluidBolusStartRequested, - * fluidBolusAbortRequested, bolusVolumeLastUpdateTimeStamp, pubBolusPermitted + * fluidBolusAbortRequested, bolusVolumeLastUpdateTimeStamp, pubBolusPermitted, + * newAlarmIndicateStop * @return none *************************************************************************/ void initFluidBolus( void ) { currentFluidBolusState = FLUID_BOLUS_IDLE_STATE; - currentFluidBolusMedium = getFluidBolusMedium(); + fluidType = getFluidType(); fluidBolusBroadCastTimerCtr = FLUID_BOLUS_DATA_PUB_INTERVAL - 10; // setup to stagger publish from other broadcasters targetBloodFlowMLPM = 0; totalFluidVolumeDelivered_mL = 0.0F; @@ -104,23 +91,24 @@ fluidBolusAbortRequested = FALSE; bolusVolumeLastUpdateTimeStamp = getMSTimerCount(); pubBolusPermitted = TRUE; + newAlarmIndicateStop = FALSE; } /*********************************************************************//** * @brief * The execFluidBolus function executes the fluid bolus state machine. - * @details \b Inputs: currentFluidBolusState - * @details \b Outputs: currentFluidBolusState + * @details \b Inputs: currentFluidBolusState, newAlarmIndicateStop + * @details \b Outputs: currentFluidBolusState, newAlarmIndicateStop * @return none *************************************************************************/ void execFluidBolus( void ) { FLUID_BOLUS_STATE_T priorState = currentFluidBolusState; // If alarm fires while bolus is active, abort the bolus - if ( ( TRUE == doesAlarmStatusIndicateStop() ) && ( TRUE == isFluidBolusActive() ) && - ( TREATMENT_PAUSED_STATE != getTreatmentState() ) ) + if ( ( TRUE == newAlarmIndicateStop ) && ( TRUE == isFluidBolusActive() ) ) { + newAlarmIndicateStop = FALSE; signalAbortFluidBolus(); } @@ -134,14 +122,10 @@ currentFluidBolusState = handleFluidBolusWait4Pumps2Stop(); break; - case FLUID_BOLUS_SALINE_IN_PROGRESS_STATE: - currentFluidBolusState = handleFluidBolusSalineInProgressState(); + case FLUID_BOLUS_IN_PROGRESS_STATE: + currentFluidBolusState = handleFluidBolusInProgressState(); break; - case FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE: - currentFluidBolusState = handleFluidBolusSubstituteInProgressState(); - break; - default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FLUID_BOLUS_STATE, currentFluidBolusState ) currentFluidBolusState = FLUID_BOLUS_IDLE_STATE; @@ -172,29 +156,6 @@ /*********************************************************************//** * @brief - * The getFluidBolusMedium function determines the fluid bolus medium based - * on the current treatment modality and online fluid configuration. - * Substitution fluid applies to HDF treatment, or HD treatment with online - * fluid enabled. Saline applies to standard HD without online fluid. - * @details \b Inputs: none - * @details \b Outputs: none - * @return FLUID_BOLUS_MEDIUM_SUBSTITUTE for HDF or HD-online, FLUID_BOLUS_MEDIUM_SALINE otherwise. - *************************************************************************/ -FLUID_BOLUS_MEDIUM_T getFluidBolusMedium( void ) -{ - FLUID_BOLUS_MEDIUM_T medium = FLUID_BOLUS_MEDIUM_SALINE; - U32 modality = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_MODALITY ); - - if ( ( modality == TREATMENT_MODALITY_HDF ) ) // || ( modality == TREATMENT_MODALITY_HD ) && ( check online fluid enabled ) - { - medium = FLUID_BOLUS_MEDIUM_SUBSTITUTE; - } - - return medium; -} - -/*********************************************************************//** - * @brief * The isFluidBolusActive function determines whether a fluid bolus is * currently being delivered. * @details \b Inputs: currentFluidBolusState @@ -298,7 +259,8 @@ * The handleFluidBolusIdleState function handles the idle state of the * fluid bolus state machine. * @details \b Inputs: fluidBolusStartRequested - * @details \b Outputs: fluidBolusStartRequested, bolusVolumeLastUpdateTimeStamp + * @details \b Outputs: fluidBolusStartRequested, bolusVolumeLastUpdateTimeStamp, + * newAlarmIndicateStop * @return next fluid bolus state *************************************************************************/ static FLUID_BOLUS_STATE_T handleFluidBolusIdleState( void ) @@ -309,6 +271,8 @@ if ( TRUE == fluidBolusStartRequested ) { fluidBolusStartRequested = FALSE; + // Clear when alarm is triggered and can be set when new alarm is triggered. + newAlarmIndicateStop = FALSE; // Stop blood pump signalBloodPumpHardStop(); // Stop substitution pump @@ -349,93 +313,67 @@ setValvePosition( H1_VALV, VALVE_POSITION_C_CLOSE ); setValvePosition( H19_VALV, VALVE_POSITION_B_OPEN ); - if ( FLUID_BOLUS_MEDIUM_SALINE == currentFluidBolusMedium ) + if ( FLUID_TYPE_SALINE == fluidType ) { setBloodPumpTargetFlowRate( targetBloodFlowMLPM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - state = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; } - else if ( TRUE == isDialysateGoodToDeliver ) + else { // set D92 flow rate cmdSubstitutionRate( (F32)targetBloodFlowMLPM ); - state = FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE; } - else - { - state = FLUID_BOLUS_IDLE_STATE; - } + + state = FLUID_BOLUS_IN_PROGRESS_STATE; } return state; } /*********************************************************************//** * @brief - * The handleFluidBolusSalineInProgressState function handles the saline - * in-progress state of the fluid bolus state machine. Integrates delivered - * volume from measured blood flow, fires an alarm if the saline bag is empty, - * and completes the bolus when the target volume is reached or an abort is requested. - * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested + * The handleFluidBolusInProgressState function handles the in-progress + * state of the fluid bolus state machine. Integrates delivered volume from + * measured flow rate every tick. For saline medium, fires an alarm if the + * saline bag is empty. For substitution medium, aborts if dialysate is no + * longer good to deliver. Completes the bolus when the target volume is + * reached or an abort is requested. + * @details \b Alarms: ALARM_ID_TD_EMPTY_SALINE_BAG if saline bag is empty or + * saline line is clamped. + * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested, + * currentFluidBolusMedium * @details \b Outputs: fluidBolusAbortRequested * @return next fluid bolus state *************************************************************************/ -static FLUID_BOLUS_STATE_T handleFluidBolusSalineInProgressState( void ) +static FLUID_BOLUS_STATE_T handleFluidBolusInProgressState( void ) { - FLUID_BOLUS_STATE_T state = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); + FLUID_BOLUS_STATE_T state = FLUID_BOLUS_IN_PROGRESS_STATE; + F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); updateFluidBolusVolumeDelivered(); - // Check for empty saline bag per arterial line pressure - if ( TRUE == isSalineBagEmpty() ) + if ( FLUID_TYPE_SALINE == fluidType ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_EMPTY_SALINE_BAG, getFilteredArterialPressure() ); - state = FLUID_BOLUS_IDLE_STATE; + // Check for empty saline bag per arterial line pressure + if ( TRUE == isSalineBagEmpty() ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_TD_EMPTY_SALINE_BAG, getFilteredArterialPressure() ); + state = FLUID_BOLUS_IDLE_STATE; + } } - // Determine if bolus is complete or stopped by user - else if ( ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) ) - { - fluidBolusAbortRequested = FALSE; - state = FLUID_BOLUS_IDLE_STATE; - } else { - // No action required + if ( FALSE == getDialysateGoodToDeliverStatus() ) + { + state = FLUID_BOLUS_IDLE_STATE; + } } - // Bolus ended, stop blood pump and record delivered volume - if ( state != FLUID_BOLUS_SALINE_IN_PROGRESS_STATE ) + // Bolus ended or target volume reached or aborted, stop delivery and record volume. + if ( ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) || + ( FLUID_BOLUS_IDLE_STATE == state ) ) { - signalBloodPumpHardStop(); - completeBolusToCumulative(); - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleFluidBolusSubstituteInProgressState function handles the - * substitute in-progress state state of the fluid bolus state machine. - * Integrates delivered volume from measured blood flow. Monitors dialysate - * readiness every tick, aborts if dialysate is no longer good to deliver. - * Completes the bolus when target is reached or an abort is requested. - * @details \b Inputs: bolusFluidVolumeDelivered_mL, fluidBolusAbortRequested - * @details \b Outputs: fluidBolusAbortRequested, - * totalFluidVolumeDelivered_mL via completeBolusToCumulative() - * @return next fluid bolus state. - *************************************************************************/ -static FLUID_BOLUS_STATE_T handleFluidBolusSubstituteInProgressState( void ) -{ - FLUID_BOLUS_STATE_T state = FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE; - F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_FLUID_BOLUS_VOLUME ); - - updateFluidBolusVolumeDelivered(); - - // Check for dialysate, target volume delivered or abort from user - if ( ( FALSE == isDialysateGoodToDeliver ) || ( bolusFluidVolumeDelivered_mL >= bolusTargetVolume ) || ( TRUE == fluidBolusAbortRequested ) ) - { fluidBolusAbortRequested = FALSE; + signalBloodPumpHardStop(); cmdSubstitutionRate( 0.0F ); completeBolusToCumulative(); state = FLUID_BOLUS_IDLE_STATE; @@ -476,58 +414,6 @@ } /*********************************************************************//** - * @brief - * The isBolusAllowedByActiveAlarms function checks whether all - * currently active alarms permit a fluid bolus from the paused state. - * For saline medium, a non-permitted alarm blocks the bolus only if it is - * TD source. For substitute medium, any non-permitted alarm blocks the bolus. - * @details \b Inputs: FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[], currentFluidBolusMedium - * @details \b Outputs: none - * @return TRUE if all active alarms permit the bolus, FALSE otherwise. - *************************************************************************/ -BOOL isBolusAllowedByActiveAlarms( void ) -{ - U32 alarm; - U32 permittedIndex; - BOOL permitted = FALSE; - BOOL result = TRUE; - - for ( alarm = 0; alarm < NUM_OF_ALARM_IDS; alarm++ ) - { - if ( TRUE == isAlarmActive( alarm ) ) - { - for ( permittedIndex = 0; permittedIndex < NUM_OF_FLUID_BOLUS_PERMITTED_ALARMS; permittedIndex++ ) - { - if ( FLUID_BOLUS_PERMITTED_PAUSED_ALARMS[ permittedIndex ] == alarm ) - { - permitted = TRUE; - break; - } - } - - if ( FALSE == permitted ) - { - if ( FLUID_BOLUS_MEDIUM_SALINE == currentFluidBolusMedium ) - { - if ( ALM_SRC_TD == getAlarmSource( alarm ) ) - { - result = FALSE; - break; - } - } - else - { - result = FALSE; - break; - } - } - } - } - - return result; -} - -/*********************************************************************//** * @brief * The handleFluidBolusRequest function handles the UI fluid bolus request. * @details \b Message \b Sent: MSG_ID_TD_FLUID_BOLUS_RESPONSE @@ -553,18 +439,6 @@ // TD Fluid Bolus Additional Bolus Prevention rejReason = REQUEST_REJECT_REASON_FLUID_BOLUS_IN_PROGRESS; } - else if ( TREATMENT_PAUSED_STATE == getTreatmentState() ) - { - if ( ( TRUE == isBolusAllowedByActiveAlarms() ) ) - { - result = signalPauseTreatFluidBolusRequest(); - rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; - } - else - { - rejReason = REQUEST_REJECT_REASON_ALARM_IS_ACTIVE; - } - } else { // Route to whichever calling state is currently active @@ -580,6 +454,11 @@ rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; break; + case TREATMENT_PAUSED_STATE: + result = signalPauseTreatFluidBolusRequest(); + rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; + break; + // case TREATMENT_HDF_STATE: // result = signalHdfFluidBolusRequest(); // rejReason = ( result == TRUE ) ? REQUEST_REJECT_REASON_NONE : REQUEST_REJECT_REASON_INVALID_TREATMENT_SUB_STATE; @@ -632,4 +511,17 @@ return result; } +/*********************************************************************//** + * @brief + * The signalNewStopAlarmActivated function is called by the alarm system + * when an alarm with the stop property is activated. + * @details \b Inputs: none + * @details \b Outputs: newAlarmIndicateStop + * @return none + *************************************************************************/ +void signalNewStopAlarmActivated( void ) +{ + newAlarmIndicateStop = TRUE; +} + /**@}*/ Index: firmware/App/Services/StateServices/FluidBolus.h =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/FluidBolus.h (.../FluidBolus.h) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/StateServices/FluidBolus.h (.../FluidBolus.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file FluidBolus.h * * @author (last) Praneeth Bunne -* @date (last) 04-Jun-2026 +* @date (last) 26-Jun-2026 * * @author (original) Praneeth Bunne * @date (original) 04-Jun-2026 @@ -52,23 +52,22 @@ } FLUID_BOLUS_DATA_PAYLOAD_T; #pragma pack(pop) -// ********** public definitions ********** +// ********** public function prototypes ********** void initFluidBolus( void ); void publishFluidBolusData( void ); void execFluidBolus( void ); void setBolusPermitted( BOOL permitted ); FLUID_BOLUS_STATE_T getCurrentFluidBolusState( void ); -FLUID_BOLUS_MEDIUM_T getFluidBolusMedium( void ); BOOL isFluidBolusActive( void ); void signalStartFluidBolus( U32 flowRate ); void signalAbortFluidBolus( void ); F32 getTotalFluidBolusVolumeDelivered( void ); BOOL handleFluidBolusRequest( MESSAGE_T *message ); -BOOL isBolusAllowedByActiveAlarms( void ); +void signalNewStopAlarmActivated( void ); /**@}*/ Index: firmware/App/Services/StateServices/TubeSetAutoEject.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/TubeSetAutoEject.c (.../TubeSetAutoEject.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/StateServices/TubeSetAutoEject.c (.../TubeSetAutoEject.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file TubeSetAutoEject.c * * @author (last) Praneeth Bunne -* @date (last) 04-Jun-2026 +* @date (last) 11-Jun-2026 * * @author (original) Praneeth Bunne * @date (original) 01-May-2026 @@ -124,8 +124,8 @@ if ( previousAutoEjectState != currentAutoEjectState ) { - previousAutoEjectState = currentAutoEjectState; SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, previousAutoEjectState, currentAutoEjectState ); + previousAutoEjectState = currentAutoEjectState; } } Index: firmware/App/Services/StateServices/TubeSetAutoEject.h =================================================================== diff -u -r9cc543b1c2508280767573e20eddd94e68be1fb5 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/TubeSetAutoEject.h (.../TubeSetAutoEject.h) (revision 9cc543b1c2508280767573e20eddd94e68be1fb5) +++ firmware/App/Services/StateServices/TubeSetAutoEject.h (.../TubeSetAutoEject.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file TubeSetAutoEject.h * * @author (last) Praneeth Bunne -* @date (last) 12-May-2026 +* @date (last) 12-Jun-2026 * * @author (original) Praneeth Bunne * @date (original) 01-May-2026 @@ -35,14 +35,14 @@ /// Enumeration of Tube Set Auto-Eject states. enum Tube_Set_Auto_Eject_States { - TUBE_SET_AUTO_EJECT_STATE_AWAIT_CONFIRMATION = 0, // Waiting for user confirmation to auto-eject - TUBE_SET_AUTO_EJECT_STATE_HOMING, // Homing blood pump - TUBE_SET_AUTO_EJECT_STATE_EXTENDING_EJECTOR, // Extending ejector state - TUBE_SET_AUTO_EJECT_STATE_EJECTING, // Ejecting tubeset state - TUBE_SET_AUTO_EJECT_STATE_RETRACTING_EJECTOR, // Retracting ejector state - TUBE_SET_AUTO_EJECT_STATE_BACK_OFF, // Auto-Eject Back-off state - TUBE_SET_AUTO_EJECT_STATE_COMPLETE, // Auto-Eject complete state - NUM_OF_TUBE_SET_AUTO_EJECT_SUB_STATES, // Num of auto-eject sub-states + TUBE_SET_AUTO_EJECT_STATE_AWAIT_CONFIRMATION = 0, ///< Waiting for user confirmation to auto-eject + TUBE_SET_AUTO_EJECT_STATE_HOMING, ///< Homing blood pump + TUBE_SET_AUTO_EJECT_STATE_EXTENDING_EJECTOR, ///< Extending ejector state + TUBE_SET_AUTO_EJECT_STATE_EJECTING, ///< Ejecting tubeset state + TUBE_SET_AUTO_EJECT_STATE_RETRACTING_EJECTOR, ///< Retracting ejector state + TUBE_SET_AUTO_EJECT_STATE_BACK_OFF, ///< Auto-Eject Back-off state + TUBE_SET_AUTO_EJECT_STATE_COMPLETE, ///< Auto-Eject complete state + NUM_OF_TUBE_SET_AUTO_EJECT_SUB_STATES, ///< Num of auto-eject sub-states }; /// Type for TD Tube Set Auto-Eject service enumeration typedef enum Tube_Set_Auto_Eject_States TUBE_SET_AUTO_EJECT_STATE_T; @@ -53,7 +53,7 @@ void execTubeSetAutoEject( void ); // Execute the service state machine (call from ModePostTreat and ModeTreatment) BOOL isTubeSetAutoEjectComplete( void ); // Returns True once auto-eject finished successfully -BOOL handleAutoEjectRequest( MESSAGE_T *message ); // Handle UI auto-eject confirmation request +BOOL handleAutoEjectRequest( MESSAGE_T *message ); // Handle UI auto-eject confirmation request /**@}*/ Index: firmware/App/Services/StateServices/TubeSetInstall.c =================================================================== diff -u -r9c833ef5623ce842267e284d958820ac0dc3a7fc -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/TubeSetInstall.c (.../TubeSetInstall.c) (revision 9c833ef5623ce842267e284d958820ac0dc3a7fc) +++ firmware/App/Services/StateServices/TubeSetInstall.c (.../TubeSetInstall.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file TubeSetInstall.c * * @author (last) Praneeth Bunne -* @date (last) 04-Jun-2026 +* @date (last) 26-Jun-2026 * * @author (original) Praneeth Bunne * @date (original) 01-May-2026 @@ -17,6 +17,7 @@ #include "AlarmMgmtTD.h" #include "BloodFlow.h" +#include "DDInterface.h" #include "Messaging.h" #include "OperationModes.h" #include "PeristalticPump.h" @@ -25,6 +26,7 @@ #include "TDDefs.h" #include "Timers.h" #include "TubeSetInstall.h" +#include "TxParams.h" /** * @addtogroup TubeSetInstall @@ -42,20 +44,24 @@ // ********** private data ********** static BOOL confirmTubesetPlaced; ///< Flag indicating user has confirmed tubeset is placed +static BOOL setupConnectionsConfirmed; ///< Flag indicating user has confirmed setup connections are complete. static U32 bloodPumpTimerCounter; ///< Blood Pump timer counter static BOOL bpLastHome; ///< Flag for blood pump last home (for rising-edge) static U32 bpLeftHomeTimerCounter; ///< Timer counter to measure how long BP has been away from home static TUBE_SET_INSTALL_STATE_T previousInstallState; ///< Previous tube set install sub-state static TUBE_SET_INSTALL_STATE_T currentInstallState; ///< Current tubing set install sub-state +static TUBE_SET_TYPE_T currentTubeSetType; ///< Current installed tube set type + // ********** private function prototypes ********** -static TUBE_SET_INSTALL_STATE_T handleAwaitTubesetConfirmationState( void ); ///< Handle Await Tubset Install Confirmation sub-state -static TUBE_SET_INSTALL_STATE_T handleAwaitBPDoorCloseState( void ); ///< Handle Await Blood Pump Door Close sub-state. -static TUBE_SET_INSTALL_STATE_T handleAutoLoadState( void ); ///< Handle Auto-Load sub-state -static TUBE_SET_INSTALL_STATE_T handleAutoLoadBackOffState( void ); ///< Handle Auto-Load Back-off sub-state -static TUBE_SET_INSTALL_STATE_T handleInstallCompleteState( void ); ///< Handle Install complete state +static TUBE_SET_INSTALL_STATE_T handleAwaitTubesetConfirmationState( void ); ///< Handle Await Tubset Install Confirmation sub-state +static TUBE_SET_INSTALL_STATE_T handleAwaitBPDoorCloseState( void ); ///< Handle Await Blood Pump Door Close sub-state. +static TUBE_SET_INSTALL_STATE_T handleAutoLoadState( void ); ///< Handle Auto-Load sub-state +static TUBE_SET_INSTALL_STATE_T handleAwaitSetupConnectionConfirmationState( void ); ///< Handle Await Setup Connection Confirmation sub-state +static TUBE_SET_INSTALL_STATE_T handleAutoLoadBackOffState( void ); ///< Handle Auto-Load Back-off sub-state +static TUBE_SET_INSTALL_STATE_T handleInstallCompleteState( void ); ///< Handle Install complete state /*********************************************************************//** * @brief @@ -67,12 +73,14 @@ **************************************************************************/ void initTubeSetInstall( void ) { - previousInstallState = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; - currentInstallState = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; - confirmTubesetPlaced = FALSE; - bloodPumpTimerCounter = 0; - bpLastHome = TRUE; - bpLeftHomeTimerCounter = 0; + previousInstallState = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; + currentInstallState = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; + confirmTubesetPlaced = FALSE; + setupConnectionsConfirmed = FALSE; + bloodPumpTimerCounter = 0; + bpLastHome = TRUE; + bpLeftHomeTimerCounter = 0; + currentTubeSetType = TUBE_SET_TYPE_UNKNOWN; } /*********************************************************************//** @@ -104,6 +112,10 @@ currentInstallState = handleAutoLoadBackOffState(); break; + case TUBE_SET_INSTALL_STATE_AWAIT_SETUP_CONNECTION_CONFIRMATION: + currentInstallState = handleAwaitSetupConnectionConfirmationState(); + break; + case TUBE_SET_INSTALL_STATE_COMPLETE: currentInstallState = handleInstallCompleteState(); break; @@ -115,8 +127,8 @@ if ( previousInstallState != currentInstallState ) { - previousInstallState = currentInstallState; SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_SUB_STATE_CHANGE, previousInstallState, currentInstallState ); + previousInstallState = currentInstallState; } } @@ -132,11 +144,24 @@ static TUBE_SET_INSTALL_STATE_T handleAwaitTubesetConfirmationState( void ) { TUBE_SET_INSTALL_STATE_T state = TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION; + F32 bicarbConvFactor = BICARBONATE_CONVERSION_FACTOR; if ( TRUE == confirmTubesetPlaced ) { // Door closed required from Auto-loading onwards, set to false if not required in subsequent states doorClosedRequired( TRUE ); + + // Request DD to generate dialysate with Qd = 600 mL/min, + // Quf = 0, and dialyzer bypassed. + cmdStartGenerateDialysate( 600.0F, + 0.0F, + getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ), + TRUE, + getTreatmentParameterF32( TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR ), + bicarbConvFactor, + getTreatmentParameterU32( TREATMENT_PARAM_SODIUM ), + getTreatmentParameterU32( TREATMENT_PARAM_BICARBONATE ) ); + confirmTubesetPlaced = FALSE; state = TUBE_SET_INSTALL_STATE_AWAIT_BP_DOOR_CLOSE; } @@ -204,7 +229,7 @@ signalBloodPumpHardStop(); bloodPumpTimerCounter = 0; bpLeftHomeTimerCounter = 0; - state = TUBE_SET_INSTALL_STATE_COMPLETE; + state = TUBE_SET_INSTALL_STATE_AWAIT_SETUP_CONNECTION_CONFIRMATION; } else { @@ -223,6 +248,28 @@ /*********************************************************************//** * @brief + * The handleAwaitSetupConnectionConfirmationState function handles the + * Await Setup Connection Confirmation state of Tube Set install state. + * @details \b Inputs: setupConnectionsConfirmed + * @details \b Outputs: setupConnectionsConfirmed + * @return next Install sub-state + *************************************************************************/ +static TUBE_SET_INSTALL_STATE_T handleAwaitSetupConnectionConfirmationState( void ) +{ + TUBE_SET_INSTALL_STATE_T state = TUBE_SET_INSTALL_STATE_AWAIT_SETUP_CONNECTION_CONFIRMATION; + + if ( TRUE == setupConnectionsConfirmed ) + { + setupConnectionsConfirmed = FALSE; + + state = TUBE_SET_INSTALL_STATE_COMPLETE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleAutoLoadBackOffState function handles the Auto-Load Back-Off * state of Tube Set install state. * @details \b Inputs: bloodPumpTimerCounter @@ -332,4 +379,113 @@ return result; } +/*********************************************************************//** + * @brief + * The handleSetupTubingSetConnectionConfirmRequest function handles a UI request + * to confirm setup connections are complete. + * @details \b Message \b Sent: MSG_ID_TD_SETUP_TUBING_SET_CONNECTIONS_CONFIRM_RESPONSE + * @details \b Inputs: none + * @details \b Outputs: setupConnectionsConfirmed + * @param message UI message which includes the user confirmation of + * setup connections completion. + * @return TRUE if confirmation accepted, FALSE otherwise. + *************************************************************************/ +BOOL handleSetupTubingSetConnectionConfirmRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + UI_RESPONSE_PAYLOAD_T response; + + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + if ( 0 == message->hdr.payloadLen ) + { + if ( TUBE_SET_INSTALL_STATE_COMPLETE != currentInstallState ) + { + setupConnectionsConfirmed = TRUE; + result = TRUE; + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } + + response.accepted = result; + + sendMessage( MSG_ID_TD_SETUP_TUBING_SET_CONNECTIONS_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)&response, sizeof( UI_RESPONSE_PAYLOAD_T ) ); + + return result; +} + +/*********************************************************************//** +* The setTubeSetType function sets the current installed tube set type. + * @details \b Alarms: ALARM_ID_TD_SOFTWARE_FAULT if tube set is invalid type + * @details \b Inputs: none + * @details \b Outputs: currentTubeSetType + * @param type Tube set type determined from barcode scan. + * @return none + *************************************************************************/ +void setTubeSetType( TUBE_SET_TYPE_T type ) +{ + if ( type < NUM_OF_TUBE_SET_TYPES ) + { + currentTubeSetType = type; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TUBE_SET_TYPE, (U32)type ); + } +} + +/*********************************************************************//** + * @brief + * The getTubeSetType function returns the current installed tube set type. + * @details \b Inputs: currentTubeSetType + * @details \b Outputs: none + * @return Current installed tube set type. + *************************************************************************/ +TUBE_SET_TYPE_T getTubeSetType( void ) +{ + return currentTubeSetType; +} + +/*********************************************************************//** + * @brief + * The validateTubeSetType function validates the current installed tube set type + * based on modality. + * @details \b Alarm: + * @details \b Inputs: none + * @details \b Outputs: none + * @return none. + *************************************************************************/ +void validateTubeSetType( void ) +{ + U32 modality = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_MODALITY ); + BOOL misMatch = FALSE; + + if ( TREATMENT_MODALITY_HDF_ONLINE_FLUID == modality ) + { + if ( TUBE_SET_TYPE_HDF != currentTubeSetType ) + { + misMatch = TRUE; + } + } + else + { + if ( TREATMENT_MODALITY_HD_SALINE_FLUID != currentTubeSetType ) + { + misMatch = TRUE; + } + } + + if ( TRUE == misMatch ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_TUBE_SET_MISMATCH, modality, (U32)currentTubeSetType ); + } +} + /**@}*/ Index: firmware/App/Services/StateServices/TubeSetInstall.h =================================================================== diff -u -r9cc543b1c2508280767573e20eddd94e68be1fb5 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/StateServices/TubeSetInstall.h (.../TubeSetInstall.h) (revision 9cc543b1c2508280767573e20eddd94e68be1fb5) +++ firmware/App/Services/StateServices/TubeSetInstall.h (.../TubeSetInstall.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -8,7 +8,7 @@ * @file TubeSetInstall.h * * @author (last) Praneeth Bunne -* @date (last) 04-May-2026 +* @date (last) 26-Jun-2026 * * @author (original) Praneeth Bunne * @date (original) 01-May-2026 @@ -32,12 +32,13 @@ // ********** public definitions ********** -/// Enumeration of Tube Set install sub-states. +/// Enumeration of Tube Set install sub-states. enum Tube_Set_Install_States { TUBE_SET_INSTALL_STATE_AWAIT_TUBE_SET_CONFIRMATION = 0, // Awaiting user confirmation that tubeset is placed. TUBE_SET_INSTALL_STATE_AWAIT_BP_DOOR_CLOSE, // Waiting for blood pump door to be closed. TUBE_SET_INSTALL_STATE_AUTO_LOAD, // Auto-Load the tubeset state + TUBE_SET_INSTALL_STATE_AWAIT_SETUP_CONNECTION_CONFIRMATION, // Awaiting user confirmation that setup connections are complete. TUBE_SET_INSTALL_STATE_AUTO_LOAD_BACK_OFF, // Auto-Load Back-off state TUBE_SET_INSTALL_STATE_COMPLETE, // Install state complete NUM_OF_TUBE_SET_INSTALL_SUB_STATES, // Num of install sub-states @@ -47,12 +48,17 @@ // ********** public function prototypes ********** -void initTubeSetInstall( void ); // Initialize this service -void execTubeSetInstall( void ); // Execute the service state machine (call from ModePreTreat and ModeTreatment) +void initTubeSetInstall( void ); // Initialize this service +void execTubeSetInstall( void ); // Execute the service state machine (call from ModePreTreat and ModeTreatment) -BOOL isTubeSetInstallComplete( void ); // Returns True once auto-load finished successfully -BOOL handleAutoLoadRequest( MESSAGE_T *message ); // Handle UI auto-load confirmation request +BOOL isTubeSetInstallComplete( void ); // Returns True once auto-load finished successfully +BOOL handleAutoLoadRequest( MESSAGE_T *message ); // Handle UI auto-load confirmation request +BOOL handleSetupTubingSetConnectionConfirmRequest( MESSAGE_T *message ); // Handle UI setup tubing set connection confirmation request +void setTubeSetType( TUBE_SET_TYPE_T type ); // Set the current installed tube set type TODO: Call this after implementing bar code logic +TUBE_SET_TYPE_T getTubeSetType( void ); // Get the current installed tube set type +void validateTubeSetType( void ); // Validate tube set type with the modality TODO: call this after implementing bar code logic and setting the tube set type + /**@}*/ #endif Index: firmware/App/Services/SystemCommTD.c =================================================================== diff -u -rf8a6d0d2b55d834e1e25ec98370e538ff547e148 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/SystemCommTD.c (.../SystemCommTD.c) (revision f8a6d0d2b55d834e1e25ec98370e538ff547e148) +++ firmware/App/Services/SystemCommTD.c (.../SystemCommTD.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,42 +7,42 @@ * * @file SystemCommTD.c * -* @author (last) Dara Navaei -* @date (last) 06-Mar-2026 +* @author (last) Praneeth Bunne +* @date (last) 12-Jun-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 * ***************************************************************************/ - -#include // For memcpy() - -#include "can.h" -#include "sci.h" -#include "sys_dma.h" - -#include "Comm.h" + +#include // For memcpy() + +#include "can.h" +#include "sci.h" +#include "sys_dma.h" + +#include "Comm.h" #include "Interrupts.h" -#include "Messaging.h" +#include "Messaging.h" #include "OperationModes.h" #include "SystemCommTD.h" -#include "Timers.h" -#include "Utilities.h" - +#include "Timers.h" +#include "Utilities.h" + /** * @addtogroup SystemCommTD * @{ */ -// ********** private definitions ********** - +// ********** private definitions ********** + #define UI_COMM_TIMEOUT_IN_MS 7500 ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD. -#define UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS (2 * SEC_PER_MIN * MS_PER_SECOND) ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD when in service mode. -#define DG_COMM_TIMEOUT_IN_MS 1000 ///< DG has not checked in for this much time - -#define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm -#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window - +#define UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS (2 * SEC_PER_MIN * MS_PER_SECOND) ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD when in service mode. +#define DG_COMM_TIMEOUT_IN_MS 1000 ///< DG has not checked in for this much time + +#define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm +#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window + #define MAX_FPGA_CLOCK_SPEED_ERRORS 3 ///< maximum number of FPGA clock speed errors within window period before alarm #define MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< FPGA clock speed error window @@ -70,122 +70,122 @@ COMM_BUFFER_IN_CAN_PC, }; -// ********** private data ********** - +// ********** private data ********** + static volatile BOOL tdIsOnlyCANNode = TRUE; ///< Flag indicating whether HD is alone on CAN bus. -static volatile BOOL ddIsCommunicating = FALSE; ///< Has DD sent a message since last check -static U32 timeOfLastDDCheckIn = 0; ///< Last time DD checked in -static volatile BOOL uiIsCommunicating = FALSE; ///< Has UI sent a message since last check -static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in +static volatile BOOL ddIsCommunicating = FALSE; ///< Has DD sent a message since last check +static U32 timeOfLastDDCheckIn = 0; ///< Last time DD checked in +static volatile BOOL uiIsCommunicating = FALSE; ///< Has UI sent a message since last check +static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in static volatile BOOL uiDidCommunicate = FALSE; ///< Has UI every sent a message - -// ********** private function prototypes ********** - - -/*********************************************************************//** - * @brief + +// ********** private function prototypes ********** + + +/*********************************************************************//** + * @brief * The initSystemCommTD function initializes the system communication unit - * for the TD firmware. - * @details \b Inputs: none - * @details \b Outputs: SystemComm unit initialized. - * @return none - *************************************************************************/ -void initSystemCommTD( void ) + * for the TD firmware. + * @details \b Inputs: none + * @details \b Outputs: SystemComm unit initialized. + * @return none + *************************************************************************/ +void initSystemCommTD( void ) { // Initialize common system comm unit initSystemComm(); - + // Initialize bad message CRC time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC, MAX_COMM_CRC_FAILURES, MAX_COMM_CRC_FAILURE_WINDOW_MS ); // Initialize FPGA clock speed error time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR, MAX_FPGA_CLOCK_SPEED_ERRORS, MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS); -} - -/*********************************************************************//** - * @brief - * The checkInFromDD function checks in the DD with the TD - indicating that - * the DD is communicating. - * @details \b Inputs: none - * @details \b Outputs: ddIsCommunicating, timeOfLastDDCheckIn - * @return none - *************************************************************************/ -void checkInFromDD( void ) -{ - ddIsCommunicating = TRUE; +} + +/*********************************************************************//** + * @brief + * The checkInFromDD function checks in the DD with the TD - indicating that + * the DD is communicating. + * @details \b Inputs: none + * @details \b Outputs: ddIsCommunicating, timeOfLastDDCheckIn + * @return none + *************************************************************************/ +void checkInFromDD( void ) +{ + ddIsCommunicating = TRUE; timeOfLastDDCheckIn = getMSTimerCount(); if ( TRUE == isAlarmActive( ALARM_ID_TD_DD_COMM_TIMEOUT ) ) { clearAlarmCondition( ALARM_ID_TD_DD_COMM_TIMEOUT ); - } -} - -/*********************************************************************//** - * @brief - * The checkInFromUI function checks in the UI with the TD - indicating that - * the UI is communicating. - * @details \b Inputs: none - * @details \b Outputs: uiIsCommunicating, timeOfLastUICheckIn, uiDidCommunicate - * @return none - *************************************************************************/ -void checkInFromUI( void ) -{ + } +} + +/*********************************************************************//** + * @brief + * The checkInFromUI function checks in the UI with the TD - indicating that + * the UI is communicating. + * @details \b Inputs: none + * @details \b Outputs: uiIsCommunicating, timeOfLastUICheckIn, uiDidCommunicate + * @return none + *************************************************************************/ +void checkInFromUI( void ) +{ if ( FALSE == uiDidCommunicate ) { // Start DD check-in timer when UI first communicates timeOfLastDDCheckIn = getMSTimerCount(); } - - uiIsCommunicating = TRUE; - timeOfLastUICheckIn = getMSTimerCount(); - uiDidCommunicate = TRUE; -} - -/*********************************************************************//** - * @brief - * The isDDCommunicating function determines whether the DD is communicating - * with the TD. - * @details \b Inputs: ddIsCommunicating - * @details \b Outputs: none - * @return TRUE if DD is communicating, FALSE if not - *************************************************************************/ -BOOL isDDCommunicating( void ) -{ - return ddIsCommunicating; -} - -/*********************************************************************//** - * @brief - * The isUICommunicating function determines whether the UI is communicating - * with the TD. - * @details \b Inputs: uiIsCommunicating - * @details \b Outputs: uiIsCommunicating - * @return TRUE if UI has checked in since last call, FALSE if not - *************************************************************************/ -BOOL isUICommunicating( void ) -{ - BOOL result = uiIsCommunicating; - - uiIsCommunicating = FALSE; - - return result; -} - -/*********************************************************************//** - * @brief + + uiIsCommunicating = TRUE; + timeOfLastUICheckIn = getMSTimerCount(); + uiDidCommunicate = TRUE; +} + +/*********************************************************************//** + * @brief + * The isDDCommunicating function determines whether the DD is communicating + * with the TD. + * @details \b Inputs: ddIsCommunicating + * @details \b Outputs: none + * @return TRUE if DD is communicating, FALSE if not + *************************************************************************/ +BOOL isDDCommunicating( void ) +{ + return ddIsCommunicating; +} + +/*********************************************************************//** + * @brief + * The isUICommunicating function determines whether the UI is communicating + * with the TD. + * @details \b Inputs: uiIsCommunicating + * @details \b Outputs: uiIsCommunicating + * @return TRUE if UI has checked in since last call, FALSE if not + *************************************************************************/ +BOOL isUICommunicating( void ) +{ + BOOL result = uiIsCommunicating; + + uiIsCommunicating = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief * The uiCommunicated function determines whether the UI has started communicating - * since power up. - * @details \b Inputs: uiDidCommunicate - * @details \b Outputs: none - * @return TRUE if UI has communicated since power up, FALSE if not - *************************************************************************/ -BOOL uiCommunicated( void ) + * since power up. + * @details \b Inputs: uiDidCommunicate + * @details \b Outputs: none + * @return TRUE if UI has communicated since power up, FALSE if not + *************************************************************************/ +BOOL uiCommunicated( void ) { #ifdef TEST_PROCESS_TASKS_WO_UI uiDidCommunicate = TRUE; #endif - return uiDidCommunicate; + return uiDidCommunicate; } /*********************************************************************//** @@ -213,8 +213,8 @@ void setOnlyCANNode( BOOL only ) { tdIsOnlyCANNode = only; -} - +} + /*********************************************************************//** * @brief * The clearCANXmitBuffers function clears all CAN transmit buffers. @@ -232,34 +232,34 @@ } } -/*********************************************************************//** - * @brief - * The checkForCommTimeouts function checks for sub-system communication +/*********************************************************************//** + * @brief + * The checkForCommTimeouts function checks for sub-system communication * timeout errors. * @details \b Alarm: ALARM_ID_TD_UI_COMM_TIMEOUT if UI no longer communicating. - * @details \b Alarm: ALARM_ID_TD_DD_COMM_TIMEOUT if DD no longer communicating. - * @details \b Inputs: timeOfLastDDCheckIn, timeOfLastUICheckIn - * @details \b Outputs: none - * @return none - *************************************************************************/ -void checkForCommTimeouts( void ) -{ - if ( TRUE == uiDidCommunicate ) + * @details \b Alarm: ALARM_ID_TD_DD_COMM_TIMEOUT if DD no longer communicating. + * @details \b Inputs: timeOfLastDDCheckIn, timeOfLastUICheckIn + * @details \b Outputs: none + * @return none + *************************************************************************/ +void checkForCommTimeouts( void ) +{ + if ( TRUE == uiDidCommunicate ) { TD_OP_MODE_T opMode = getCurrentOperationMode(); U32 uiTO_MS = ( MODE_SERV == opMode ? UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS : UI_COMM_TIMEOUT_IN_MS ); - if ( TRUE == didTimeout( timeOfLastUICheckIn, uiTO_MS ) ) + if ( TRUE == didTimeout( timeOfLastUICheckIn, uiTO_MS ) ) { #ifndef _RELEASE_ // if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_COMM_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif - { + { #ifndef TEST_DISABLE_UI_ALARMS activateAlarmNoData( ALARM_ID_TD_UI_COMM_TIMEOUT ); #endif } - } + } if ( TRUE == didTimeout( timeOfLastDDCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) { @@ -353,21 +353,21 @@ return result; -} - -/*********************************************************************//** - * @brief - * The processReceivedMessage function processes a given message. - * @details \b Inputs: none - * @details \b Outputs: message processed - * @param message Pointer to the message to process. - * @return none - *************************************************************************/ -void processReceivedMessage( MESSAGE_T *message ) -{ +} + +/*********************************************************************//** + * @brief + * The processReceivedMessage function processes a given message. + * @details \b Inputs: none + * @details \b Outputs: message processed + * @param message Pointer to the message to process. + * @return none + *************************************************************************/ +void processReceivedMessage( MESSAGE_T *message ) +{ // Handle any messages from other sub-systems - handleIncomingMessage( message ); -} + handleIncomingMessage( message ); +} /************************************************************************* Index: firmware/App/Services/TxParams.c =================================================================== diff -u -r5cc57a6d8eb3721811a2d6ace3176b7074c52fe8 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/Services/TxParams.c (.../TxParams.c) (revision 5cc57a6d8eb3721811a2d6ace3176b7074c52fe8) +++ firmware/App/Services/TxParams.c (.../TxParams.c) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file TxParams.c * -* @author (last) Vijay Pamula -* @date (last) 11-Jun-2026 +* @author (last) Praneeth Bunne +* @date (last) 02-Jul-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 02-Dec-2025 @@ -21,6 +21,7 @@ #include "BloodFlow.h" #include "Buttons.h" #include "Messaging.h" +#include "ModeStandby.h" #include "ModeTreatment.h" #include "ModePreTreat.h" #include "OperationModes.h" @@ -575,11 +576,11 @@ switch ( txType ) { - case TREATMENT_MODALITY_HDF: + case TREATMENT_MODALITY_HDF_ONLINE_FLUID: result = FALSE; break; - case TREATMENT_MODALITY_HD: + case TREATMENT_MODALITY_HD_SALINE_FLUID: result = ( ( ( param == TREATMENT_PARAM_HDF_DILUTION ) || ( param == TREATMENT_PARAM_SUBST_FLUID_VOLUME ) ) ? TRUE : FALSE ); break; @@ -738,6 +739,7 @@ F32 hepDR = stagedParams[ TREATMENT_PARAM_HEPARIN_DELIVERY_RATE ].sFlt; F32 hepBV = stagedParams[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].sFlt; F32 txVol = hepBV + ( hepDR * ( hepST / (F32)SEC_PER_MIN ) ) + SYRINGE_PUMP_PRIME_VOLUME_ML + SYRINGE_PUMP_FILL_VOLUME_OFFSET_ML; + TREATMENT_TYPE_T modality = (TREATMENT_TYPE_T)stagedParams[ TREATMENT_PARAM_TREATMENT_MODALITY ].uInt; // Variable to validate acid conversion factor consistency U32 acidType = stagedParams[ TREATMENT_PARAM_ACID_CONCENTRATE ].uInt; @@ -768,6 +770,13 @@ result = FALSE; } + // Verify Rx entered modality with the treatment initiation modality + if ( modality != getModality() ) + { + reasons[ TREATMENT_PARAM_TREATMENT_MODALITY ] = REQUEST_REJECT_REASON_MODALITY_MISMATCH; + result = FALSE; + } + return result; } Index: firmware/App/TDCommon.h =================================================================== diff -u -r0904e146ed12daa575b419612f5cdef5000fd0f5 -r069dee3a2428d3c6bb281db1844a372ae6e2063a --- firmware/App/TDCommon.h (.../TDCommon.h) (revision 0904e146ed12daa575b419612f5cdef5000fd0f5) +++ firmware/App/TDCommon.h (.../TDCommon.h) (revision 069dee3a2428d3c6bb281db1844a372ae6e2063a) @@ -7,8 +7,8 @@ * * @file TDCommon.h * -* @author (last) Dara Navaei -* @date (last) 27-May-2026 +* @author (last) Varshini Nagabooshanam +* @date (last) 02-Jul-2026 * * @author (original) Sean Nash * @date (original) 01-Aug-2024 @@ -25,7 +25,7 @@ #define TD_VERSION_MAJOR 0 #define TD_VERSION_MINOR 0 #define TD_VERSION_MICRO 0 -#define TD_VERSION_BUILD 55 +#define TD_VERSION_BUILD 58 // ********** development build switches **********