/************************************************************************** * * 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 Temperature.c * * @author (last) Sean Nash * @date (last) 09-Nov-2024 * * @author (original) Sean Nash * @date (original) 09-Nov-2024 * ***************************************************************************/ #include "AlarmMgmtFP.h" #include "Messaging.h" #include "MessageSupport.h" #include "ModeGenPermeate.h" #include "ModeGenPermeateDefeatured.h" #include "ModePreGenPermeate.h" #include "ModePreGenPermeateDefeatured.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PressureSensor.h" #include "Temperature.h" #include "Timers.h" #include "TaskPriority.h" #include "Utilities.h" /** * @addtogroup Temperature * @{ */ // ********** private definitions ********** #define ADC_FPGA_READ_DELAY 30U ///< Delay in ms before reading the ADC values from FPGA. #define TEMP_SENSORS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Temperature sensors publish data time interval. #define TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors FPGA error timeout in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 30 ///< Data publish counter start count. #define TEMPERATURE_INLET_LOW_THRESHOLD 5.0F #define TEMPERATURE_INLET_HIGH_THRESHOLD 30.0F #define TEMPERATURE_INLET_PERSISTENCE_TIMER ( 5 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) #define TEMPERATURE_INLET_PERSISTENCE_CLEAR ( 5 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) /// Temperature sensor exec states. typedef enum tempSensors_Exec_States { TEMPSENSORS_EXEC_STATE_START = 0, ///< Temperature sensors exec start TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES, ///< Temperature sensors exec get ADC values NUM_OF_TEMPSENSORS_EXEC_STATES, ///< Total number of exec states } TEMPSENSORS_EXEC_STATES_T; // ********** private data ********** static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state. static U32 startTime; ///< star time to read FPGA values. static U32 dataPublicationTimerCounter; ///< Temperature sensors data publish timer counter. static OVERRIDE_U32_T tempSensorsPublishInterval; ///< Temperature sensors publish time interval override. // ********** private function prototypes ********** static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ); static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ); static void publishTemperatureSensorsData( void ); static void monitorTemperatureSenors( void ); static void monitorOperationModeAlarms( FP_OP_MODE_T opMode ); static void monitorPreGenAlarms( void ); static void monitorPreGenDefAlarms( void ); static void monitorGenPAlarms( void ); /*********************************************************************//** * @brief * The initTemperature function initializes the temperature unit. * @details \b Inputs: none * @details \b Outputs: temperature unit variables initialized. * @return none *************************************************************************/ void initTemperature( void ) { startTime = 0; tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; tempSensorsPublishInterval.data = TEMP_SENSORS_DATA_PUBLISH_INTERVAL; tempSensorsPublishInterval.ovData = TEMP_SENSORS_DATA_PUBLISH_INTERVAL; tempSensorsPublishInterval.ovInitData = 0; tempSensorsPublishInterval.override = OVERRIDE_RESET; // Initialize the temperature sensors initTemperatureSensors(); initPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, TEMPERATURE_INLET_PERSISTENCE_CLEAR, TEMPERATURE_INLET_PERSISTENCE_TIMER ); initPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, TEMPERATURE_INLET_PERSISTENCE_CLEAR, TEMPERATURE_INLET_PERSISTENCE_TIMER ); } /*********************************************************************//** * @brief * The execTemperatureSensorsSelfTest function runs the TemperatureSensors * POST during the self-test. * @details \b Inputs: none * @details \b Outputs: none * @return tempSensorsSelfTestState which is the status of the self test *************************************************************************/ //SELF_TEST_STATUS_T execTemperatureSensorsSelfTest( void ) //{ // SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; // // //BOOL calStatus = getNVRecord2Driver( GET_CAL_TEMP_SENSORS, (U08*)&tempSensorCalRecord, sizeof( DD_TEMP_SENSORS_CAL_RECORD_T ), // // NUM_OF_CAL_DATA_TEMP_SENSORS, ALARM_ID_DD_TEMPERATURE_SENSORS_INVALID_CAL_RECORD ); // BOOL calStatus = TRUE; // // if ( TRUE == calStatus ) // { // result = SELF_TEST_STATUS_PASSED; // } // else // { // result = SELF_TEST_STATUS_FAILED; // } // // return result; //} /*********************************************************************//** * @brief * The execTemperatureSensors function executes the temperature sensors' * state machine. * @details \b Inputs: tempSensorsExecState * @details \b Outputs: tempSensorsExecState * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid temperature * sensor state is seen. * @return none *************************************************************************/ void execTemperatureSensors( void ) { // Check if a new calibration is available // if ( TRUE == isNewCalibrationRecordAvailable() ) // { // getNVRecord2Driver( GET_CAL_TEMP_SENSORS, (U08*)&tempSensorCalRecord, sizeof( DD_TEMP_SENSORS_CAL_RECORD_T ), // NUM_OF_CAL_DATA_TEMP_SENSORS, ALARM_ID_DD_TEMPERATURE_SENSORS_INVALID_CAL_RECORD ); // } // Read the sensors all the time switch ( tempSensorsExecState ) { case TEMPSENSORS_EXEC_STATE_START: tempSensorsExecState = handleExecStart(); break; case TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES: tempSensorsExecState = handleExecGetADCValues(); break; default: // SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, tempSensorsExecState ); // tempSensorsExecState = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; break; } // Monitor the temperature values monitorTemperatureSenors(); // Publish the data publishTemperatureSensorsData(); } /*********************************************************************//** * @brief * The handleExecStart function waits for a period of time and switches to * the state that reads the ADC values from FPGA. * @details \b Inputs: startTime * @details \b Outputs: startTime, baroCoeffsWaitToRcvStartTime * @return the next state of the state machine *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ) { TEMPSENSORS_EXEC_STATES_T state = TEMPSENSORS_EXEC_STATE_START; if ( 0 == startTime ) { startTime = getMSTimerCount(); } // A delay to let FPGA to boot up else if ( TRUE == didTimeout( startTime, ADC_FPGA_READ_DELAY ) ) { startTime = 0; state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; } return state; } /*********************************************************************//** * @brief * The handleExecGetADCValues function reads the ADC values from FPGA and * at the specified time intervals and calls required functions to calculate * the actual tempetature from the raw ADC values. * @details \b Inputs: FPGA * @details \b Outputs: temperature value. * @return the next state of the state machine *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ) { // Read temperature sensors readTemperatureSensors(); return TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; } /*********************************************************************//** * @brief * The monitorTemperatureSensors function monitors the temperature sensors' * temperature value and raises an alarm if any of them are out of range * for more than the specified time. * @details \b Inputs: tempSensors * @details \b Outputs: tempSensors * @details \b Alarms: ALARM_ID_DD_TEMPERATURE_SENSOR_OUT_OF_RANGE when the * measured temperature exceeds the maximum limit temperature. * @return none *************************************************************************/ static void monitorTemperatureSenors( void ) { monitorOperationModeAlarms( getCurrentOperationMode() ); } static void monitorOperationModeAlarms( FP_OP_MODE_T opMode ) { switch ( opMode ) { case FP_MODE_FAUL: break; case FP_MODE_SERV: break; case FP_MODE_INIT: break; case FP_MODE_STAN: break; case FP_MODE_PGEN: monitorPreGenAlarms(); break; case FP_MODE_GENP: monitorGenPAlarms(); break; case FP_MODE_DPGW: monitorPreGenDefAlarms(); break; case FP_MODE_DEGW: break; default: // SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, tempSensorsExecState ); // tempSensorsExecState = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; break; } } /*********************************************************************//** * @brief * The monitorPreGenAlarms function checks temperature alarm conditions for alarms that are * monitored in Pre-Generate Permeate mode * @details \b Inputs: none * @details \b Outputs: none * @return none *************************************************************************/ static void monitorPreGenAlarms( void ) { FP_PRE_GENP_MODE_STATE_T preGenState = getCurrentPreGenPState(); F32 temperatureP10 = getTemperatureValue( P10_TEMP ); BOOL isTempOutOfLowRange = FALSE; BOOL isTempOutOfHighRange = FALSE; if ( ( preGenState > FP_PRE_GENP_FILTER_FLUSH ) && ( preGenState != FP_PRE_GENP_PAUSED ) ) { isTempOutOfLowRange = ( ( temperatureP10 < TEMPERATURE_INLET_LOW_THRESHOLD ) ? TRUE : FALSE); isTempOutOfHighRange = ( ( temperatureP10 > TEMPERATURE_INLET_HIGH_THRESHOLD ) ? TRUE : FALSE); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureP10, TEMPERATURE_INLET_LOW_THRESHOLD ); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureP10, TEMPERATURE_INLET_HIGH_THRESHOLD ); // TODO - Check M1 temp } } /*********************************************************************//** * @brief * The monitorGenPAlarms function checks temperature alarm conditions for alarms that are * monitored in Generate Permeate mode * @details \b Inputs: none * @details \b Outputs: none * @return none *************************************************************************/ static void monitorGenPAlarms( void ) { FP_GENP_MODE_STATE_T genState = getCurrentGenPermeateState(); F32 temperatureP10 = getTemperatureValue( P10_TEMP ); BOOL isTempOutOfLowRange = FALSE; BOOL isTempOutOfHighRange = FALSE; isTempOutOfLowRange = ( ( temperatureP10 < TEMPERATURE_INLET_LOW_THRESHOLD ) ? TRUE : FALSE); isTempOutOfHighRange = ( ( temperatureP10 > TEMPERATURE_INLET_HIGH_THRESHOLD ) ? TRUE : FALSE); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureP10, TEMPERATURE_INLET_LOW_THRESHOLD ); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureP10, TEMPERATURE_INLET_HIGH_THRESHOLD ); // TODO - Check M1 temp } /*********************************************************************//** * @brief * The monitorPreGenDefAlarms function checks temperature alarm conditions for alarms that are * monitored in Pre-Generate Permeate, Defeatured mode * @details \b Inputs: none * @details \b Outputs: none * @return none *************************************************************************/ static void monitorPreGenDefAlarms( void ) { //FP_PRE_GENP_DEF_MODE_STATE_T preGenDefState; F32 temperatureM4 = getTemperatureValue( M4_TEMP ); BOOL isTempOutOfLowRange = FALSE; BOOL isTempOutOfHighRange = FALSE; //if ( preGenDefState == FP_PRE_GENP_DEF_INLET_WATER_CHECK ) isTempOutOfLowRange = ( ( temperatureM4 < TEMPERATURE_INLET_LOW_THRESHOLD ) ? TRUE : FALSE); isTempOutOfHighRange = ( ( temperatureM4 > TEMPERATURE_INLET_HIGH_THRESHOLD ) ? TRUE : FALSE); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_LOW_RANGE, isTempOutOfLowRange, temperatureM4, TEMPERATURE_INLET_LOW_THRESHOLD ); checkPersistentAlarm( ALARM_ID_FP_INLET_TEMPERATURE_OUT_HIGH_RANGE, isTempOutOfHighRange, temperatureM4, TEMPERATURE_INLET_HIGH_THRESHOLD ); } /*********************************************************************//** * @brief * The publishTemperatureSensorsData function broadcasts the temperature * sensors data at the publication interval. * @details \b Inputs: dataPublicationTimerCounter and publish interval time. * @details \b Outputs: dataPublicationTimerCounter * @details \b Message \b Sent: MSG_ID_DD_TEMPERATURE_DATA publishes the temperature * data in a periodic interval. * @return none *************************************************************************/ static void publishTemperatureSensorsData( void ) { if ( ++dataPublicationTimerCounter >= getU32OverrideValue( &tempSensorsPublishInterval ) ) { TEMPERATURE_SENSORS_DATA_T data; data.p10Temp = getTemperatureValue( P10_TEMP ); data.p19Temp = getTemperatureValue( P19_TEMP ); data.m1Temp = getFilteredPressureSensorTemperature( M1_PRES ); data.m3Temp = getFilteredPressureSensorTemperature( M3_PRES ); data.p8Temp = getFilteredPressureSensorTemperature( P8_PRES ); data.p13Temp = getFilteredPressureSensorTemperature( P13_PRES ); data.p17Temp = getFilteredPressureSensorTemperature( P17_PRES ); data.x1Temp = getFilteredPressureSensorTemperature( X1_PRES ); data.x2Temp = getFilteredPressureSensorTemperature( X2_PRES ); data.x3Temp = getFilteredPressureSensorTemperature( X3_PRES ); data.x4Temp = getFilteredPressureSensorTemperature( X4_PRES ); broadcastData( MSG_ID_FP_TEMPERATURE_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); dataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testTemperatureSensorsDataPublishIntervalOverride function overrides the * temperature sensors data publish interval. * @details \b Inputs: none * @details \b Outputs: tempSensorsPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the temperature sensor data broadcast interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testTemperatureSensorsDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &tempSensorsPublishInterval, TASK_PRIORITY_INTERVAL ); return result; } /**@}*/