/************************************************************************** * * Copyright (c) 2025-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 FlushPermeate.c * * @author (last) “Raghu * @date (last) 14-Oct-2025 * * @author (original) Michael Garthwaite * @date (original) 08-Sep-2025 * ***************************************************************************/ #include "BoostPump.h" #include "Conductivity.h" #include "FlushPermeate.h" #include "FPOperationModes.h" #include "MessageSupport.h" #include "Messaging.h" #include "PermeateTank.h" #include "Pressure.h" #include "ROPump.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup FPPermeateFlush * @{ */ // ********** private definitions ********** #define PERMEATE_FLUSH_MAX_TIMEOUT ( 600 * MS_PER_SECOND ) ///< Max override timeout for 10 minutes #define PERMEATE_FLUSH_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen water mode data published. #define PERMEATE_FLUSH_TIMEOUT ( 120 * MS_PER_SECOND ) ///< Permeate flush timer (in ms) #define PERMEATE_FLUSH_ALARM_TIMEOUT ( 180 * MS_PER_SECOND ) ///< Permeate flush alarm timer (in ms) #define PERMEATE_FLUSH_RO_PUMP_TGT_ML 700 ///< Pressure target in ml/min for the RO pump during permeate flush. #define PERMEATE_FLUSH_BOOST_PUMP_TGT_PSI 25 ///< Pressure target in PSI for the boost pump during permeate flush. #define PERMEATE_FLUSH_CONDUCTIVITY_THRESHOLD 200.0F ///< Conductivity alarm threshold for permeate flush. // ********** private data ********** static FP_PERM_FLUSH_STATE_T permeateFlushState; ///< Currently active Permeate flush state. static U32 permeateFlushDataPublicationTimerCounter; ///< Used to schedule Permeate flush data publication to CAN bus. static OVERRIDE_U32_T permeateFlushDataPublishInterval; ///< Permeate Flush mode data publish interval. static OVERRIDE_U32_T permeateFlushTimeout; ///< Permeate Flush timeout value static OVERRIDE_U32_T permeateFlushAlarmTimeout; static U32 permeateFlushTimer; ///< Permeate Flush timeout timer static U32 permeateFlushAlarmTimer; static BOOL pendingStartPermeateFlushRequest; ///< signal to start flushing. static BOOL isFlushComplete; ///< Permeate Flush complete BOOL // ********** private function prototypes ********** static void publishPermeateFlushData( void ); static FP_PERM_FLUSH_STATE_T handlePermeateFlushProgressState( void ); static FP_PERM_FLUSH_STATE_T handlePermeateFlushPausedState( void ); static void setPermeateFlushTransition( FP_PERM_FLUSH_STATE_T state ); static U32 getPermeateFlushTimeout( void ); static U32 getPermeateFlushAlarmTimeout( void ); static U32 getPermeateFlushPublishInterval( void ); /*********************************************************************//** * @brief * The initPermeateFlush function initializes the Permeate flush unit. * @details \b Inputs: none * @details \b Outputs: Permeate flush unit initialized * @return none *************************************************************************/ void initPermeateFlush( void ) { permeateFlushState = PERM_FLUSH_PAUSED; permeateFlushDataPublishInterval.data = PERMEATE_FLUSH_DATA_PUBLISH_INTERVAL; permeateFlushDataPublishInterval.ovData = PERMEATE_FLUSH_DATA_PUBLISH_INTERVAL; permeateFlushDataPublishInterval.ovInitData = 0; permeateFlushDataPublishInterval.override = OVERRIDE_RESET; permeateFlushTimeout.data = PERMEATE_FLUSH_TIMEOUT; permeateFlushTimeout.ovData = PERMEATE_FLUSH_TIMEOUT; permeateFlushTimeout.ovInitData = 0; permeateFlushTimeout.override = OVERRIDE_RESET; permeateFlushAlarmTimeout.data = PERMEATE_FLUSH_ALARM_TIMEOUT; permeateFlushAlarmTimeout.ovData = PERMEATE_FLUSH_ALARM_TIMEOUT; permeateFlushAlarmTimeout.ovInitData = 0; permeateFlushAlarmTimeout.override = OVERRIDE_RESET; permeateFlushDataPublicationTimerCounter = 0; permeateFlushTimer = 0; permeateFlushAlarmTimer = 0; isFlushComplete = FALSE; pendingStartPermeateFlushRequest = FALSE; } /*********************************************************************//** * @brief * The execPermeateFlush function executes the Permeate flush state machine * and publishes Permeate flush data. * @details \b Inputs: permeateFlushState * @details \b Outputs: permeateFlushState * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if in invalid flush state * @return none *************************************************************************/ void execPermeateFlush( void ) { FP_PERM_FLUSH_STATE_T prevState = permeateFlushState; switch ( permeateFlushState ) { case PERM_FLUSH_IN_PROGRESS: permeateFlushState = handlePermeateFlushProgressState(); break; case PERM_FLUSH_PAUSED: permeateFlushState = handlePermeateFlushPausedState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, FP_FAULT_ID_FP_INVALID_PERMEATE_FLUSH_STATE, (U32)permeateFlushState ) permeateFlushState = PERM_FLUSH_PAUSED; break; } if ( prevState != permeateFlushState ) { setPermeateFlushTransition( permeateFlushState ); } // publish Permeate flush data on interval publishPermeateFlushData(); } /*********************************************************************//** * @brief * The handlePermeateFlushProgressState handles the in progress state of Permeate flush * @details \b Inputs: permeateFlushTimer, permeateFlushAlarmTimer * @details \b Outputs: isFlushComplete * @return the next state of Permeate flush state *************************************************************************/ static FP_PERM_FLUSH_STATE_T handlePermeateFlushProgressState( void ) { FP_PERM_FLUSH_STATE_T state = PERM_FLUSH_IN_PROGRESS; // if ( TRUE == 1 ))// TODO Alarm and Stop State Rework // { // state = PERM_FLUSH_PAUSED; // } if( TRUE == didTimeout( permeateFlushTimer, getPermeateFlushTimeout() ) ) { F32 p18conductivity = getFilteredConductivity( P18_COND ); if( PERMEATE_FLUSH_CONDUCTIVITY_THRESHOLD > p18conductivity ) { isFlushComplete = TRUE; state = PERM_FLUSH_PAUSED; } // If conductivity is not in range, continue to monitor until timeout else { if( TRUE == didTimeout( permeateFlushAlarmTimer, getPermeateFlushAlarmTimeout() ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_PERMEATE_FLUSH_CONDUCTIVITY_TIMEOUT, PERMEATE_FLUSH_CONDUCTIVITY_THRESHOLD, p18conductivity) state = PERM_FLUSH_PAUSED; } } } return state; } /*********************************************************************//** * @brief * The handlePermeateFlushProgressState handles the in progress state of Permeate flush * @details \b Inputs: pendingStartPermeateFlushRequest * @details \b Outputs: isFlushComplete * @return the next state of Permeate flush state *************************************************************************/ static FP_PERM_FLUSH_STATE_T handlePermeateFlushPausedState( void ) { FP_PERM_FLUSH_STATE_T state = PERM_FLUSH_PAUSED; if ( TRUE == pendingStartPermeateFlushRequest ) { isFlushComplete = FALSE; state = PERM_FLUSH_IN_PROGRESS; } return state; } /*********************************************************************//** * @brief * The setPermeateFlushTransition function sets the actuators and variables * for the state transition in Permeate flush mode. * @details Inputs: Valve states, Pump speed * @details Outputs: Actuate valves, pumps as desired. * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if in invalid flush transition * @param state Permeate flush state enum * @return none *************************************************************************/ static void setPermeateFlushTransition( FP_PERM_FLUSH_STATE_T state ) { // Execute on running state switch( state ) { case PERM_FLUSH_IN_PROGRESS: setValveState( M4_VALV, VALVE_STATE_OPEN ); setValveState( M12_VALV, VALVE_STATE_OPEN ); setValveState( P6_VALV, VALVE_STATE_CLOSED ); setValveState( P11_VALV, VALVE_STATE_OPEN ); setValveState( P33_VALV, VALVE_STATE_CLOSED ); setValveState( P34_VALV, VALVE_STATE_CLOSED ); setValveState( P37_VALV, VALVE_STATE_CLOSED ); setValveState( P39_VALV, VALVE_STATE_OPEN ); startPermeateTankControl(); if ( TRUE == isBoostPumpInstalled() ) { setBoostPumpTargetPressure( PERMEATE_FLUSH_BOOST_PUMP_TGT_PSI ); } setROPumpTargetFlowRateMLPM( PERMEATE_FLUSH_RO_PUMP_TGT_ML, TRUE ); permeateFlushTimer = getMSTimerCount(); permeateFlushAlarmTimer = getMSTimerCount(); pendingStartPermeateFlushRequest = FALSE; break; case PERM_FLUSH_PAUSED: // Stop pumps and close only if we alarm ( pause ) during flush. if ( FALSE == isPermeateFlushComplete() ) { setValveState( M4_VALV, VALVE_STATE_CLOSED ); setValveState( M12_VALV, VALVE_STATE_CLOSED ); setValveState( P6_VALV, VALVE_STATE_CLOSED ); setValveState( P11_VALV, VALVE_STATE_CLOSED ); setValveState( P33_VALV, VALVE_STATE_CLOSED ); setValveState( P34_VALV, VALVE_STATE_CLOSED ); setValveState( P37_VALV, VALVE_STATE_CLOSED ); setValveState( P39_VALV, VALVE_STATE_CLOSED ); if ( TRUE == isBoostPumpInstalled() ) { signalBoostPumpHardStop(); } signalROPumpHardStop(); } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, FP_FAULT_ID_FP_INVALID_PERMEATE_FLUSH_STATE, state ) break; } } /*********************************************************************//** * @brief * The signalStartPermeateFlush function signals the FP to start Permeate flush. * @details \b Inputs: none * @details \b Outputs: pendingStartPermeateFlushRequest * @return none *************************************************************************/ void signalStartPermeateFlush( void ) { if ( PERM_FLUSH_PAUSED == getCurrentPermeateFlushState() ) { pendingStartPermeateFlushRequest = TRUE; } } /*********************************************************************//** * @brief * The resetFilterFlushSignals function resets the signal values for * FP filter flush. * @details \b Inputs: none * @details \b Outputs: pendingStartFilterFlushRequest, isFlushComplete * @return none *************************************************************************/ void resetPermeateFlushSignals( void ) { pendingStartPermeateFlushRequest = FALSE; isFlushComplete = FALSE; } /*********************************************************************//** * @brief * The getCurrentPermeateFlushState function returns the current state of * Permeate flush. * @details \b Inputs: permeateFlushState * @details \b Outputs: none * @return the current state of Permeate flush *************************************************************************/ FP_PERM_FLUSH_STATE_T getCurrentPermeateFlushState( void ) { return permeateFlushState; } /*********************************************************************//** * @brief * The isPermeateFlushComplete function returns the state of completeness * of Permeate Flush. * @details \b Inputs: isFlushComplete * @details \b Outputs: none * @return TRUE if permeate flush is complete, FALSE if not. *************************************************************************/ BOOL isPermeateFlushComplete( void ) { return isFlushComplete; } /*********************************************************************//** * @brief * The getPermeateFlushTimeout function gets the generate water * mode data publish interval. * @details \b Inputs: PermeateFlushTimeOut * @details \b Outputs: none * @return the timeout timer for Permeate flush. *************************************************************************/ static U32 getPermeateFlushTimeout( void ) { U32 result = getU32OverrideValue( &permeateFlushTimeout ); return result; } /*********************************************************************//** * @brief * The getPermeateFlushTimeout function gets the generate water * mode data publish interval. * @details \b Inputs: PermeateFlushTimeOut * @details \b Outputs: none * @return the timeout timer for Permeate flush. *************************************************************************/ static U32 getPermeateFlushAlarmTimeout( void ) { U32 result = getU32OverrideValue( &permeateFlushAlarmTimeout ); return result; } /*********************************************************************//** * @brief * The getPermeateFlushPublishInterval function gets the Permeate flush * mode data publish interval. * @details \b Inputs: permeateFlushDataPublishInterval * @details \b Outputs: none * @return the interval at Permeate flush mode data being published. *************************************************************************/ static U32 getPermeateFlushPublishInterval( void ) { U32 result = getU32OverrideValue( &permeateFlushDataPublishInterval ); return result; } /*********************************************************************//** * @brief * The publishPermeateFlushData function broadcasts the Permeate flush * mode data at defined interval. * @details \b Inputs: permeateFlushDataPublicationTimerCounter * @details \b Outputs: fp Permeate flush data broadcast message sent * @details \b Message \Sent: MSG_ID_FP_PERMEATE_FLUSH_DATA to publish the * Permeate flush mode data. * @return none *************************************************************************/ static void publishPermeateFlushData( void ) { if ( ++permeateFlushDataPublicationTimerCounter >= getPermeateFlushPublishInterval() ) { PERM_FLUSH_DATA_T data; data.permeateFlushExecState = (U32)getCurrentPermeateFlushState(); broadcastData( MSG_ID_FP_PERMEATE_FLUSH_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( PERM_FLUSH_DATA_T ) ); permeateFlushDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testPermeateFlushDataPublishIntervalOverride function overrides the * FP Permeate flush mode data publish interval. * @details \b Inputs: permeateFlushDataPublishInterval * @details \b Outputs: permeateFlushDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the FP Permeate flush data publish interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testPermeateFlushDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &permeateFlushDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /*********************************************************************//** * @brief * The testPermeateFlushTimerOverride function overrides the * FP Permeate flush timeout value. * @details \b Inputs: permeateFlushTimeout * @details \b Outputs: permeateFlushTimeout * @param Override message from Dialin which includes the interval * (in ms) to override the FP Permeate flush timeout to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testPermeateFlushTimerOverride( MESSAGE_T *message ) { BOOL result = u32Override( message, &permeateFlushTimeout, 0, PERMEATE_FLUSH_MAX_TIMEOUT ); return result; } /*********************************************************************//** * @brief * The testPermeateFlushAlarmTimerOverride function overrides the * FP Permeate flush timeout value. * @details \b Inputs: permeateFlushAlarmTimeout * @details \b Outputs: permeateFlushAlarmTimeout * @param Override message from Dialin which includes the interval * (in ms) to override the FP Permeate flush timeout to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testPermeateFlushAlarmTimerOverride( MESSAGE_T *message ) { BOOL result = u32Override( message, &permeateFlushAlarmTimeout, 0, PERMEATE_FLUSH_MAX_TIMEOUT ); return result; } /**@}*/