/************************************************************************** * * Copyright (c) 2020-2025 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModePreGenPermeate.c * * @author (last) Michael Garthwaite * @date (last) 28-Feb-2025 * * @author (original) Michael Garthwaite * @date (original) 28-Feb-2025 * ***************************************************************************/ #include "BoostPump.h" #include "DDInterface.h" #include "FlushFilter.h" #include "FlushPermeate.h" #include "FlushConcentrate.h" #include "FPModeStandby.h" #include "FPOperationModes.h" #include "InletPressureCheck.h" #include "Level.h" #include "MessageSupport.h" #include "Messaging.h" #include "ModeGenPermeate.h" #include "ModePreGenPermeate.h" #include "PermeateTank.h" #include "ROPump.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup FPPreGenPermeateMode * @{ */ // ********** private definitions ********** #define PRE_GENP_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the pre gen Permeate mode data published. #define VERIFY_WATER_RO_PUMP_TGT_FLOW_ML 750 ///< Target flow rate for RO pump in ml/min #define VERIFY_WATER_BOOST_PUMP_TGT_PSI 25 ///< Target pressure for boost pump in psi. #define VERIFY_WATER_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Verify Water timer ( in ms ) // ********** private data ********** static FP_PRE_GENP_MODE_STATE_T preGenPState; ///< Currently active pre generate Permeate state. static U32 preGenPDataPublicationTimerCounter; ///< Used to schedule pre generate Permeate data publication to CAN bus. static OVERRIDE_U32_T preGenPDataPublishInterval; ///< Pre Generate Permeate mode data publish interval. static BOOL isPreGenComplete; ///< Flag indicating if Pre generation has completed. static U32 pendingStartPreGenRequest; ///< Flag indicating DD has requested FP start the generate permeate. static U32 verifyWaterTimer; // ********** private function prototypes ********** static void publishPreGenPModeData( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPInletPressureCheckState( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPFilterFlushState( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPPermeateFlushState( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPConcentrateFlushState( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPVerifyWaterState( void ); static FP_PRE_GENP_MODE_STATE_T handlePreGenPPausedState( void ); static void setModePreGenPTransition( FP_PRE_GENP_MODE_STATE_T state ); /*********************************************************************//** * @brief * The initPreGenPMode function initializes the pre generate Permeate mode unit. * @details \b Inputs: none * @details \b Outputs: pre gen Permeate mode unit initialized * @return none *************************************************************************/ void initPreGenPMode( void ) { preGenPState = FP_PRE_GENP_INLET_PRESSURE_CHECK; preGenPDataPublishInterval.data = PRE_GENP_DATA_PUBLISH_INTERVAL; preGenPDataPublishInterval.ovData = PRE_GENP_DATA_PUBLISH_INTERVAL; preGenPDataPublishInterval.ovInitData = 0; preGenPDataPublishInterval.override = OVERRIDE_RESET; preGenPDataPublicationTimerCounter = 0; pendingStartPreGenRequest = FALSE; isPreGenComplete = FALSE; verifyWaterTimer = 0; } /*********************************************************************//** * @brief * The transitionToPreGenPMode function prepares for transition to pre gen * Permeate mode. * @details \b Inputs: none * @details \b Outputs: none * @return initial state *************************************************************************/ U32 transitionToPreGenPMode( void ) { initPreGenPMode(); setCurrentSubState( preGenPState ); setModePreGenPTransition( preGenPState ); resetPermeateTank(); initInletPressureCheck(); return preGenPState; } /*********************************************************************//** * @brief * The execPreGenPMode function executes the pre gen Permeate mode state machine. * @details \b Inputs: preGenWState * @details \b Outputs: Pre Gen Permeate mode state machine executed * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT when wrong pre gen Permeate state invoked. * @return current state. *************************************************************************/ U32 execPreGenPMode( void ) { FP_PRE_GENP_MODE_STATE_T previouspreGenPState = preGenPState; // execute current pre gen Permeate state switch ( preGenPState ) { case FP_PRE_GENP_INLET_PRESSURE_CHECK: preGenPState = handlePreGenPInletPressureCheckState(); break; case FP_PRE_GENP_FILTER_FLUSH: preGenPState = handlePreGenPFilterFlushState(); break; case FP_PRE_GENP_PERMEATE_FLUSH: preGenPState = handlePreGenPPermeateFlushState(); break; case FP_PRE_GENP_CONCENTRATE_FLUSH: preGenPState = handlePreGenPConcentrateFlushState(); break; case FP_PRE_GENP_VERIFY_WATER: preGenPState = handlePreGenPVerifyWaterState(); break; case FP_PRE_GENP_PAUSED: preGenPState = handlePreGenPPausedState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_PGEN_STATE, preGenPState ) break; } if( previouspreGenPState != preGenPState ) { setModePreGenPTransition( preGenPState ); SEND_EVENT_WITH_2_U32_DATA( FP_EVENT_PRE_GEN_CHANGE, preGenPState, previouspreGenPState ) } //Publish pre Gen Permeate mode data publishPreGenPModeData(); return preGenPState; } /*********************************************************************//** * @brief * The setModePreGenPTransition function sets the actuators and variables * for the state transition in pre generate Permeate mode. * @details Inputs: none * @details Outputs: Actuate valves, pumps as desired. * @param state pre gen Permeate state enum * @return none *************************************************************************/ static void setModePreGenPTransition( FP_PRE_GENP_MODE_STATE_T state ) { // Execute on running state switch( state ) { case FP_PRE_GENP_INLET_PRESSURE_CHECK: break; case FP_PRE_GENP_FILTER_FLUSH: // Actuator transitions happen within Filter Flush exec break; case FP_PRE_GENP_PERMEATE_FLUSH: // Actuator transitions happen within Permeate Flush exec break; case FP_PRE_GENP_CONCENTRATE_FLUSH: // Actuator transitions happen within Concentrate Flush exec break; case FP_PRE_GENP_VERIFY_WATER: setValveState( M4_VALV, VALVE_STATE_OPEN ); setValveState( M7_VALV, VALVE_STATE_CLOSED ); setValveState( P6_VALV, VALVE_STATE_CLOSED ); setValveState( P11_VALV, VALVE_STATE_OPEN ); setValveState( P33_VALV, VALVE_STATE_OPEN ); // TODO - Change valves to handle RO rejection config setValveState( P34_VALV, VALVE_STATE_CLOSED ); // Current set to Medium recovery for alpha HW setValveState( P37_VALV, VALVE_STATE_CLOSED ); setValveState( P39_VALV, VALVE_STATE_OPEN ); setValveState( P20_VALV, VALVE_STATE_CLOSED ); setValveState( P43_VALV, VALVE_STATE_CLOSED ); if ( TRUE == isBoostPumpInstalled() ) { setBoostPumpTargetPressure( VERIFY_WATER_BOOST_PUMP_TGT_PSI ); } setROPumpTargetFlowRateMLPM( VERIFY_WATER_RO_PUMP_TGT_FLOW_ML, TRUE ); verifyWaterTimer = getMSTimerCount(); break; case FP_PRE_GENP_PAUSED: break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_FP_INVALID_PGEN_STATE, state ) break; } } /*********************************************************************//** * @brief * The handlePreGenPInletPressureCheckState handles the inlet pressure check state of pre gen Permeate. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of pre gen Permeate mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPInletPressureCheckState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_INLET_PRESSURE_CHECK; // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = FP_PRE_GENP_PAUSED; // } if ( FALSE == isBoostPumpInstalled() ) { signalStartFilterFlush(); state = FP_PRE_GENP_FILTER_FLUSH; } else { execInletPressureCheck(); if ( TRUE == isInletPressureCheckCompleted() ) { signalStartFilterFlush(); state = FP_PRE_GENP_FILTER_FLUSH; } } return state; } /*********************************************************************//** * @brief * The handlePreGenPFilterFlushState handles the filter flush state of pre gen Permeate. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of pre gen Permeate mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPFilterFlushState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_FILTER_FLUSH; // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = FP_PRE_GENP_PAUSED; // } execFilterFlush(); if( TRUE == isFilterFlushComplete() ) { signalStartPermeateFlush(); state = FP_PRE_GENP_PERMEATE_FLUSH; } return state; } /*********************************************************************//** * @brief * The handlePreGenPPermeateFlushState handles the permeate flush * state of pre gen permeate. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of pre gen permeate mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPPermeateFlushState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_PERMEATE_FLUSH; // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = FP_PRE_GENP_PAUSED; // } execPermeateFlush(); if( TRUE == isPermeateFlushComplete() ) { signalStartConcentrateFlush(); state = FP_PRE_GENP_CONCENTRATE_FLUSH; } return state; } /*********************************************************************//** * @brief * The handlePreGenPConcentrateFlushState handles the concentrate flush * state of pre gen water. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of pre gen water mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPConcentrateFlushState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_CONCENTRATE_FLUSH; // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = FP_PRE_GENP_PAUSED; // } execConcentrateFlush(); if( TRUE == isConcentrateFlushComplete() ) { state = FP_PRE_GENP_VERIFY_WATER; } return state; } /*********************************************************************//** * @brief * The handlePreGenPVerifyWaterState handles the verify water state of * pre gen water. * @details \b Inputs: none * @details \b Outputs: isPreGenComplete * @return the next state of pre gen water mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPVerifyWaterState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_VERIFY_WATER; F32 roCurrentDutyCycle = getCurrentROPumpDutyCyclePCT(); // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = FP_PRE_GENP_PAUSED; // } if( TRUE == didTimeout( verifyWaterTimer, VERIFY_WATER_TIMEOUT_MS ) ) { transitionToGenPermeateMode(); requestGenWaterStart(); // transition function will clear start flag isPreGenComplete = TRUE; SEND_EVENT_WITH_2_U32_DATA( FP_EVENT_PRE_GEN_RO_SET_PWM, roCurrentDutyCycle, getFluidPumpReadPWMDutyCycle( P12_PUMP ) ) } return state; } /*********************************************************************//** * @brief * The handlePreGenPPausedState handles the paused state of * pre gen water. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of pre gen water mode *************************************************************************/ static FP_PRE_GENP_MODE_STATE_T handlePreGenPPausedState( void ) { FP_PRE_GENP_MODE_STATE_T state = FP_PRE_GENP_PAUSED; return state; } /** * *******************************************************************//** * @brief * The getCurrentPreGenWState function returns the current state of the * pre gen water mode. * @details \b Inputs: preGenWState * @details \b Outputs: none * @return the current state of pre gen water mode *************************************************************************/ FP_PRE_GENP_MODE_STATE_T getCurrentPreGenPState( void ) { return preGenPState; } /*********************************************************************//** * @brief * The isPreGenPComplete function returns isPreGenComplete. * @details \b Inputs: none * @details \b Outputs: none * @return the complete boolean for Pre-Gen Mode. *************************************************************************/ BOOL isPreGenPComplete( void ) { return isPreGenComplete; } /*********************************************************************//** * @brief * The getPreGenRequest function returns the current state of the * pre gen water mode. * @details \b Inputs: pendingStartPreGenRequest * @details \b Outputs: none * @return the current state of pre gen request *************************************************************************/ BOOL getPreGenRequest( void ) { return pendingStartPreGenRequest; } /*********************************************************************//** * @brief * The getPreGenWDataPublishInterval function gets the pre generate water * mode data publish interval. * @details \b Inputs: genWaterDataPublishInterval * @details \b Outputs: none * @return the interval at generate water mode data being published. *************************************************************************/ static U32 getPreGenPDataPublishInterval( void ) { U32 result = getU32OverrideValue( &preGenPDataPublishInterval ); return result; } /*********************************************************************//** * @brief * The publishPreGenWModeData function broadcasts the pre generate water * mode data at defined interval. * @details \b Inputs: genDialysateDataPublicationTimerCounter * @details \b Outputs: preGenWState, preGenWDataPublicationTimerCounter * @details \b Message \b Sent: MSG_ID_FP_GEN_WATER_MODE_DATA to publish the * generate water mode data. * @return none *************************************************************************/ static void publishPreGenPModeData( void ) { if ( ++preGenPDataPublicationTimerCounter >= getPreGenPDataPublishInterval() ) { PRE_GENP_MODE_DATA_T data; data.preGenPExecState = (U32)getCurrentPreGenPState(); broadcastData( MSG_ID_FP_PRE_GEN_WATER_MODE_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( PRE_GENP_MODE_DATA_T ) ); preGenPDataPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The requestPreGenStart function handles an DD request to start (go to pre gen permeate mode). * @details \b Inputs: standbyState * @details \b Outputs: pendingStartRORequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ BOOL requestPreGenStart( void ) { BOOL result = FALSE; if ( ( FP_MODE_STAN == getCurrentOperationMode() ) && ( FP_STANDBY_MODE_STATE_IDLE == getCurrentStandbyState() ) ) { result = TRUE; pendingStartPreGenRequest = TRUE; requestNewOperationMode( FP_MODE_PGEN ); } return result; } /*********************************************************************//** * @brief * The requestPreGenStop function handles an DD request to stop (go to standby mode). * @details \b Inputs: none * @details \b Outputs: pendingStartPreGenRequest * @return TRUE if request accepted, FALSE if not. *************************************************************************/ BOOL requestPreGenStop( void ) { BOOL result = TRUE; pendingStartPreGenRequest = FALSE; signalROPumpHardStop(); if ( TRUE == isBoostPumpInstalled() ) { signalBoostPumpHardStop(); } requestNewOperationMode( FP_MODE_STAN ); return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testPreGenDataPublishIntervalOverride function overrides the * DD generate water mode data publish interval. * @details \b Inputs: preGenPDataPublishInterval * @details \b Outputs: preGenPDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the FP generate water data publish interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testPreGenDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &preGenPDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /**@}*/