/************************************************************************** * * 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 ConductivitySensors.c * * @author (last) Vinayakam Mani * @date (last) 10-Sep-2024 * * @author (original) Vinayakam Mani * @date (original) 10-Sep-2024 * ***************************************************************************/ #include // Used for calculating the polynomial calibration equation. #include // For memcpy #include "ConductivitySensors.h" #include "ConductivityTeensy.h" #include "FpgaDD.h" #include "MessageSupport.h" #include "Messaging.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Utilities.h" /** * @addtogroup ConductivitySensors * @{ */ // ********** private definitions ********** #define SIEMENS_TO_MICROSIEMENS_CONVERSION 1000000 ///< Siemens to microSiemens conversion factor. #define COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Conductivity sensors FPGA error timeout in milliseconds. #define COND_SENSORS_READ_ERR_MAX_CNT 255 ///< Conductivity sensors read and error count max value /// Defined states for the conductivity write transaction. typedef enum Conductvity_write_tx_states { CONDUCTIVITY_WRITE_INITIATE = 0, ///< Conductivity sensor write initiate state. CONDUCTIVITY_WRITE_COMPLETE, ///< Conductivity sensor write complete state. NUM_OF_CONDUCTIVITY_WR_STATES ///< Number of conductivity write states. } CONDUCTIVITY_WRITE_STATE_T; /// Defined states for the conductivity read transaction. typedef enum Conductvity_read_tx_states { CONDUCTIVITY_READ_INITIATE = 0, ///< Conductivity sensor read initiate state. CONDUCTIVITY_READ_COMPLETE, ///< Conductivity sensor read complete state. NUM_OF_CONDUCTIVITY_RD_STATES ///< Number of conductivity read states. } CONDUCTIVITY_READ_STATE_T; /// Conductivity Sensor Control group typedef struct { BOOL resetRequested; ///< Flag indicates a reset command for the given conductivity sensor. BOOL initEnable; ///< Flag indicates a enables initialization procedure for the given conductivity sensor. BOOL writeEnable; ///< Flag indicates a enables write transaction for the given conductivity sensor. BOOL readEnable; ///< Flag indicates a enables read transaction for the given conductivity sensor. BOOL writeInProgress; ///< Flag indicates write transaction in progress BOOL readInProgress; ///< Flag indicates read transaction in progress BOOL writeComplete; ///< Flag indicates write transaction complete state. BOOL readComplete; ///< Flag indicates read transaction complete state. U32 writeData; ///< Data to write for the given conductivity sensor. U32 readData; ///< Read data from the given conductivity sensor. CONDUCTIVITY_READ_STATE_T readExecState; ///< Read executive state from the given conductivity sensor. CONDUCTIVITY_WRITE_STATE_T writeExecState; ///< Write executive state from the given conductivity sensor. U16 writeAddress; ///< Write address where the data needs to be written. U16 readAddress; ///< Read address to read the data. } CONDUCTIVITY_SENSOR_CONTROL_T; // ********** private data ********** static OVERRIDE_F32_T currentConductivityReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Current conductivity sensor conductivity readings (overrideable). static OVERRIDE_F32_T currentTemperatureReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Current conductivity sensor temperature readings (overrideable). static OVERRIDE_U32_T lastConductivityReadCounter[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Last conductivity sensor read count (Overrideable). static OVERRIDE_U32_T lastConductivityErrorCounter[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Last conductivity sensor error count (Overrideable). static CONDUCTIVITY_SENSOR_CONTROL_T conductivitySensorControl[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Conductivity sensor Control for reset, init, read and write operations. static const TEENSY_SENSOR_INDEX_T teensySensorMapping[NUM_OF_CONDUCTIVITY_SENSORS] = { [D17_COND] = TEENSY_SENSOR_0, [D27_COND] = TEENSY_SENSOR_1, [D43_COND] = TEENSY_SENSOR_2, [D74_COND] = TEENSY_SENSOR_3, [P9_COND] = TEENSY_SENSOR_4, [P18_COND] = TEENSY_SENSOR_5 }; // ********** private function prototypes ********** static void checkConductivitySensors( void ); static CONDUCTIVITY_READ_STATE_T handleConductivitySensorsReadInitiate( CONDUCTIVITY_SENSORS_T sensorID ); static CONDUCTIVITY_WRITE_STATE_T handleConductivitySensorsWriteComplete( CONDUCTIVITY_SENSORS_T sensorID ); static CONDUCTIVITY_WRITE_STATE_T handleConductivitySensorsWriteInitiate( CONDUCTIVITY_SENSORS_T sensorID ); static CONDUCTIVITY_READ_STATE_T handleConductivitySensorsReadComplete( CONDUCTIVITY_SENSORS_T sensorID ); static TEENSY_SENSOR_INDEX_T getTeensySensorNum( CONDUCTIVITY_SENSORS_T sensorID ); /*********************************************************************//** * @brief * The initConductivitySensors function initializes the ConductivitySensors unit. * @details \b Inputs: none * @details \b Outputs: ConductivitySensors unit variables initialized * @return none *************************************************************************/ void initConductivitySensors( void ) { CONDUCTIVITY_SENSORS_T sensor; // Initialize override structures for each conductivity sensor for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { currentConductivityReadings[ sensor ].data = 0.0F; currentConductivityReadings[ sensor ].ovData = 0.0F; currentConductivityReadings[ sensor ].ovInitData = 0.0F; currentConductivityReadings[ sensor ].override = OVERRIDE_RESET; currentTemperatureReadings[ sensor ].data = 0.0F; currentTemperatureReadings[ sensor ].ovData = 0.0F; currentTemperatureReadings[ sensor ].ovInitData = 0.0F; currentTemperatureReadings[ sensor ].override = OVERRIDE_RESET; lastConductivityReadCounter[ sensor ].data = 0; lastConductivityReadCounter[ sensor ].ovData = 0; lastConductivityReadCounter[ sensor ].ovInitData = 0; lastConductivityReadCounter[ sensor ].override = OVERRIDE_RESET; lastConductivityErrorCounter[ sensor ].data = 0; lastConductivityErrorCounter[ sensor ].ovData = 0; lastConductivityErrorCounter[ sensor ].ovInitData = 0; lastConductivityErrorCounter[ sensor ].override = OVERRIDE_RESET; conductivitySensorControl[ sensor ].initEnable = FALSE; conductivitySensorControl[ sensor ].readAddress = 0; conductivitySensorControl[ sensor ].readComplete = FALSE; conductivitySensorControl[ sensor ].readData = 0; conductivitySensorControl[ sensor ].readEnable = FALSE; conductivitySensorControl[ sensor ].readInProgress = FALSE; conductivitySensorControl[ sensor ].resetRequested = FALSE; conductivitySensorControl[ sensor ].writeAddress = 0; conductivitySensorControl[ sensor ].writeComplete = 0; conductivitySensorControl[ sensor ].writeData = 0; conductivitySensorControl[ sensor ].readExecState = CONDUCTIVITY_READ_INITIATE; conductivitySensorControl[ sensor ].writeExecState = CONDUCTIVITY_WRITE_INITIATE; conductivitySensorControl[ sensor ].writeEnable = FALSE; conductivitySensorControl[ sensor ].writeInProgress = FALSE; } // Initialize the conductivity sensor FPGA alarms initFPGAPersistentAlarm( FPGA_PERS_ERROR_D17_COND_SENSOR, ALARM_ID_DD_D17_COND_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_D27_COND_SENSOR, ALARM_ID_DD_D27_COND_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_D29_COND_SENSOR, ALARM_ID_DD_D29_COND_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_D43_COND_SENSOR, ALARM_ID_DD_D43_COND_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initFPGAPersistentAlarm( FPGA_PERS_ERROR_D74_COND_SENSOR, ALARM_ID_DD_D74_COND_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); //initFPGAPersistentAlarm( FPGA_PERS_ERROR_P9_COND_SENSOR, ALARM_ID_FP_P9_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); //initFPGAPersistentAlarm( FPGA_PERS_ERROR_P18_COND_SENSOR, ALARM_ID_FP_P18_SENSOR_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); initCondTeensy(); } /*********************************************************************//** * @brief * The readConductivitySensors function gets the current conductivity reading * for all conductivity sensors from the FPGA and also reads the freshness * and error counters to verify that the conductivity sensors are being read * by the FPGA without issue. * @note This function should be called periodically to maintain fresh * sensor readings for all conductivity sensors. * @details \b Inputs: FPGA * @details \b Outputs: currentConductivityReadings[],currentTemperatureReadings[], * lastConductivityReadCounter[],lastConductivityErrorCounter[]. * @return none *************************************************************************/ void readConductivitySensors( void ) { // Read raw conductivity currentConductivityReadings[ D17_COND ].data = (F32)getFPGAD17Cond(); currentConductivityReadings[ D27_COND ].data = (F32)getFPGAD27Cond(); currentConductivityReadings[ D29_COND ].data = (F32)getFPGAD29Cond(); currentConductivityReadings[ D43_COND ].data = (F32)getFPGAD43Cond(); currentConductivityReadings[ D74_COND ].data = (F32)getFPGAD74Cond(); currentConductivityReadings[ P9_COND ].data = (F32)getFPGAP9Conductivity(); currentConductivityReadings[ P18_COND ].data = (F32)getFPGAP18Conductivity(); // Read temperature associated to conductivity sensor currentTemperatureReadings[ D17_COND ].data = (F32)getFPGAD17CondTemp(); currentTemperatureReadings[ D27_COND ].data = (F32)getFPGAD27CondTemp(); currentTemperatureReadings[ D29_COND ].data = (F32)getFPGAD29CondTemp(); currentTemperatureReadings[ D43_COND ].data = (F32)getFPGAD43CondTemp(); currentTemperatureReadings[ D74_COND ].data = (F32)getFPGAD74CondTemp(); currentTemperatureReadings[ P9_COND ].data = (F32)getFPGAP9Temperature(); currentTemperatureReadings[ P18_COND ].data = (F32)getFPGAP18Temperature(); // Update read and error counters for each conductivity sensor lastConductivityReadCounter[ D17_COND ].data = (U32)getFPGAD17CondReadCount(); lastConductivityReadCounter[ D27_COND ].data = (U32)getFPGAD27CondReadCount(); lastConductivityReadCounter[ D29_COND ].data = (U32)getFPGAD29CondReadCount(); lastConductivityReadCounter[ D43_COND ].data = (U32)getFPGAD43CondReadCount(); lastConductivityReadCounter[ D74_COND ].data = (U32)getFPGAD74CondReadCount(); lastConductivityReadCounter[ P9_COND ].data = (U32)getFPGAP9ReadCount(); lastConductivityReadCounter[ P18_COND ].data = (U32)getFPGAP18ReadCount(); lastConductivityErrorCounter[ D17_COND ].data = (U32)getFPGAD17CondErrorCount(); lastConductivityErrorCounter[ D27_COND ].data = (U32)getFPGAD27CondErrorCount(); lastConductivityErrorCounter[ D29_COND ].data = (U32)getFPGAD29CondErrorCount(); lastConductivityErrorCounter[ D43_COND ].data = (U32)getFPGAD43CondErrorCount(); lastConductivityErrorCounter[ D74_COND ].data = (U32)getFPGAD74CondErrorCount(); lastConductivityErrorCounter[ P9_COND ].data = (U32)getFPGAP9ErrorCount(); lastConductivityErrorCounter[ P18_COND ].data = (U32)getFPGAP18ErrorCount(); #ifdef ENABLE_ALARM_1 // Monitor conductivity sensor health checkConductivitySensors(); #endif } /*********************************************************************//** * @brief * The checkConductivitySensors function checks the read and error counters for * each conductivity sensor. * @details \b Alarm: ALARM_ID_DD_D17_COND_SENSOR_FPGA_FAULT if the * D17 conductivity sensor is not able to be read. * @details \b Alarm: ALARM_ID_DD_D27_COND_SENSOR_FPGA_FAULT if the * D27 conductivity sensor is not able to be read. * @details \b Alarm: ALARM_ID_DD_D29_COND_SENSOR_FPGA_FAULT if the * D29 conductivity sensor is not able to be read. * @details \b Alarm: ALARM_ID_DD_D43_COND_SENSOR_FPGA_FAULT if the * D43 conductivity sensor is not able to be read. * @details \b Alarm: ALARM_ID_DD_D74_COND_SENSOR_FPGA_FAULT if the * D74 conductivity sensor is not able to be read. * @details \b Inputs: lastConductivityReadCounter, lastConductivityErrorCounter * @details \b Outputs: none * @return none *************************************************************************/ static void checkConductivitySensors( void ) { checkFPGAPersistentAlarms( FPGA_PERS_ERROR_D17_COND_SENSOR, getConductivitySensorReadCount( D17_COND ) ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_D27_COND_SENSOR, getConductivitySensorReadCount( D27_COND ) ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_D29_COND_SENSOR, getConductivitySensorReadCount( D29_COND ) ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_D43_COND_SENSOR, getConductivitySensorReadCount( D43_COND ) ); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_D74_COND_SENSOR, getConductivitySensorReadCount( D74_COND ) ); //checkFPGAPersistentAlarms( FPGA_PERS_ERROR_P9_COND_SENSOR, getConductivitySensorReadCount( P9_COND ) ); //checkFPGAPersistentAlarms( FPGA_PERS_ERROR_P18_COND_SENSOR, getConductivitySensorReadCount( P18_COND ) ); checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_D17_COND_SENSOR, getConductivitySensorErrorCount( D17_COND ) ); checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_D27_COND_SENSOR, getConductivitySensorErrorCount( D27_COND ) ); checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_D29_COND_SENSOR, getConductivitySensorErrorCount( D29_COND ) ); checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_D43_COND_SENSOR, getConductivitySensorErrorCount( D43_COND ) ); checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_D74_COND_SENSOR, getConductivitySensorErrorCount( D74_COND ) ); //checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_P9_COND_SENSOR, getConductivitySensorErrorCount( P9_COND ) ); //checkFPGAPersistentErrorCountAlarm( FPGA_PERS_ERROR_P18_COND_SENSOR, getConductivitySensorErrorCount( P18_COND ) ); } /*********************************************************************//** * @brief * The getConductivityValue function gets the conductivity * value for a given conductivity sensor id. * @details \b Inputs: currentConductivityReadings[] * @details \b Outputs: none * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensorId conductivity sensor id * @return conductivity value *************************************************************************/ F32 getConductivityValue( CONDUCTIVITY_SENSORS_T sensor ) { F32 result = 0.0F; if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { result = currentConductivityReadings[ sensor ].data; if ( OVERRIDE_KEY == currentConductivityReadings[ sensor ].override ) { result = currentConductivityReadings[ sensor ].ovData; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensor ); } return result; } /*********************************************************************//** * @brief * The getConductivityTemperatureValue function gets the temperature * value for a given conductivity sensor id. * @details \b Inputs: currentTemperatureReadings[] * @details \b Outputs: none * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensorId conductivity sensor id * @return temperature value *************************************************************************/ F32 getConductivityTemperatureValue( CONDUCTIVITY_SENSORS_T sensor ) { F32 result = 0.0F; if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { result = currentTemperatureReadings[ sensor ].data; if ( OVERRIDE_KEY == currentTemperatureReadings[ sensor ].override ) { result = currentTemperatureReadings[ sensor ].ovData; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID1, sensor ); } return result; } /*********************************************************************//** * @brief * The getConductivitySensorReadCount function gets the current conductivity sensor * read count for a given conductivity sensor. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @details \b Inputs: lastConductivityReadCounter * @details \b Outputs: none * @param sensor ID of conductivity sensor to get read count for. * @return The current conductivity sensor read count of a given conductivity sensor. *************************************************************************/ U32 getConductivitySensorReadCount( CONDUCTIVITY_SENSORS_T sensor ) { U32 result = 0; if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { result = lastConductivityReadCounter[ sensor ].data; if ( OVERRIDE_KEY == lastConductivityReadCounter[ sensor ].override ) { result = lastConductivityReadCounter[ sensor ].ovData; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID2, sensor ) } return result; } /*********************************************************************//** * @brief * The getConductivitySensorErrorCount function gets the current conductivity sensor * error count for a given conductivity sensor. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @details \b Inputs: lastConductivityErrorCounter * @details \b Outputs: none * @param sensor ID of conductivity sensor to get error count for. * @return The current conductivity sensor error count of a given conductivity sensor. *************************************************************************/ U32 getConductivitySensorErrorCount( CONDUCTIVITY_SENSORS_T sensor ) { U32 result = 0; if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { result = lastConductivityErrorCounter[ sensor ].data; if ( OVERRIDE_KEY == lastConductivityErrorCounter[ sensor ].override ) { result = lastConductivityErrorCounter[ sensor ].ovData; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID3, sensor ) } return result; } /*********************************************************************//** * @brief * The requestConductivitySensorReset function commands the given * the conductivity sensor to go for reset. * @details \b Inputs: none * @details \b Outputs: conductivitySensorControl * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensor conductivity sensor id * @return none *************************************************************************/ void requestConductivitySensorReset( CONDUCTIVITY_SENSORS_T sensor ) { if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { conductivitySensorControl[ sensor ].resetRequested = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID4, sensor ); } } /*********************************************************************//** * @brief * The setConductivitySensorInitEnable function enables the given * the conductivity sensor (re)initialization procedure. * @details \b Inputs: none * @details \b Outputs: conductivitySensorControl * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensor conductivity sensor id * @return none *************************************************************************/ void setConductivitySensorInitEnable( CONDUCTIVITY_SENSORS_T sensor ) { if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { conductivitySensorControl[ sensor ].initEnable = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID5, sensor ); } } /*********************************************************************//** * @brief * The conductivitySensorWriteRequest function requests the write transaction * for the given conductivity sensor. * @details \b Inputs: none * @details \b Outputs: conductivitySensorControl * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensor conductivity sensor id * @param writeAddr address to write for the given conductivity sensor. * @param data data to write in write address of given conductivity sensor. * @return none *************************************************************************/ void conductivitySensorWriteRequest( CONDUCTIVITY_SENSORS_T sensor, U16 writeAddr, U32 data ) { if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { conductivitySensorControl[ sensor ].writeAddress = writeAddr; conductivitySensorControl[ sensor ].writeData = data; conductivitySensorControl[ sensor ].writeEnable = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID6, sensor ); } } /*********************************************************************//** * @brief * The conductivitySensorReadRequest function requests the read transaction * for the given conductivity sensor. * @details \b Inputs: none * @details \b Outputs: conductivitySensorControl * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @param sensor conductivity sensor id * @param readAddr for sensor read transaction. * @return none *************************************************************************/ void conductivitySensorReadRequest( CONDUCTIVITY_SENSORS_T sensor, U16 readAddr ) { if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { conductivitySensorControl[ sensor ].readAddress = readAddr; conductivitySensorControl[ sensor ].readEnable = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID7, sensor ); } } /*********************************************************************//** * @brief * The conductivitySensorReadData function returns the read data * for the given conductivity sensor. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: none * @param sensor conductivity sensor id * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid. * @return read data for the last request *************************************************************************/ U32 conductivitySensorReadData( CONDUCTIVITY_SENSORS_T sensor ) { U32 data; if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { data = conductivitySensorControl[ sensor ].readData; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID8, sensor ); } return data; } /*********************************************************************//** * @brief * The handleConductivitySensorsReset function checks the reset requested * for all conductivity sensors and perform the sensor reset. * @note This function should be called periodically to handle any * reset request for all conductivity sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @return none *************************************************************************/ void handleConductivitySensorsReset( void ) { if ( TRUE == conductivitySensorControl[ D17_COND ].resetRequested ) { // D17 Cond sensor reset setFPGAD17CondReset(); conductivitySensorControl[ D17_COND ].resetRequested = FALSE; } else { // clear D17 reset clearFPGAD17CondReset(); } if ( TRUE == conductivitySensorControl[ D27_COND ].resetRequested ) { // D27 reset setFPGAD27CondReset(); conductivitySensorControl[ D27_COND ].resetRequested = FALSE; } else { // clear D27 reset clearFPGAD27CondReset(); } if ( TRUE == conductivitySensorControl[ D29_COND ].resetRequested ) { // D29 reset setFPGAD29CondReset(); conductivitySensorControl[ D29_COND ].resetRequested = FALSE; } else { // clear D29 reset clearFPGAD29CondReset(); } if ( TRUE == conductivitySensorControl[ D43_COND ].resetRequested ) { // D43 reset setFPGAD43CondReset(); conductivitySensorControl[ D43_COND ].resetRequested = FALSE; } else { // clear D43 reset clearFPGAD43CondReset(); } if ( TRUE == conductivitySensorControl[ D74_COND ].resetRequested ) { // D74 reset setFPGAD74CondReset(); conductivitySensorControl[ D74_COND ].resetRequested = FALSE; } else { // clear D74 reset clearFPGAD74CondReset(); } if ( TRUE == conductivitySensorControl[ P9_COND ].resetRequested ) { // P9 reset setFPGAP9Reset(); conductivitySensorControl[ P9_COND ].resetRequested = FALSE; } else { // clear P9 reset clearFPGAP9Reset(); } if ( TRUE == conductivitySensorControl[ P18_COND ].resetRequested ) { // P18 reset setFPGAP18Reset(); conductivitySensorControl[ P18_COND ].resetRequested = FALSE; } else { // clear P18 reset clearFPGAP18Reset(); } } /*********************************************************************//** * @brief * The handleConductivitySensorsInitProcedure function checks the (re)initialization * of conducitviy sensors request and may perform the sensor sequencing to * complete the initialization. * @note This function should be called periodically to handle any * Init request for all conductivity sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @return none *************************************************************************/ void handleConductivitySensorsInitProcedure( void ) { if ( TRUE == conductivitySensorControl[ D17_COND ].initEnable ) { // D17 initialization setFPGAD17CondInitEnable(); conductivitySensorControl[ D17_COND ].initEnable = FALSE; } else { // clear D17 Init command clearFPGAD17CondInitEnable(); } if ( TRUE == conductivitySensorControl[ D27_COND ].initEnable ) { // D27 initialization setFPGAD27CondInitEnable(); conductivitySensorControl[ D27_COND ].initEnable = FALSE; } else { // clear D27 Init command clearFPGAD27CondInitEnable(); } if ( TRUE == conductivitySensorControl[ D29_COND ].initEnable ) { // D29 initialization setFPGAD29CondInitEnable(); conductivitySensorControl[ D29_COND ].initEnable = FALSE; } else { // clear D29 Init command clearFPGAD29CondInitEnable(); } if ( TRUE == conductivitySensorControl[ D43_COND ].initEnable ) { // D43 initialization setFPGAD43CondInitEnable(); conductivitySensorControl[ D43_COND ].initEnable = FALSE; } else { // clear D43 Init command clearFPGAD43CondInitEnable(); } if ( TRUE == conductivitySensorControl[ D74_COND ].initEnable ) { // D74 initialization setFPGAD74CondInitEnable(); conductivitySensorControl[ D74_COND ].initEnable = FALSE; } else { // clear D74 Init command clearFPGAD74CondInitEnable(); } if ( TRUE == conductivitySensorControl[ P9_COND ].initEnable ) { // P9 initialization setFPGAP9InitEnable(); conductivitySensorControl[ P9_COND ].initEnable = FALSE; } else { // clear P9 Init command clearFPGAP9InitEnable(); } if ( TRUE == conductivitySensorControl[ P18_COND ].initEnable ) { // P18 initialization setFPGAP18InitEnable(); conductivitySensorControl[ P18_COND ].initEnable = FALSE; } else { // clear P18 Init command clearFPGAP18InitEnable(); } } /*********************************************************************//** * @brief * The execConductivitySensorWrite function executes the conductivity sensor write * state machine. * @details \b Inputs: conductivitySensorWriteState * @details \b Outputs: conductivitySensorWriteState * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if invalid conductivity sensor write * state seen * @return none *************************************************************************/ void execConductivitySensorWrite( void ) { CONDUCTIVITY_SENSORS_T sensor; for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { // write state machine switch ( conductivitySensorControl[ sensor ].writeExecState ) { case CONDUCTIVITY_WRITE_INITIATE: conductivitySensorControl[ sensor ].writeExecState = handleConductivitySensorsWriteInitiate( sensor ); break; case CONDUCTIVITY_WRITE_COMPLETE: conductivitySensorControl[ sensor ].writeExecState = handleConductivitySensorsWriteComplete( sensor ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_WR_INVALID_EXEC_STATE, conductivitySensorControl[ sensor ].writeExecState ) conductivitySensorControl[ sensor ].writeExecState = CONDUCTIVITY_WRITE_INITIATE; break; } } } /*********************************************************************//** * @brief * The handleConductivitySensorsWriteInitiate function initiates the write * transaction of given conducitviy sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @param sensorID ID of conductivity sensor to handle write initiate state for * @return CONDUCTIVITY_WRITE_STATE_T current state of write transaction *************************************************************************/ static CONDUCTIVITY_WRITE_STATE_T handleConductivitySensorsWriteInitiate( CONDUCTIVITY_SENSORS_T sensorID ) { CONDUCTIVITY_WRITE_STATE_T state = CONDUCTIVITY_WRITE_INITIATE; if ( TRUE == conductivitySensorControl[ sensorID ].writeEnable && FALSE == conductivitySensorControl[ sensorID ].writeInProgress ) { conductivitySensorControl[ sensorID ].writeComplete = FALSE; conductivitySensorControl[ sensorID ].writeInProgress = TRUE; if ( D17_COND == sensorID ) { setFPGAD17D74Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAD17D74Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAD17CondWriteEnable(); } else if ( D27_COND == sensorID ) { setFPGAD27D29Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAD27D29Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAD27CondWriteEnable(); } else if ( D29_COND == sensorID ) { setFPGAD27D29Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAD27D29Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAD29CondWriteEnable(); } else if ( D43_COND == sensorID ) { setFPGAD43Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAD43Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAD43CondWriteEnable(); } else if ( D74_COND == sensorID ) { setFPGAD17D74Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAD17D74Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAD74CondWriteEnable(); } else if ( P9_COND == sensorID ) { setFPGAP9Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAP9Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAP9WriteEnable(); } else if ( P18_COND == sensorID ) { setFPGAP18Address( conductivitySensorControl[ sensorID ].writeAddress ); setFPGAP18Data( conductivitySensorControl[ sensorID ].writeData ); setFPGAP18WriteEnable(); } state = CONDUCTIVITY_WRITE_COMPLETE; } return state; } /*********************************************************************//** * @brief * The handleConductivitySensorsWriteComplete function updates the write * transaction completion of given conducitviy sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @param sensorID ID of conductivity sensor to handle write complete state for * @return CONDUCTIVITY_WRITE_STATE_T current state of write transaction *************************************************************************/ static CONDUCTIVITY_WRITE_STATE_T handleConductivitySensorsWriteComplete( CONDUCTIVITY_SENSORS_T sensorID ) { CONDUCTIVITY_WRITE_STATE_T state = CONDUCTIVITY_WRITE_COMPLETE; if ( TRUE == conductivitySensorControl[ sensorID ].writeInProgress ) { conductivitySensorControl[ sensorID ].writeComplete = TRUE; conductivitySensorControl[ sensorID ].writeEnable = FALSE; if ( D17_COND == sensorID ) { clearFPGAD17CondWriteEnable(); } else if ( D27_COND == sensorID ) { clearFPGAD27CondWriteEnable(); } else if ( D29_COND == sensorID ) { clearFPGAD29CondWriteEnable(); } else if ( D43_COND == sensorID ) { clearFPGAD43CondWriteEnable(); } else if ( D74_COND == sensorID ) { clearFPGAD74CondWriteEnable(); } else if ( P9_COND == sensorID ) { clearFPGAP9WriteEnable(); } else if ( P18_COND == sensorID ) { clearFPGAP18WriteEnable(); } state = CONDUCTIVITY_WRITE_INITIATE; } return state; } /*********************************************************************//** * @brief * The execConductivitySensorRead function executes the conductivity sensor read * state machine. * @details \b Inputs: conductivitySensorReadState * @details \b Outputs: conductivitySensorReadState * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if invalid conductivity sensor read * state seen * @return none *************************************************************************/ void execConductivitySensorRead( void ) { CONDUCTIVITY_SENSORS_T sensor; for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { // Read state machine switch ( conductivitySensorControl[ sensor ].readExecState ) { case CONDUCTIVITY_READ_INITIATE: conductivitySensorControl[ sensor ].readExecState = handleConductivitySensorsReadInitiate( sensor ); break; case CONDUCTIVITY_READ_COMPLETE: conductivitySensorControl[ sensor ].readExecState = handleConductivitySensorsReadComplete( sensor ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_CONDUCTIVITY_RD_INVALID_EXEC_STATE, conductivitySensorControl[ sensor ].readExecState ) conductivitySensorControl[ sensor ].readExecState = CONDUCTIVITY_READ_INITIATE; break; } } } /*********************************************************************//** * @brief * The handleConductivitySensorsReadInitiate function initiates the read * transaction of given conducitviy sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @param sensorID ID of conductivity sensor to handle read initiate state for * @return CONDUCTIVITY_READ_STATE_T current state of read transaction *************************************************************************/ static CONDUCTIVITY_READ_STATE_T handleConductivitySensorsReadInitiate( CONDUCTIVITY_SENSORS_T sensorID ) { CONDUCTIVITY_READ_STATE_T state = CONDUCTIVITY_READ_INITIATE; if ( TRUE == conductivitySensorControl[ sensorID ].readEnable && FALSE == conductivitySensorControl[ sensorID ].readInProgress ) { // D17 read request conductivitySensorControl[ sensorID ].readComplete = FALSE; conductivitySensorControl[ sensorID ].readInProgress = TRUE; if ( D17_COND == sensorID ) { setFPGAD17D74Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAD17CondReadEnable(); } else if ( D27_COND == sensorID ) { setFPGAD27D29Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAD27CondReadEnable(); } else if ( D29_COND == sensorID ) { setFPGAD27D29Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAD29CondReadEnable(); } else if ( D43_COND == sensorID ) { setFPGAD43Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAD43CondReadEnable(); } else if ( D74_COND == sensorID ) { setFPGAD17D74Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAD74CondReadEnable(); } else if ( P9_COND == sensorID ) { setFPGAP9Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAP9ReadEnable(); } else if ( P18_COND == sensorID ) { setFPGAP18Address( conductivitySensorControl[ sensorID ].readAddress ); setFPGAP18ReadEnable(); } state = CONDUCTIVITY_READ_COMPLETE; } return state; } /*********************************************************************//** * @brief * The handleConductivitySensorsReadComplete function updates the read * request completion of given conducitviy sensors. * @details \b Inputs: conductivitySensorControl * @details \b Outputs: conductivitySensorControl * @param sensorID ID of conductivity sensor to handle read complete state for * @return CONDUCTIVITY_READ_STATE_T current state of write transaction *************************************************************************/ static CONDUCTIVITY_READ_STATE_T handleConductivitySensorsReadComplete( CONDUCTIVITY_SENSORS_T sensorID ) { CONDUCTIVITY_READ_STATE_T state = CONDUCTIVITY_READ_COMPLETE; if ( TRUE == conductivitySensorControl[ sensorID ].readInProgress ) { conductivitySensorControl[ sensorID ].readComplete = TRUE; conductivitySensorControl[ sensorID ].readEnable = FALSE; if ( D17_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAD17CondData(); clearFPGAD17CondReadEnable(); } else if ( D27_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAD27CondData(); clearFPGAD27CondReadEnable(); } else if ( D29_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAD29CondData(); clearFPGAD29CondReadEnable(); } else if ( D43_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAD43CondData(); clearFPGAD43CondReadEnable(); } else if ( D74_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAD74CondData(); clearFPGAD74CondReadEnable(); } else if ( P9_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAP9Data(); clearFPGAP9ReadEnable(); } else if ( P18_COND == sensorID ) { conductivitySensorControl[ sensorID ].readData = getFPGAP18Data(); clearFPGAP18ReadEnable(); } state = CONDUCTIVITY_READ_INITIATE; } return state; } static TEENSY_SENSOR_INDEX_T getTeensySensorNum( CONDUCTIVITY_SENSORS_T sensorID ) { if ( sensorID >= NUM_OF_CONDUCTIVITY_SENSORS ) { return MAX_TEENSY_SENSOR; // Invalid sensor ID } return teensySensorMapping[ sensorID ]; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testDDConductivitySensorReadingsOverride function overrides the value of the * specified DD conductivity sensor with a given value. * @details \b Inputs: none * @details \b Outputs: currentConductivityReadings[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDConductivitySensorReadingsOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( payload.index <= LAST_DD_COND_SENSOR ) { result = f32ArrayOverride( message, ¤tConductivityReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); } return result; } /*********************************************************************//** * @brief * The testDDConductivitySensorTemperatureReadingsOverride function overrides * the value of the specified DD conductivity sensor temperature with a given value. * @details \b Inputs: none * @details \b Outputs: currentPresTempReadings[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor temperature. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDConductivitySensorTemperatureReadingsOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( payload.index <= LAST_DD_COND_SENSOR ) { result = f32ArrayOverride( message, ¤tTemperatureReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); } return result; } /*********************************************************************//** * @brief * The testDDConductivitySensorReadCounterOverride function overrides * the value of the specified DD conductivity sensor read counter with a given value. * @details \b Inputs: none * @details \b Outputs: lastConductivityReadCounter[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor read counter. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDConductivitySensorReadCounterOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( payload.index <= LAST_DD_COND_SENSOR ) { result = u32ArrayOverride( message, &lastConductivityReadCounter[0], NUM_OF_CONDUCTIVITY_SENSORS - 1, 0, COND_SENSORS_READ_ERR_MAX_CNT ); } return result; } /*********************************************************************//** * @brief * The testDDConductivitySensorErrorCounterOverride function overrides * the value of the specified DD conductivity sensor error counter with a given value. * @details \b Inputs: none * @details \b Outputs: lastConductivityErrorCounter[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor error counter. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDConductivitySensorErrorCounterOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( payload.index <= LAST_DD_COND_SENSOR ) { result = u32ArrayOverride( message, &lastConductivityErrorCounter[0], NUM_OF_CONDUCTIVITY_SENSORS - 1, 0, COND_SENSORS_READ_ERR_MAX_CNT ); } return result; } /*********************************************************************//** * @brief * The testConductivitySensorReadingsOverride function overrides the value of the * specified conductivity sensor with a given value. * @details \b Inputs: none * @details \b Outputs: currentConductivityReadings[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testFPConductivitySensorReadingsOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( ( payload.index >= FIRST_FP_COND_SENSOR ) && ( payload.index <= LAST_FP_COND_SENSOR ) ) { result = f32ArrayOverride( message, ¤tConductivityReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); } return result; } /*********************************************************************//** * @brief * The testConductivitySensorTemperatureReadingsOverride function overrides * the value of the specified conductivity sensor temperature with a given value. * @details \b Inputs: none * @details \b Outputs: currentPresTempReadings[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor temperature. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testFPConductivitySensorTemperatureReadingsOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( ( payload.index >= FIRST_FP_COND_SENSOR ) && ( payload.index <= LAST_FP_COND_SENSOR ) ) { result = f32ArrayOverride( message, ¤tTemperatureReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); } return result; } /*********************************************************************//** * @brief * The testConductivitySensorReadCounterOverride function overrides * the value of the specified conductivity sensor read counter with a given value. * @details \b Inputs: none * @details \b Outputs: lastConductivityReadCounter[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor read counter. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testFPConductivitySensorReadCounterOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( ( payload.index >= FIRST_FP_COND_SENSOR ) && ( payload.index <= LAST_FP_COND_SENSOR ) ) { result = u32ArrayOverride( message, &lastConductivityReadCounter[0], NUM_OF_CONDUCTIVITY_SENSORS - 1, 0, COND_SENSORS_READ_ERR_MAX_CNT ); } return result; } /*********************************************************************//** * @brief * The testConductivitySensorErrorCounterOverride function overrides * the value of the specified conductivity sensor error counter with a given value. * @details \b Inputs: none * @details \b Outputs: lastConductivityErrorCounter[] * @param message Override message from Dialin which includes an sensor * ID and override value of the conductivity sensor error counter. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testFPConductivitySensorErrorCounterOverride( MESSAGE_T *message ) { BOOL result = FALSE; TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); if ( ( payload.index >= FIRST_FP_COND_SENSOR ) && ( payload.index <= LAST_FP_COND_SENSOR ) ) { result = u32ArrayOverride( message, &lastConductivityErrorCounter[0], NUM_OF_CONDUCTIVITY_SENSORS - 1, 0, COND_SENSORS_READ_ERR_MAX_CNT ); } return result; } /**@}*/