Index: firmware/App/Monitors/Level.c =================================================================== diff -u -r229341f9eb23fec730cdf9b1f8f3960de2daf384 -r046bc2b62cf942b7e846fa5bff698b94238edf24 --- firmware/App/Monitors/Level.c (.../Level.c) (revision 229341f9eb23fec730cdf9b1f8f3960de2daf384) +++ firmware/App/Monitors/Level.c (.../Level.c) (revision 046bc2b62cf942b7e846fa5bff698b94238edf24) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 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 Level.c * -* @author (last) Vinayakam Mani -* @date (last) 11-Oct-2024 +* @author (last) Raghu Kallala +* @date (last) 23-Feb-2026 * * @author (original) Vinayakam Mani -* @date (original) 11-Oct-2024 +* @date (original) 14-Oct-2024 * ***************************************************************************/ @@ -28,12 +28,21 @@ */ // ********** private definitions ********** +#define LEVEL_SENSOR_VALUE_LOW 0U ///< Level sensor digital low value (0 = low, non-zero = high). +#define FPGA_B1_HW_LEVEL_LOW 5 ///< Floater low level status for Beta 1.0 +#define FPGA_B1_HW_LEVEL_MEDIUM 4 ///< Floater medium level status for Beta 1.0 +#define FPGA_B1_HW_LEVEL_HIGH 6 ///< Floater high level status for Beta 1.0 +#define FPGA_LEVEL_EMPTY 3 ///< Floater empty level status #define FPGA_LEVEL_LOW 2 ///< Floater low level status -#define FPGA_LEVEL_MEDIUM 3 ///< Floater medium level status -#define FPGA_LEVEL_HIGH 1 ///< Floater high level status +#define FPGA_LEVEL_MEDIUM 0 ///< Floater medium level status +#define FPGA_LEVEL_HIGH 4 ///< Floater high level status +#define FPGA_B2_LEVEL_EMPTY 0x0B ///< Floater empty level status for beta 2.0 +#define FPGA_B2_LEVEL_LOW 0x0A ///< Floater low level status for beta 2.0 +#define FPGA_B2_LEVEL_MEDIUM 8 ///< Floater medium level status for beta 2.0 +#define FPGA_B2_LEVEL_HIGH 0x0C ///< Floater high level status for beta 2.0 #define LEVEL_COUNT_LOW 0xFFFF ///< Level sensor count when fluid level is low or non submerged -#define LEVEL_COUNT_HIGH_START 0x2000 ///< Start range of level sensor count when fluid level is high or submerged -#define LEVEL_COUNT_HIGH_END 0x2FFF ///< End range of level sensor count when fluid level is high or submerged +#define LEVEL_COUNT_HIGH_START 0x0000 ///< Start range of level sensor count when fluid level is high or submerged +#define LEVEL_COUNT_HIGH_END 0x1FFF ///< End range of level sensor count when fluid level is high or submerged #define LOW_LEVEL_COUNT_TOLERANCE ( ( LEVEL_COUNT_LOW / 100 ) * 1 ) ///< Level sensor count 1% tolerance for low level #define HIGH_LEVEL_COUNT_TOLERANCE ( ( LEVEL_COUNT_HIGH / 100 ) * 1 ) ///< Level sensor count 1% tolerance for high level #define LEVEL_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the level data is published on the CAN bus. @@ -51,16 +60,20 @@ // ********** private data ********** static U32 levelsDataPublicationCounter; ///< Level data publication counter. -static OVERRIDE_U32_T levelsDataPublishInterval = { LEVEL_DATA_PUB_INTERVAL, - LEVEL_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish Level data to CAN bus. +static U32 fplevelsDataPublicationCounter; ///< fp Level data publication counter. +static OVERRIDE_U32_T levelsDataPublishInterval; ///< Interval (in ms) at which to publish Level data to CAN bus. +static OVERRIDE_U32_T fplevelsDataPublishInterval; ///< Interval (in ms/task interval) for FP levels at which to publish valves state to CAN bus. static LEVEL_STATUS_T levelsStatus[ NUM_OF_LEVELS ]; ///< Level status array. static OVERRIDE_U32_T status[ NUM_OF_LEVELS ]; ///< Level status. // ********** private function prototypes ********** static void publishLevelsData( void ); static BOOL processLevelCount( U16 count ); -static LEVEL_STATE_T getFloaterLevelstatus( void ); +static LEVEL_STATE_T readFloaterLevelStatus( LEVEL_T levelId ); +static LEVEL_STATE_T getLevelState( U32 levelStatus ); +static LEVEL_STATE_T getLevelStateBeta19( U32 levelStatus ); +static LEVEL_STATE_T getLevelStateBeta10( U32 levelStatus ); /*********************************************************************//** * @brief @@ -73,7 +86,15 @@ { U32 i; - levelsDataPublicationCounter = DATA_PUBLISH_COUNTER_START_COUNT; + levelsDataPublicationCounter = DATA_PUBLISH_COUNTER_START_COUNT; + fplevelsDataPublishInterval.data = LEVEL_DATA_PUB_INTERVAL; + fplevelsDataPublishInterval.ovData = LEVEL_DATA_PUB_INTERVAL; + fplevelsDataPublishInterval.ovInitData = 0; + fplevelsDataPublishInterval.override = OVERRIDE_RESET; + levelsDataPublishInterval.data = LEVEL_DATA_PUB_INTERVAL; + levelsDataPublishInterval.ovData = LEVEL_DATA_PUB_INTERVAL; + levelsDataPublishInterval.ovInitData = 0; + levelsDataPublishInterval.override = OVERRIDE_RESET; // Initialize all the Level for ( i = 0; i < NUM_OF_LEVELS; i++ ) @@ -109,17 +130,46 @@ { // Process the status of the Level case D6_LEVL: - currentLevelStatus = getFloaterLevelstatus(); + currentLevelStatus = readFloaterLevelStatus( D6_LEVL ); break; case D63_LEVL: - currentLevelStatus = ( processLevelCount( getFPGAD63LevelSensor() ) == 0 ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH ); + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) ) + { + currentLevelStatus = ( LEVEL_SENSOR_VALUE_LOW == getFPGAD63LevelSensor() ) ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH; + } + else + { + currentLevelStatus = ( processLevelCount( getFPGAD63LevelSensor() ) == LEVEL_SENSOR_VALUE_LOW ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH ); + } break; + case D98_LEVL: + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) ) + { + currentLevelStatus = ( LEVEL_SENSOR_VALUE_LOW == getFPGAD98LevelSensor() ) ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH; + } + else + { + currentLevelStatus = ( processLevelCount( getFPGAD98LevelSensor() ) == LEVEL_SENSOR_VALUE_LOW ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH ); + } + break; + case D46_LEVL: - currentLevelStatus = ( processLevelCount( getFPGAD46LevelSensor() ) == 0 ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH ); + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) ) + { + currentLevelStatus = ( LEVEL_SENSOR_VALUE_LOW == getFPGAD46LevelSensor() ) ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH; + } + else + { + currentLevelStatus = ( processLevelCount( getFPGAD46LevelSensor() ) == LEVEL_SENSOR_VALUE_LOW ? LEVEL_STATE_LOW : LEVEL_STATE_HIGH ); + } break; + case P25_LEVL: + currentLevelStatus = readFloaterLevelStatus( P25_LEVL ); + break; + #ifndef _VECTORCAST_ default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_LEVEL_SELECTED, i ); @@ -148,6 +198,10 @@ SEND_EVENT_WITH_2_U32_DATA( DD_EVENT_D63_LEVL_CHANGE, (U32)status[ i ].data, (U32)currentLevelStatus ); break; + case D98_LEVL: + SEND_EVENT_WITH_2_U32_DATA( DD_EVENT_D98_LEVL_CHANGE, (U32)status[ i ].data, (U32)currentLevelStatus ); + break; + case D46_LEVL: SEND_EVENT_WITH_2_U32_DATA( DD_EVENT_D46_LEVL_CHANGE, (U32)status[ i ].data, (U32)currentLevelStatus ); break; @@ -184,7 +238,7 @@ * @param levelId which is the sensor that its status is requested * @return level status *************************************************************************/ -LEVEL_STATE_T getLevelStatus( LELVEL_T levelId ) +LEVEL_STATE_T getLevelStatus( LEVEL_T levelId ) { U32 stat = 0; @@ -220,53 +274,225 @@ BOOL level = FALSE; // Check the level count with in the high level range - if ( ( count >= LEVEL_COUNT_HIGH_START ) && - ( count <= LEVEL_COUNT_HIGH_END ) ) + if ( count <= LEVEL_COUNT_HIGH_END ) { level = TRUE; } + + return level; +} + +/*********************************************************************//** + * @brief + * The getLevelStateBeta19 function maps the raw floater/level status reported + * by FPGA to the corresponding LEVEL_STATE_T for Beta 1.9 hardware. + * @details \b Inputs: levelStatus + * @details \b Outputs: none + * @param levelStatus Raw FPGA level status value + * @return mapped level state + *************************************************************************/ +static LEVEL_STATE_T getLevelStateBeta19( U32 levelStatus ) +{ + LEVEL_STATE_T currentLevelStatus = LEVEL_STATE_ILLEGAL; + + if ( FPGA_LEVEL_EMPTY == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_EMPTY; + } + else if ( FPGA_LEVEL_LOW == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_LOW; + } + else if ( FPGA_LEVEL_MEDIUM == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_MEDIUM; + } + else if ( FPGA_LEVEL_HIGH == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_HIGH; + } else { - level = FALSE; + // TODO - Handle invalid level alarm + currentLevelStatus = LEVEL_STATE_ILLEGAL; } - return level; + return currentLevelStatus; } /*********************************************************************//** * @brief - * The getFloaterLevelstatus function gets the floater level reported by FPGA + * The getLevelState function maps the raw floater/level status reported + * by FPGA to the corresponding LEVEL_STATE_T for Beta 2.0 hardware. + * @details \b Inputs: levelStatus + * @details \b Outputs: none + * @param levelStatus Raw FPGA level status value + * @return mapped level state + *************************************************************************/ +static LEVEL_STATE_T getLevelState( U32 levelStatus ) +{ + LEVEL_STATE_T currentLevelStatus = LEVEL_STATE_ILLEGAL; + + if ( FPGA_B2_LEVEL_EMPTY == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_EMPTY; + } + else if ( FPGA_B2_LEVEL_LOW == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_LOW; + } + else if ( FPGA_B2_LEVEL_MEDIUM == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_MEDIUM; + } + else if ( FPGA_B2_LEVEL_HIGH == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_HIGH; + } + else + { + // TODO - Handle invalid level alarm + currentLevelStatus = LEVEL_STATE_ILLEGAL; + } + + return currentLevelStatus; +} + +/*********************************************************************//** + * @brief + * The getLevelStateBeta10 function maps the raw floater/level status reported + * by FPGA to the corresponding LEVEL_STATE_T for Beta 1.0 hardware. + * @details \b Inputs: levelStatus + * @details \b Outputs: none + * @param levelStatus Raw FPGA level status value + * @return mapped level state + *************************************************************************/ +static LEVEL_STATE_T getLevelStateBeta10( U32 levelStatus ) +{ + LEVEL_STATE_T currentLevelStatus = LEVEL_STATE_ILLEGAL; + + if ( FPGA_B1_HW_LEVEL_LOW == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_LOW; + } + else if ( FPGA_B1_HW_LEVEL_MEDIUM == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_MEDIUM; + } + else if ( FPGA_B1_HW_LEVEL_HIGH == levelStatus ) + { + currentLevelStatus = LEVEL_STATE_HIGH; + } + else + { + // TODO - Handle invalid level alarm + currentLevelStatus = LEVEL_STATE_ILLEGAL; + } + + return currentLevelStatus; +} + +/*********************************************************************//** + * @brief + * The readFloaterLevelStatus function gets the floater level reported by FPGA + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if the current state is invalid. * @details \b Inputs: FPGA level sensor data * @details \b Outputs: level * @return level status *************************************************************************/ -static LEVEL_STATE_T getFloaterLevelstatus( void ) +static LEVEL_STATE_T readFloaterLevelStatus( LEVEL_T levelId ) { LEVEL_STATE_T currentLevelStatus = LEVEL_STATE_HIGH; + U32 levelStatus = 0; - if ( FPGA_LEVEL_LOW == getFPGAD6LevelStatus() ) + if ( D6_LEVL == levelId ) { - currentLevelStatus = LEVEL_STATE_HIGH ; + levelStatus = getFPGAD6LevelStatus(); + + if ( ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) != TRUE ) && + ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) != TRUE ) ) + { + // Beta 1.9 behavior + currentLevelStatus = getLevelStateBeta19( levelStatus ); + } + else if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) == TRUE ) + { + // Beta 2.0 behavior + currentLevelStatus = getLevelState( levelStatus ); + } + else + { + // Beta 1.0 behavior + currentLevelStatus = getLevelStateBeta10( levelStatus ); + } } - else if ( FPGA_LEVEL_MEDIUM == getFPGAD6LevelStatus() ) + + else if ( P25_LEVL == levelId ) { - currentLevelStatus = LEVEL_STATE_MEDIUM ; + levelStatus = getFPGAP25FloaterState(); + + if ( ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) != TRUE ) && + ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) != TRUE ) ) + { + // Beta 1.9 behavior + currentLevelStatus = getLevelStateBeta19( levelStatus ); + } + else if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_2_0_HW ) == TRUE ) + { + // Beta 2.0 behavior + currentLevelStatus = getLevelState( levelStatus ); + } + else + { + // Beta 1.0 behavior + currentLevelStatus = getLevelStateBeta10( levelStatus ); + } } - else if ( FPGA_LEVEL_HIGH == getFPGAD6LevelStatus() ) - { - currentLevelStatus = LEVEL_STATE_LOW ; - } + else { - // TODO - Handle invalid level alarm - currentLevelStatus = LEVEL_STATE_ILLEGAL ; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DD_INVALID_LEVEL_ID, (U32)levelId ); } return currentLevelStatus; } /*********************************************************************//** * @brief + * The getBicarbChamberLevelStatus function returns the status of Bicarb chamber + * F level from the upper level and lower level sensors. + * @details \b Inputs: FPGA level sensor data + * @details \b Outputs: level + * @return level status + *************************************************************************/ +LEVEL_STATE_T getBicarbChamberLevelStatus( void ) +{ + LEVEL_STATE_T status = LEVEL_STATE_ILLEGAL; + LEVEL_STATE_T upperlevel = getLevelStatus( D63_LEVL ); + LEVEL_STATE_T lowerlevel = getLevelStatus( D98_LEVL ); + + if ( ( lowerlevel == LEVEL_STATE_LOW ) && ( upperlevel == LEVEL_STATE_LOW ) ) + { + status = LEVEL_STATE_LOW; + } + else if ( ( lowerlevel == LEVEL_STATE_HIGH ) && ( upperlevel == LEVEL_STATE_LOW ) ) + { + status = LEVEL_STATE_MEDIUM; + } + else if ( ( lowerlevel == LEVEL_STATE_HIGH ) && ( upperlevel == LEVEL_STATE_HIGH ) ) + { + status = LEVEL_STATE_HIGH; + } + else + { + // upperlevel == TRUE while lowerlevel == FALSE - illegal + status = LEVEL_STATE_ILLEGAL; + } + return status; +} + +/*********************************************************************//** + * @brief * The publishLevelsData function broadcasts the level data at the * publication interval. * @details \b Inputs: levelsDataPublicationCounter @@ -279,16 +505,28 @@ { if ( ++levelsDataPublicationCounter >= getU32OverrideValue( &levelsDataPublishInterval ) ) { - LEVEL_DATA_T data; + DD_LEVEL_DATA_T data; - data.d6Level = (U32)getLevelStatus( D6_LEVL ); - data.d63Level = (U32)getLevelStatus( D63_LEVL ); - data.d46Level = (U32)getLevelStatus( D46_LEVL ); + data.d6Level = (U32)getLevelStatus( D6_LEVL ); + data.d63Level = (U32)getLevelStatus( D63_LEVL ); + data.d98Level = (U32)getLevelStatus( D98_LEVL ); + data.bicarbLevel = (U32)getBicarbChamberLevelStatus(); + data.d46Level = (U32)getLevelStatus( D46_LEVL ); levelsDataPublicationCounter = 0; - broadcastData( MSG_ID_DD_LEVEL_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( LEVEL_DATA_T ) ); + broadcastData( MSG_ID_DD_LEVEL_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( DD_LEVEL_DATA_T ) ); } + + // publish IOFP float states on interval + if ( ++fplevelsDataPublicationCounter >= getU32OverrideValue( &fplevelsDataPublishInterval ) ) + { + FP_LEVEL_DATA_T data; + + data.p25Level = (U32)getLevelStatus( P25_LEVL ); + fplevelsDataPublicationCounter = 0; + broadcastData( MSG_ID_FP_LEVEL_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( FP_LEVEL_DATA_T ) ); + } } @@ -331,4 +569,45 @@ return result; } +/*********************************************************************//** + * @brief + * The testFPLevelsDataPublishIntervalOverride function overrides the Level + * data publish interval. + * @details \b Inputs: levelsDataPublishInterval + * @details \b Outputs: levelsDataPublishInterval + * @param Override message from Dialin which includes the interval + * (in ms) to override the level data broadcast interval to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testFPLevelsDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &fplevelsDataPublishInterval, TASK_PRIORITY_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testFPLevelStateOverride function sets the override state for the floater + * level sensor. + * @details \b Inputs: none + * @details \b Outputs: levelState + * @param message Override message from Dialin which includes the state to + * override the floater level sensor to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testFPLevelStateOverride( MESSAGE_T *message ) +{ + BOOL result = FALSE; + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + OVERRIDE_TYPE_T ovType = getOverrideArrayPayloadFromMessage( message, &payload ); + + if ( ( payload.index >= FIRST_FP_LEVL ) && ( payload.index <= LAST_FP_LEVL ) ) + { + BOOL result = u32Override( message, &status[0], 0, NUM_OF_LEVELS_STATES -1 ); + } + + return result; +} + /**@}*/