Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r4d635c390c184a405bdc96e56ce35505fe3868c5 -rcd5be724d5a3ba7457e761191d82f278654d7f5c --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 4d635c390c184a405bdc96e56ce35505fe3868c5) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision cd5be724d5a3ba7457e761191d82f278654d7f5c) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file Valves.c * -* @author (last) Bill Bracken -* @date (last) 19-Apr-2023 +* @author (last) Dara Navaei +* @date (last) 17-Oct-2023 * * @author (original) Dara Navaei * @date (original) 07-Aug-2020 @@ -19,7 +19,7 @@ #include "reg_het.h" #include "gio.h" -#include "Battery.h" +#include "CPLD.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" @@ -40,7 +40,7 @@ // Valve dialyzer inlet defines #define VDI_SET_PID_BIT_MASK 0x0010 ///< VDI enable PID bit mask #define VDI_SET_BYPASS_BIT_MASK 0x0020 ///< VDI enable bypass bit mask -#define VDI_RESET_CONTROL_BIT_MASK 0x03CF ///< VDI reset control bit mask +#define VDI_RESET_CONTROL_BIT_MASK 0x0FCF ///< VDI reset control bit mask #define VDI_INIT_STATUS_BIT_MASK 0x0040 ///< VDI init status bit mask #define VDI_ENABLE_PID_STATUS_BIT_MASK 0x0080 ///< VDI PID status bit mask @@ -49,7 +49,7 @@ // Valve dialyzer outlet defines #define VDO_SET_PID_BIT_MASK 0x0040 ///< VDO enable PID interface #define VDO_SET_BYPASS_BIT_MASK 0x0080 ///< VDO enable bypass bit mask -#define VDO_RESET_CONTROL_BIT_MASK 0x033F ///< VDO reset control bit mask +#define VDO_RESET_CONTROL_BIT_MASK 0x09FF ///< VDO reset control bit mask #define VDO_INIT_STATUS_BIT_MASK 0x0200 ///< VDO init status bit mask #define VDO_ENABLE_PID_STATUS_BIT_MASK 0x0400 ///< VDO enable PID status bit mask @@ -58,7 +58,7 @@ // Valve blood arterial defines #define VBA_SET_PID_BIT_MASK 0x0001 ///< VBA enable PID interface #define VBA_SET_BYPASS_BIT_MASK 0x0002 ///< VBA enable bypass interface -#define VBA_RESET_CONTROL_BIT_MASK 0x03FC ///< VBA reset control bit mask +#define VBA_RESET_CONTROL_BIT_MASK 0x0FFC ///< VBA reset control bit mask #define VBA_INIT_STATUS_BIT_MASK 0x0001 ///< VBA init status bit mask #define VBA_ENABLE_PID_STATUS_BIT_MASK 0x0002 ///< VBA PID status bit mask @@ -67,7 +67,7 @@ // Valve blood venous defines #define VBV_SET_PID_BIT_MASK 0x0004 ///< VBV enable PID interface bit mask #define VBV_SET_BYPASS_BIT_MASK 0x0008 ///< VBV enable bypass interface bit mask -#define VBV_RESET_CONTROL_BIT_MASK 0x03F3 ///< VBV reset control bit mask +#define VBV_RESET_CONTROL_BIT_MASK 0x0FF3 ///< VBV reset control bit mask #define VBV_INIT_STATUS_BIT_MASK 0x0008 ///< VBV init status bit mask #define VBV_ENABLE_PID_STATUS_BIT_MASK 0x0010 ///< VBV PID status bit mask @@ -219,12 +219,44 @@ static const U16 VALVE_CONTROL_MODES_RESET_BITS[ NUM_OF_VALVES ] = { VDI_RESET_CONTROL_BIT_MASK, VDO_RESET_CONTROL_BIT_MASK, VBA_RESET_CONTROL_BIT_MASK, VBV_RESET_CONTROL_BIT_MASK }; ///< Valves control modes rest bits -static const U16 VALVE_CONTROL_STATUS_BITS[ NUM_OF_VALVES ][ NUM_OF_VALVE_CONTROL_STATUS ] = - { { VDI_INIT_STATUS_BIT_MASK, VDI_ENABLE_PID_STATUS_BIT_MASK, VDI_ENABLE_BYPASS_STATUS_BIT_MASK, VDI_RESET_CONTROL_BIT_MASK }, - { VDO_INIT_STATUS_BIT_MASK, VDO_ENABLE_PID_STATUS_BIT_MASK, VDO_ENABLE_BYPASS_STATUS_BIT_MASK, VDO_RESET_CONTROL_BIT_MASK }, - { VBA_INIT_STATUS_BIT_MASK, VBA_ENABLE_PID_STATUS_BIT_MASK, VBA_ENABLE_BYPASS_STATUS_BIT_MASK, VBA_RESET_CONTROL_BIT_MASK }, - { VBV_INIT_STATUS_BIT_MASK, VBV_ENABLE_PID_STATUS_BIT_MASK, VBV_ENABLE_BYPASS_STATUS_BIT_MASK, VBV_RESET_CONTROL_BIT_MASK } }; ///< Valves control status bits +/// Valve check entries +enum valve_check_entries +{ + VALVE_CHECK_EXPECTED_CONTROL = 0, ///< Valve check expected control values + VALVE_CHECK_BIT_MASK, ///< Valve check bit mask + NUM_OF_VALVE_CHECK_ENTRIES, ///< Number of valve check entries +}; +#define VALVE_INIT_STATUS_BIT 0x0001 ///< valve init +#define VALVE_ENABLE_PID_STATUS_BIT 0x0002 ///< valve PID enabled +#define VALVE_ENABLE_BYPASS_STATUS_BIT 0x0004 ///< valve bypass + +#define VALVE_PID_CHECK ( VALVE_INIT_STATUS_BIT | VALVE_ENABLE_PID_STATUS_BIT ) +#define VALVE_CHECK_MASK ( VALVE_INIT_STATUS_BIT | VALVE_ENABLE_PID_STATUS_BIT | VALVE_ENABLE_BYPASS_STATUS_BIT ) +#define VALVE_CHECK_BITS_PER_VALVE ( 3 ) + +#define VDI_POS ( 2 ) +#define VDO_POS ( 3 ) +#define VBA_POS ( 0 ) +#define VBV_POS ( 1 ) +#define VDI_VALVE_CHECK ( VALVE_PID_CHECK << ( VDI_POS * VALVE_CHECK_BITS_PER_VALVE ) ) +#define VDO_VALVE_CHECK ( VALVE_PID_CHECK << ( VDO_POS * VALVE_CHECK_BITS_PER_VALVE ) ) +#define VBA_VALVE_CHECK ( VALVE_PID_CHECK << ( VBA_POS * VALVE_CHECK_BITS_PER_VALVE ) ) +#define VBV_VALVE_CHECK ( VALVE_PID_CHECK << ( VBV_POS * VALVE_CHECK_BITS_PER_VALVE ) ) + +#define VDI_VALVE_CHECK_MASK ( ( VALVE_CHECK_MASK << ( VDI_POS * VALVE_CHECK_BITS_PER_VALVE ) ) ) +#define VDO_VALVE_CHECK_MASK ( ( VALVE_CHECK_MASK << ( VDO_POS * VALVE_CHECK_BITS_PER_VALVE ) ) ) +#define VBA_VALVE_CHECK_MASK ( ( VALVE_CHECK_MASK << ( VBA_POS * VALVE_CHECK_BITS_PER_VALVE ) ) ) +#define VBV_VALVE_CHECK_MASK ( ( VALVE_CHECK_MASK << ( VBV_POS * VALVE_CHECK_BITS_PER_VALVE ) ) ) + +static const U16 VALVE_CHECK[ NUM_OF_VALVES ][ NUM_OF_VALVE_CHECK_ENTRIES ] = +{ { VDI_VALVE_CHECK, VDI_VALVE_CHECK_MASK }, + { VDO_VALVE_CHECK, VDO_VALVE_CHECK_MASK }, + { VBA_VALVE_CHECK, VBA_VALVE_CHECK_MASK }, + { VBV_VALVE_CHECK, VBV_VALVE_CHECK_MASK } +}; ///< Valve check entries + + static U16 valvesControlSetBits; ///< Valves control set bit static OPN_CLS_STATE_T valveAirTrapStatus; ///< Air trap valve status (open/close) static HD_VALVES_CAL_RECORD_T valvesCalibrationRecord; ///< Valves calibration record. @@ -240,7 +272,9 @@ static VALVE_STATE_T handleValveStateHomingFindDeenergizedEdge( VALVE_T valve ); static VALVE_STATE_T handleValveStateIdle( VALVE_T valve ); static VALVE_STATE_T handleValveStateInTransition( VALVE_T valve ); +#ifdef DEBUG_ENABLED static VALVE_STATE_T handleValveStateInBypassMode( VALVE_T valve ); +#endif // Private function prototypes static void setValveControlMode( VALVE_T valve, VALVE_MODE_T mode ); @@ -829,13 +863,14 @@ ( FALSE == isValveCloseToCommandedPosition( valve, valvesStatus[ valve ].pendingCommandedPosition ) ) ) { // Just set the valves to transition so it will not be in a known position for a while - valvesStatus[ valve ].commandedPosition = valvesStatus[ valve ].pendingCommandedPosition; - valvesStatus[ valve ].transitionStartTime = getMSTimerCount(); - valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; + valvesStatus[ valve ].commandedPosition = valvesStatus[ valve ].pendingCommandedPosition; + valvesStatus[ valve ].transitionStartTime = getMSTimerCount(); + setValveNextStep( valve, TRANSITION_STEP_CHANGE_IN_COUNTS ); state = VALVE_STATE_IN_TRANSITION; } + valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; } // This option is only available in a debug build #ifdef DEBUG_ENABLED @@ -892,7 +927,7 @@ state = VALVE_STATE_IDLE; } // Check if the valve's transition time has timed out - else if ( ( TRUE == didTimeout( valvesStatus[ valve ].transitionStartTime, VALVE_TRANSITION_TIMEOUT_MS ) ) && ( FALSE == isACPowerLost() ) ) + else if ( ( TRUE == didTimeout( valvesStatus[ valve ].transitionStartTime, VALVE_TRANSITION_TIMEOUT_MS ) ) && ( getCPLDACPowerLossDetected() != TRUE ) ) { // Go back to Idle state and set the valve position to not in position because it was not able to get to the target position valvesStatus[ valve ].currentPosition = VALVE_POSITION_NOT_IN_POSITION; @@ -1006,62 +1041,26 @@ * The areValvesEnabled function checks the current valves status from FPGA * to the enable bit mask of each valve. If any of the valves is not enabled * the function raises an alarm. - * @details Inputs: valvesStatus + * @details Inputs: valvesStatus, VALVE_CHECK * @details Outputs: none - * @return Returns TRUE if all the valves are enabled properly + * @return Returns TRUE if all the valves status bits are correct *************************************************************************/ static BOOL areValvesFunctional( void ) { BOOL result = TRUE; VALVE_T valve; - VALVE_MODE_T mode; // Get the status of the valves from FPGA - U16 status = getFPGAValvesStatus(); + U16 status = getFPGAValvesStatus(); for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) { - mode = valvesStatus[ valve ].controlMode; - - // Depending on the control mode of the valve, different bit masks will be checked - if ( mode == VALVE_CONTROL_MODE_ENABLE_PID ) + U16 statusCheck = status & VALVE_CHECK[ valve ][ VALVE_CHECK_BIT_MASK ]; + if ( VALVE_CHECK[ valve ][ VALVE_CHECK_EXPECTED_CONTROL ] != statusCheck ) { - if ( FALSE == ( status & VALVE_CONTROL_STATUS_BITS[ valve ][ VALVE_CONTROL_STATUS_INITIALIZED ] ) ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_NOT_FUNCTIONAL, (U32)valve, (U32)mode ); - result = FALSE; - } - if ( FALSE == ( status & VALVE_CONTROL_STATUS_BITS[ valve ][ VALVE_CONTROL_STATUS_PID_ENABLED ] ) ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_NOT_FUNCTIONAL, (U32)valve, (U32)mode ); - result = FALSE; - } - } - else if ( mode == VALVE_CONTROL_MODE_ENABLE_BYPASS ) - { - if ( FALSE == ( status & VALVE_CONTROL_STATUS_BITS[ valve ][ VALVE_CONTROL_STATUS_BYPASS_ENABLED ] ) ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_NOT_FUNCTIONAL, (U32)valve, (U32)mode ); - result = FALSE; - } - } - else if ( mode == VALVE_CONTROL_MODE_DISABLE_ALL ) - { - if ( FALSE == ( status & ( ~VALVE_CONTROL_STATUS_BITS[ valve ][ VALVE_CONTROL_STATUS_DISABLED ] ) ) ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_NOT_FUNCTIONAL, (U32)valve, (U32)mode ); - result = FALSE; - } - } -#ifndef _VECTORCAST_ - // The default cannot be reached in VectorCAST since the cases are run in a for loop - // Invalid mode was selected - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_VALVES_INVALID_CONTROL_MODE_SELECTED, (U32)valve ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_NOT_FUNCTIONAL, (U32)valve, (U32)status); result = FALSE; - } -#endif + } } return result; @@ -1084,7 +1083,7 @@ position &= DISABLE_VALVE_CURRENT_RELAXATION; // If current relaxation is needed, set the MSB to 1 - if ( enableCurrentRelaxation ) + if ( TRUE == enableCurrentRelaxation ) { position |= ENABLE_VALVE_CURRENT_RELAXATION; } @@ -1190,7 +1189,7 @@ for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) { // Check the valve is in Idle state, otherwise the position should not be checked - if ( ( valvesStatus[ valve ].execState == VALVE_STATE_IDLE ) && ( FALSE == isACPowerLost() ) ) + if ( ( valvesStatus[ valve ].execState == VALVE_STATE_IDLE ) && ( getCPLDACPowerLossDetected() != TRUE ) ) { U32 maxDeviation = MAX_DEVIATION_FROM_TARGET_IN_COUNTS;