/************************************************************************** * * Copyright (c) 2024-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 ModeGenPermeate.c * * @author (last) Michael Garthwaite * @date (last) 28-Feb-2025 * * @author (original) Michael Garthwaite * @date (original) 28-Feb-2025 * ***************************************************************************/ #include "DDInterface.h" #include "Level.h" #include "ModeGenPermeate.h" #include "ModeStandby.h" #include "MessageSupport.h" #include "Messaging.h" #include "OperationModes.h" #include "TaskGeneral.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup ROGenPermeateMode * @{ */ // ********** private definitions ********** #define GEN_PERMEATE_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the gen permeate mode data published. #define GEN_PERMEATE_TIMEOUT_MS ( 6 * MS_PER_SECOND ) ///< state switch timeout (in ms) // ********** private data ********** static RO_GENP_MODE_STATE_T genPermeateState; ///< Currently active generate permeate water state. static U32 genPermeateDataPublicationTimerCounter; ///< Used to schedule generate permeate data publication to CAN bus. static OVERRIDE_U32_T genPermeateDataPublishInterval; ///< Generate permeate mode data publish interval. static U32 stateDelayTime; ///< Time stamp to track delay before valve switch. // ********** private function prototypes ********** static void publishGenPermeateModeData( void ); static RO_GENP_MODE_STATE_T handleGenPStartState( void ); static RO_GENP_MODE_STATE_T handleGenPWaterFullState( void ); static RO_GENP_MODE_STATE_T handleGenPWaterLowState( void ); static void setModeGenPStateTransition( RO_GENP_MODE_STATE_T state ); /*********************************************************************//** * @brief * The initGenPermeateMode function initializes the dialysis permeate mode unit. * @details \b Inputs: none * @details \b Outputs: Gen permeate mode unit initialized * @return none *************************************************************************/ void initGenPermeateMode( void ) { RO_GENP_MODE_STATE_T genPermeateState = RO_GENP_STATE_START; genPermeateDataPublishInterval.data = GEN_PERMEATE_DATA_PUBLISH_INTERVAL; genPermeateDataPublishInterval.ovData = GEN_PERMEATE_DATA_PUBLISH_INTERVAL; genPermeateDataPublishInterval.ovInitData = 0; genPermeateDataPublishInterval.override = OVERRIDE_RESET; genPermeateDataPublicationTimerCounter = 0; } /*********************************************************************//** * @brief * The transitionToGenPermeateMode function prepares for transition to gen * permeate mode. * @details \b Inputs: none * @details \b Outputs: none * @return initial state *************************************************************************/ U32 transitionToGenPermeateMode( void ) { initGenPermeateMode(); setCurrentSubState( genPermeateState ); return genPermeateState; } /*********************************************************************//** * @brief * The execGenPermeateMode function executes the Gen permeate mode state machine. * @details \b Inputs: none * @details \b Outputs: Gen permeate mode state machine executed * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT when wrong gen permeate state invoked. * @return current state. *************************************************************************/ U32 execGenPermeateMode( void ) { LEVEL_STATE_T level = getLevelStatus(); if ( LEVEL_STATE_ILLEGAL == level ) { // TODO: Raise illegal level alarm } // execute current gen permeate state switch ( genPermeateState ) { case RO_GENP_STATE_START: genPermeateState = handleGenPStartState(); break; case RO_GENP_WATER_LOW_STATE: genPermeateState = handleGenPWaterLowState(); break; case RO_GENP_WATER_FULL_STATE: genPermeateState = handleGenPWaterFullState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_RO_INVALID_GENP_STATE, genPermeateState ) break; } //Publish Gen permeate mode data publishGenPermeateModeData(); return genPermeateState; } /*********************************************************************//** * @brief * The setModeGenPStateTransition function sets the actuators and variables * for the state transition in generate permeate mode. * @details Inputs: Valve states, Pump speed * @details Outputs: Actuate valves, pumps as desired. * @param state gen permeate state enum * @return none *************************************************************************/ static void setModeGenPStateTransition( RO_GENP_MODE_STATE_T state ) { // Execute on running state switch( state ) { case RO_GENP_STATE_START: // Do nothing break; case RO_GENP_WATER_LOW_STATE: setValveState( M4_VALV,VALVE_STATE_OPEN ); setValveState( M7_VALV,VALVE_STATE_CLOSED ); setValveState( P6_VALV,VALVE_STATE_CLOSED ); setValveState( P39_VALV,VALVE_STATE_OPEN ); setValveState( P11_VALV, VALVE_STATE_OPEN ); stateDelayTime = getMSTimerCount(); break; case RO_GENP_WATER_FULL_STATE: //set setValveState( M4_VALV,VALVE_STATE_CLOSED ); setValveState( M7_VALV,VALVE_STATE_CLOSED ); setValveState( P6_VALV,VALVE_STATE_CLOSED ); setValveState( P39_VALV,VALVE_STATE_OPEN ); setValveState( P11_VALV, VALVE_STATE_CLOSED ); stateDelayTime = getMSTimerCount(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_RO_INVALID_GENP_STATE, state ) break; } } /*********************************************************************//** * @brief * The handleGenPStartState handles the initial state of gen permeate. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of gen permeate mode *************************************************************************/ static RO_GENP_MODE_STATE_T handleGenPStartState( void ) { RO_GENP_MODE_STATE_T state = RO_GENP_STATE_START; LEVEL_STATE_T level = getLevelStatus(); U16 ropwm = (U16)getDDPermeateFlowRate(); if ( LEVEL_STATE_HIGH == level ) { setModeGenPStateTransition( RO_GENP_WATER_FULL_STATE ); state = RO_GENP_WATER_FULL_STATE; } else if ( ( LEVEL_STATE_MEDIUM == level ) || ( LEVEL_STATE_LOW == level ) ) { setModeGenPStateTransition( RO_GENP_WATER_LOW_STATE ); state = RO_GENP_WATER_LOW_STATE; } return state; } /*********************************************************************//** * @brief * The handleGenPWaterLowState handles the low water state of gen permeate. * @details \b Inputs: stateDelayTime * @details \b Outputs: none * @return the next state of gen permeate mode *************************************************************************/ static RO_GENP_MODE_STATE_T handleGenPWaterLowState( void ) { RO_GENP_MODE_STATE_T state = RO_GENP_WATER_LOW_STATE; LEVEL_STATE_T level = getLevelStatus(); if ( LEVEL_STATE_HIGH == level ) { setModeGenPStateTransition( RO_GENP_WATER_FULL_STATE ); state = RO_GENP_WATER_FULL_STATE; } else if ( level <= LEVEL_STATE_MEDIUM ) { // expected state. No action required. // If level is low we still want to fill. } return state; } /*********************************************************************//** * @brief * The handleGenPWaterFullState handles the high water state of gen permeate. * @details \b Inputs: none * @details \b Outputs: none * @return the next state of gen permeate mode *************************************************************************/ static RO_GENP_MODE_STATE_T handleGenPWaterFullState( void ) { RO_GENP_MODE_STATE_T state = RO_GENP_WATER_FULL_STATE; LEVEL_STATE_T level = getLevelStatus(); if ( LEVEL_STATE_LOW == level ) { // TODO: Turn off heater. } else if ( ( level >= LEVEL_STATE_MEDIUM ) && ( TRUE == didTimeout( stateDelayTime, GEN_PERMEATE_TIMEOUT_MS ) ) ) { setModeGenPStateTransition( RO_GENP_WATER_LOW_STATE ); state = RO_GENP_WATER_LOW_STATE; } return state; } /** * *******************************************************************//** * @brief * The getCurrentGenPermeateState function returns the current state of the * gen dialysate mode. * @details \b Inputs: genDialysateState * @details \b Outputs: none * @return the current state of gen dialysate mode *************************************************************************/ RO_GENP_MODE_STATE_T getCurrentGenPermeateState( void ) { return genPermeateState; } /*********************************************************************//** * @brief * The getGenPermeateDataPublishInterval function gets the generate permeate * mode data publish interval. * @details \b Inputs: genPermeateDataPublishInterval * @details \b Outputs: none * @return the interval at generate permeate mode data being published. *************************************************************************/ static U32 getGenPermeateDataPublishInterval( void ) { U32 result = getU32OverrideValue( &genPermeateDataPublishInterval ); return result; } /*********************************************************************//** * @brief * The publishGenDialysateModeData function broadcasts the generate dialysate * mode data at defined interval. * @details \b Inputs: genDialysateDataPublicationTimerCounter * @details \b Outputs: DD generate dialysate data broadcast message sent * @details \b Message \Sent: MSG_ID_DD_GEN_DIALYSATE_MODE_DATA to publish the * generate dialysate mode data. * @return none *************************************************************************/ static void publishGenPermeateModeData( void ) { if ( ++genPermeateDataPublicationTimerCounter >= getGenPermeateDataPublishInterval() ) { GEN_PERMEATE_MODE_DATA_T data; data.genPermeateExecState = (U32)getCurrentGenPermeateState(); data.setFlowRate = (F32)getDDPermeateFlowRate(); broadcastData( MSG_ID_DD_GEN_DIALYSATE_MODE_DATA, COMM_BUFFER_OUT_CAN_RO_BROADCAST, (U08*)&data, sizeof( GEN_PERMEATE_MODE_DATA_T ) ); genPermeateDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testROGenPermeateDataPublishIntervalOverride function overrides the * DD generate permeate mode data publish interval. * @details \b Inputs: genDialysateDataPublishInterval * @details \b Outputs: genDialysateDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the RO generate permeate data publish interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testROGenPermeateDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &genPermeateDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /**@}*/