Index: firmware/App/Controllers/Valves.h =================================================================== diff -u -rf9c86e807b65164850947909bf63bd327ed69a32 -rf1adb311cbf9bcf5863864d165f68e4a497ae627 --- firmware/App/Controllers/Valves.h (.../Valves.h) (revision f9c86e807b65164850947909bf63bd327ed69a32) +++ firmware/App/Controllers/Valves.h (.../Valves.h) (revision f1adb311cbf9bcf5863864d165f68e4a497ae627) @@ -7,8 +7,8 @@ * * @file Valves.h * -* @author (last) Sean Nash -* @date (last) 04-May-2026 +* @author (last) Varshini Nagabooshanam +* @date (last) 28-Jul-2026 * * @author (original) Sean Nash * @date (original) 24-Oct-2024 @@ -21,7 +21,7 @@ // ********** public definitions ********** #include "TDCommon.h" -#include "RotaryValve.h" +#include "PinchValve.h" /** * @defgroup Valves Valves @@ -36,17 +36,6 @@ #define VALVE_NO_FORCE_HOME FALSE ///< Do not re-home valve if already homed - just go to position A instead #define VALVE_CARTRIDGE_MAY_BE_PRESENT TRUE ///< A cartridge may be present, so allow for homed positions to be further away from where expected -/// Valves positions -typedef enum valveStatesNames -{ - VALVE_POSITION_NOT_IN_POSITION = 0, ///< Valve position is unknown (cannot be used as a command) - VALVE_POSITION_A_INSERT_EJECT, ///< Position A, Insert/Eject - VALVE_POSITION_B_OPEN, ///< Position B, Open - VALVE_POSITION_C_CLOSE, ///< Position C, Close - VALVE_POSITION_D_PARTIAL_CLOSE, ///< Position D, partial close - NUM_OF_VALVE_POSITIONS, ///< Number of valve positions -} VALVE_POSITION_T; - #pragma pack(push, 1) /// TD valves broadcast data typedef struct @@ -59,21 +48,14 @@ S16 posA; ///< Position A (count) S16 posB; ///< Position B (count) S16 posC; ///< Position C (count) - S16 posD; ///< Position D (count) - S16 maxHomingPos; ///< Maximum homing position } 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_HOMING_NOT_HOMED, ///< Valve state homing not started. VALVE_STATE_IDLE, ///< Valve state idle. VALVE_STATE_IN_TRANSITION, ///< Valve state in transition. NUM_OF_VALVE_STATES, ///< Number of valve exec states. @@ -83,7 +65,7 @@ void initValves(void); void execValvesController(void); -SELF_TEST_STATUS_T execValvesSelfTest( void ); +//SELF_TEST_STATUS_T execValvesSelfTest( void ); BOOL homeValve( VALVE_T valve, BOOL force, BOOL cartridge ); BOOL setValvePosition( VALVE_T valve, VALVE_POSITION_T position ); Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r2c16de14d2acd2aa1e36943f95c3855da094dc97 -rf1adb311cbf9bcf5863864d165f68e4a497ae627 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 2c16de14d2acd2aa1e36943f95c3855da094dc97) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision f1adb311cbf9bcf5863864d165f68e4a497ae627) @@ -15,18 +15,24 @@ * ***************************************************************************/ +#include "AirPump.h" #include "AirTrap.h" #include "BloodFlow.h" +#include "Bubbles.h" #include "Buttons.h" +#include "Compatible.h" #include "DDInterface.h" #include "Messaging.h" +#include "ModeInitPOST.h" +#include "ModePostTreat.h" #include "ModePreTreat.h" -#include "ModeTreatment.h" #include "ModeStandby.h" +#include "ModeTreatment.h" #include "OperationModes.h" #include "Switches.h" #include "SyringePump.h" #include "SystemCommTD.h" +#include "SyringePump.h" #include "TxParams.h" #include "Valve3Way.h" #include "Valves.h" @@ -53,6 +59,7 @@ static TD_STANDBY_STATE_T handleStandbyModeStartState( void ); static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); +static void setStandbyStateTransition( void ); /*********************************************************************//** * @brief @@ -80,22 +87,24 @@ *************************************************************************/ U32 transitionToStandbyMode( void ) { - TD_OP_MODE_T previousOpMode = getPreviousOperationMode(); + TD_OP_MODE_T previousOpMode = getPreviousOperationMode(); //TODO +// U08 requestPayload[3] = { 0U, 0U, 0U }; // Re-initialize when transitioning to standby mode initStandbyMode(); resetDDInterface(); + resetAirTrap(); + resetBloodPumpRotorCount(); + resetPreLoadStatus(); + setVenousBubbleDetectionEnabled( H18_BBLD, FALSE ); setCurrentSubState( NO_SUB_STATE ); +// clearNoRetriggerFlag(); // Alarm flag // Set user alarm recovery actions allowed in this mode setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, FALSE ); - // Pumps should be off - signalBloodPumpHardStop(); -// stopSyringePump(); - // Set valves to default positions set3WayValveState( H13_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); set3WayValveState( H20_VALV, VALVE_3WAY_COMMON_TO_CLOSED_STATE ); @@ -107,12 +116,19 @@ { setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); } - + // Standby currently supports Start and Wait For Treatment states. + currentStandbyState = STANDBY_START_STATE; + // Pumps should be off + signalBloodPumpHardStop(); +// stopSyringePump(); doorClosedRequired( FALSE ); // door no longer required to be closed in standby mode // Request DD service record and usage information from DD -// sendDGServiceRequestToDG(); -// sendDGUsageInfoRequestToDG(); +// sendDDServiceRequestToDD(); + //TODO: Service record id not available +// sendMessage( MSG_ID_TD_DD_REQUEST_SERVICE_RECORD_FROM_TD, COMM_BUFFER_OUT_CAN_TD_2_DD, requestPayload, sizeof( requestPayload ) ); +// sendMessage( MSG_ID_TD_DD_USAGE_INFO_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_DD, requestPayload, sizeof( requestPayload ) ); +// sendDDUsageInfoRequestToDD(); //TODO need to enable return currentStandbyState; } @@ -127,6 +143,7 @@ U32 execStandbyMode( void ) { BOOL stop = isStopButtonPressed(); + TD_STANDBY_STATE_T prevStandbyState = currentStandbyState; if ( TRUE == stop ) { @@ -149,15 +166,21 @@ currentStandbyState = STANDBY_START_STATE; break; } + if ( prevStandbyState != currentStandbyState ) + { + setStandbyStateTransition(); + } return currentStandbyState; } /*********************************************************************//** * @brief * The handleStandbyModeStartState function handles the standby start state. - * This state waits for the door to be closed and then initiates homing of - * pumps and valves and transitions to the wait for treatment state. + * This state initiates homing of the syringe pump and pinch valves, + * then transitions to Wait For Treatment after homing completes and + * then initiates homing of pumps and valves and transitions to the + * wait for treatment state. * @details \b Inputs: homingInitiated * @details \b Outputs: homingInitiated * @return next state of the standby mode state machine @@ -166,24 +189,32 @@ { TD_STANDBY_STATE_T state = STANDBY_START_STATE; + // If we haven't already initiated homing of actuators, initiate now if ( FALSE == homingInitiated ) { - VALVE_T valve; - // Initiate homing for both pinch valves. - for ( valve = FIRST_VALVE; valve < NUM_OF_VALVES; ++valve ) + // Home Standby pinch valves. + homeValve( H1_VALV, FALSE, TRUE ); + homeValve( H19_VALV, FALSE, TRUE ); + + if ( FALSE == isSyringePumpHome() ) { - homeValve( valve, FALSE, TRUE ); + retractSyringePump(); } + homingInitiated = TRUE; } - else if ( ( VALVE_STATE_IDLE == getValveState( H1_VALV ) ) && - ( VALVE_STATE_IDLE == getValveState( H19_VALV ) ) ) + else { - // After homing completes, move both pinch valves to Position A. - setValvePosition( H1_VALV, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( H19_VALV, VALVE_POSITION_A_INSERT_EJECT ); - homingInitiated = FALSE; - state = STANDBY_WAIT_FOR_TREATMENT_STATE; + // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration + if ( ( TRUE == isSyringePumpHome() ) && ( TRUE == isSyringePumpStopped() ) + && ( VALVE_POSITION_A_INSERT_EJECT == getValvePosition( H1_VALV ) ) + && ( VALVE_POSITION_A_INSERT_EJECT == getValvePosition( H19_VALV ) ) ) + { + syringePumpVerifyForceSensorDACCalibration(); + homingInitiated = FALSE; // reset for next time + + state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check + } } return state; @@ -200,43 +231,50 @@ static TD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) { TD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; - DD_OP_MODE_T ddOperationMode = getDDOpMode(); F32 bicarbConvFactor = BICARBONATE_CONVERSION_FACTOR; + TD_VERSIONS_T payload; + //TODO +// DD_OP_MODE_T ddOperationMode = getDDOpMode(); -// switch ( dgOperationMode ) +// switch ( ddOperationMode ) // { -// case DG_MODE_GENE: -// // If DG is in idle generation state while we are in standby mode, transition DG to standby too -// cmdStopDG(); +// case DD_MODE_GENE: +// // If DD is in idle generation state while we are in standby mode, transition DD to standby too +// cmdStopDD(); // break; // -// // If DG is any of the cleaning modes, set the HD standby to be in the corresponding cleaning mode -// case DG_MODE_FLUS: -// case DG_MODE_HEAT: -// case DG_MODE_CHEM: -// case DG_MODE_CHFL: -// case DG_MODE_HCOL: -// case DG_MODE_ROPS: -// setRequestedCleaningMode( dgOperationMode ); -// state = STANDBY_WAIT_FOR_DG_CLEANING_MODE_TO_START_STATE; +// // If DD is any of the cleaning modes, set the TD standby to be in the corresponding cleaning mode +// case DD_MODE_HEAT: +// case DD_MODE_HCOL: +// case DD_MODE_ROPS: +// setRequestedCleaningMode( ddOperationMode ); +// state = STANDBY_WAIT_FOR_DD_CLEANING_MODE_TO_START_STATE; +// // DD cleaning mode handling is not enabled yet. +// // Stay in Wait For Treatment until DD returns to a supported standby state. // break; // // default: -// // Do nothing. There are other DG modes that HD standby does not need to act upon them. +// // Do nothing. There are other DD modes that TD standby does not need to act upon them. // break; // } - // If DD is communicating and we don't yet have DD version info, request it -// if ( TRUE == isDDCommunicating() ) -// { -// DG_VERSIONS_T ddVersion = getDDVersion(); -// -// if ( 0 == dgVersion.compatibilityRev ) -// { -// sendFWVersionRequest(); -// } -// } + // If DD is communicating and we don't yet have DD version info, request it. + if ( TRUE == isDDCommunicating() ) + { + if ( FALSE == isDDCompatible() ) + { + // Populate TD firmware version payload. + payload.major = (U08)TD_VERSION_MAJOR; + payload.minor = (U08)TD_VERSION_MINOR; + payload.micro = (U08)TD_VERSION_MICRO; + payload.build = (U16)TD_VERSION_BUILD; + payload.compatibilityRev = (U32)SW_COMPATIBILITY_REV; + sendMessage( MSG_ID_FW_VERSIONS_REQUEST, COMM_BUFFER_OUT_CAN_TD_2_DD, + (U08 *)&payload, sizeof( TD_VERSIONS_T ) ); + } + } + // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). if ( TRUE == treatStartReqReceived ) { @@ -245,33 +283,89 @@ // Initialize treatment modes before starting a new treatment initPreTreatmentMode(); initTreatmentMode(); -// initPostTreatmentMode(); + initPostTreatmentMode(); resetAirTrap(); // Send UI default pressure settings since user is not asked to set them. respRecord.artPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ); respRecord.venPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_HIGH_LIMIT_WINDOW ); respRecord.venPresLimitAsymmetricmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_VEN_PRES_LOW_LIMIT_WINDOW ); respRecord.tmpPresLimitWindowmmHg = getSysConfigTreatmentParameterU32DefaultValue( TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW ); sendPressureLimitsChangeResponse( &respRecord ); - // start DD pre-gen // TODO + // start DD pre-gen // TODO we need to add UF rate as per new requirement + cmdStartPreGenerateDialysate( (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ), getTreatmentParameterF32( TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR ), bicarbConvFactor, getTreatmentParameterU32( TREATMENT_PARAM_SODIUM ), getTreatmentParameterU32( TREATMENT_PARAM_BICARBONATE ) ); // Start treatment workflow with pretreatment mode - requestNewOperationMode( MODE_PRET ); - treatStartReqReceived = FALSE; // Set fluid type setFluidType( modality ); + requestNewOperationMode( MODE_PRET ); + treatStartReqReceived = FALSE; } return state; } /*********************************************************************//** * @brief + * The setStandbyStateTransition function sets the actuators and variables + * for Standby state transitions. + * @details \b Inputs: newState + * @details \b Outputs: Actuators configured for the new Standby state. + * @param newState New Standby state. + * @return none + *************************************************************************/ +static void setStandbyStateTransition( void ) +{ + // Common Standby actuator settings. + resetAirTrap(); + + setAirPumpState( AIR_PUMP_STATE_OFF, + AIR_PUMP_MOTOR_OFF ); + + set3WayValveState( H13_VALV, + VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + + set3WayValveState( H20_VALV, + VALVE_3WAY_COMMON_TO_CLOSED_STATE ); + + stopSyringePump(); + signalBloodPumpHardStop(); + + switch ( currentStandbyState ) + { + case STANDBY_START_STATE: + // Homing is handled in handleStandbyModeStartState(). + break; + + case STANDBY_WAIT_FOR_TREATMENT_STATE: + setValvePosition( H1_VALV, + VALVE_POSITION_A_INSERT_EJECT ); + + setValvePosition( H19_VALV, + VALVE_POSITION_A_INSERT_EJECT ); + + // TODO: + // H5 Ejector Off + // Dialyzer Bypassed + // Qd 0 + // Quf 0 + // Qs 0 + break; + + default: + SET_ALARM_WITH_2_U32_DATA( + ALARM_ID_TD_SOFTWARE_FAULT, + SW_FAULT_ID_MODE_STANDBY_INVALID_STATE, + currentStandbyState ); + break; + } +} +/*********************************************************************//** + * @brief * The setFluidType function sets the fluid type based on the user's * treatment selection from the home screen. * @details \b Inputs: none @@ -331,52 +425,99 @@ BOOL signalUserInitiateTreatment( MESSAGE_T *message ) { BOOL result = FALSE; - U32 cmd = 0; - TD_OP_MODE_T mode = getCurrentOperationMode(); + INITIATE_TREATMENT_REQUEST_PAYLOAD_T cmd; + 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; + memset( &cmd, 0, sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) ); + memset( &response, 0, sizeof( UI_RESPONSE_PAYLOAD_T ) ); // Verify message payload length is valid if ( sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) == message->hdr.payloadLen ) { memcpy( &request, message->payload, sizeof( INITIATE_TREATMENT_REQUEST_PAYLOAD_T ) ); - cmd = request.command; + cmd.command = request.command; - if ( USER_COMMAND_INITIATE == cmd ) + if ( USER_COMMAND_INITIATE == cmd.command ) { - // Verify TD is in standby mode waiting for treatment start request - if ( ( mode != MODE_STAN ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) + // Verify TD is in Standby mode and waiting for treatment start request. + if ( ( MODE_STAN != mode ) || ( STANDBY_WAIT_FOR_TREATMENT_STATE != currentStandbyState ) ) { rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; } + else if ( TRUE == treatStartReqReceived ) + { + rejReason = REQUEST_REJECT_REASON_REQUEST_ALREADY_PENDING; + } 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 ) + // Verify DD is communicating. + else if ( TRUE != isDDCommunicating() ) { rejReason = REQUEST_REJECT_REASON_DD_COMM_LOST; } - // Verify DD is not busy - else if ( ( DD_MODE_STAN != getDDOpMode() ) || ( DD_STANDBY_MODE_STATE_IDLE != getDDSubMode() ) ) // || ( isDDPOSTPassed() != TRUE ) ) + // Verify DD is ready and not busy with flush/disinfect/cleaning/generation. + else if ( ( DD_MODE_STAN != getDDOpMode() ) || ( DD_STANDBY_MODE_STATE_IDLE != getDDSubMode() ) ) { - rejReason = REQUEST_REJECT_REASON_DD_NOT_IN_STANDBY_IDLE_STATE; + rejReason = REQUEST_REJECT_REASON_DD_BUSY; } + else if ( FALSE == isDDCompatible() ) + { + rejReason = REQUEST_REJECT_REASON_DD_INCOMPATIBLE; + } + // TODO: Need to uncomment below after implementation +// else if ( TRUE == isDDDisinfectionOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_DISINFECT_HAS_BEEN_EXPIRED; +// } +// else if ( TRUE == isDDFlushOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_FILTER_FLUSH_HAS_BEEN_EXPIRED; +// } +// else if ( TRUE == isDDTemperatureTooHigh() ) +// { +// rejReason = REQUEST_REJECT_REASON_DD_TEMPERATURE_OUT_OF_RANGE; +// } +// else if ( TRUE == isDDServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_DD_SERVICE_IS_DUE; +// } +// else if ( TRUE == isTDServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_TD_SERVICE_IS_DUE; +// } +// else if ( FALSE == isFPStandbymode() ) +// { +// rejReason = REQUEST_REJECT_REASON_FP_BUSY; +// } +// else if ( TRUE == isfpServiceOverdue() ) +// { +// rejReason = REQUEST_REJECT_REASON_FP_SERVICE_IS_DUE; +// } + #endif else { - // If request to start treatment not rejected, set flag to initiate treatment workflow +// Low battery is a warning only, not a rejection. + //TODO +// if ( TRUE == isBatteryRemainingCapacityLessThan60Wh() ) +// { +// SET_ALARM( ALARM_ID_TD_LOW_BATTERY_CHARGE ); +// } + + // 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 ) + else if ( USER_COMMAND_CANCEL == cmd.command ) { result = signalPreTreatmentBackoutToStandby(); @@ -387,14 +528,18 @@ } else { - rejReason = REQUEST_REJECT_REASON_INVALID_COMMAND; + rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; } } + else + { + rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } - // Respond to request to start treatment - response.accepted = result; + // Respond to request to start treatment. + response.accepted = result; response.rejectionReason = rejReason; - sendMessage( MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( UI_RESPONSE_PAYLOAD_T ) ); + sendMessage( MSG_ID_TD_RESP_INITIATE_TREATMENT_WORKFLOW, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*) &response, sizeof( UI_RESPONSE_PAYLOAD_T ) ); return result; }