Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r736cc5b56cc9c784ab1d8fc8687a73d190c35759 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 736cc5b56cc9c784ab1d8fc8687a73d190c35759) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -87,20 +87,35 @@ #define BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE 12 ///< Blood leak embedded mode command queue maximum size. #define BLOOD_LEAK_EMB_MODE_ZERO_CMD_RQRD_Q 5 ///< Blood leak embedded mode zero command required queue count. #define BLOOD_LEAK_EMB_MODE_NUM_OF_RETRIES 3 ///< Blood leak embedded mode number of retries to enqueue. -#define BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMOUE_MS ( 2 * MS_PER_SECOND ) ///< Blood leak embedded mode informative command timeout in milliseconds. -#define BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS 3 ///< Blood leak embedded mode number of informative commands. +#define BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Blood leak embedded mode informative command timeout in milliseconds. +#define BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS 2 ///< Blood leak embedded mode number of informative commands. #define BLOOD_LEAK_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak embedded mode FPGA error timeout in milliseconds. -#define BLOOD_LEAK_RXFIFO_COUNT_MASK 0x03FF ///< Mask high order bits of blood leak sensor rx count +#define BLOOD_LEAK_RXFIFO_COUNT_MASK 0x03FF ///< Mask high order bits of blood leak sensor rx count. +// ***************** zeroing status *************** // + +#define BLD_NOMINAL_INTENSITY 930 ///< Blood leak nominal intensity. +#define BLD_MAX_INTENSITY_DRFT_AFTER_ZEROING 10 ///< Blood leak max intensity drift after zeroing. +#define BLD_MAX_INTENSITY_OUT_OF_RANGE 0.40F ///< Blood leak maximum allowed intensity. +#define BLD_MIN_INTENSITY_OUT_OF_RANGE 0.35F ///< Blood leak minimum allowed intensity. +#define BLD_ZERO_MIN_INTERVAL_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Blood leak zeroing minimum interval in milliseconds. +#define BLD_ZERO_MVG_AVG_NUM_OF_SAMPLES 16 ///< Blood leak number of moving average samples. +#define BLD_ZERO_IN_RANGE_DRIFT_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Blood leak zero value drift in range timeout in milliseconds. +#define BLD_MAX_UPPER_INTENSITY_DRIFT ( BLD_NOMINAL_INTENSITY + 20 ) ///< Blood leak maximum upper range intensity drift. +#define BLD_START_OF_TX_MIN_INTENSITY_DRIFT 915 ///< Blood leak start of treatment minimum intensity. +#define BLD_UPPER_INTENSITY_INTERVAL_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Blood leak upper drift interval in milliseconds. +#define BLD_ZERO_UPPER_RANGE_DRIFT_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Blood leak zero upper range drift timeout in milliseconds. + /// Defined states for the blood leak detector state machine. typedef enum BloodLeakStates { - BLOOD_LEAK_WAIT_FOR_POST_STATE = 0, ///< Wait for post state. - BLOOD_LEAK_CHECK_SET_POINT_STATE, ///< Check set point state. - BLOOD_LEAK_INIT_STATE, ///< Init state. + BLOOD_LEAK_WAIT_FOR_POST_STATE = 0, ///< Blood leak wait for post state. + BLOOD_LEAK_CHECK_SET_POINT_STATE, ///< Blood leak check set point state. + BLOOD_LEAK_INIT_STATE, ///< Blood leak init state. BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE, ///< Blood leak check for zero and self test commands state. - BLOOD_LEAK_NORMAL_STATE, ///< Normal state. + BLOOD_LEAK_VERIFY_INTENSITY_AFTER_ZEROING_STATE, ///< Blood leak verify intensity after zeroing state. + BLOOD_LEAK_NORMAL_STATE, ///< Blood leak normal state. BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE, ///< Blood leak recover blood detect state. NUM_OF_BLOOD_LEAK_STATES ///< Number of blood leak detector states. } BLOOD_LEAK_STATE_T; @@ -114,6 +129,7 @@ NUM_OF_BLOOD_LEAK_EMB_MODE_STATES ///< Number of blood leak embedded mode states. } BLOOD_LEAK_EMB_MODE_STATE_T; +/// Blood leak detector embedded mode commands typedef enum EmbCommands { NU_EMB_MODE_CMD = 0, ///< Null command. @@ -143,13 +159,28 @@ BOOL isCmdRespRdy; ///< Blood leak sensor is command response ready flag. } EMB_MODE_CMD_T; +/// Blood leak zeroing status data structure +typedef struct +{ + U32 lastZeroingStartTimeMS; ///< Blood leak last zero sequence start time in milliseconds. + U32 driftInRangeDebounceTimeMS; ///< Blood leak drift is in range debounce start time in milliseconds. + U32 rawIntensity[ BLD_ZERO_MVG_AVG_NUM_OF_SAMPLES ]; ///< Blood leak raw intensity array. + U32 intensityRunningSum; ///< Blood leak intensity running sum for moving average. + U32 rawIntensityNextIndex; ///< Blood leak raw intensity next index for moving average. + OVERRIDE_F32_T intensityMovingAverage; ///< Blood leak intensity moving average. + OVERRIDE_U32_T zeroingDriftIntervalTimeMS; ///< Blood leak zeroing interval time in milliseconds. + OVERRIDE_U32_T zeroingUpperRangeIntervalTimeMS; ///< BLood leak zeroing upper range interval time in milliseconds. + U32 driftUpperRangeDebounceTimeMS; ///< Blood leak drift in upper range debounce time in milliseconds. + U32 driftInRangeStatus; + U32 driftUpperRangeStatus; +} BLOOD_LEAK_ZEROING_STATUS_T; + // ********** private data ********** static BLOOD_LEAK_STATE_T bloodLeakState; ///< Current state of blood leak state machine. static OVERRIDE_U32_T bloodLeakStatus; ///< Detected blood leak status for blood leak detector. static SELF_TEST_STATUS_T bloodLeakSelfTestStatus; ///< Current status of blood leak self-test. static U32 bloodLeakPersistenceCtr; ///< Blood leak alarm persistence timer counter. - static OVERRIDE_U32_T bloodLeakDataPublishInterval = { BLOOD_LEAK_PUB_INTERVAL, BLOOD_LEAK_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish blood leak data to CAN bus. static U32 bloodLeakDataPublicationCounter; ///< Timer counter used to schedule blood leak data publication to CAN bus. @@ -159,6 +190,7 @@ static HD_BLOOD_LEAK_SENSOR_CAL_RECORD_T bloodLeakCalRecord; ///< Blood leak calibration record structure. static BOOL bloodLeakExitNormalRequested; ///< Blood leak exit normal state requested. static U32 bloodLeakRecoveryStartTimeMS; ///< Blood leak recovery start time in milliseconds. +static BLOOD_LEAK_ZEROING_STATUS_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // Embedded mode variables static BOOL bloodLeakSignalEmbModeReq; ///< Blood leak signal embedded mode has been requested. @@ -180,13 +212,16 @@ static U32 bloodLeakEmbModeCmdEnqueueCount; ///< Blood leak embedded mode command enqueue count. static U32 bloodLeakEmbModeInfoCmdEnqLastTimeStamp; ///< Blood leak embedded mode informative command (i.e. I, V, D) timer. static U32 bloodLeakEmbModeInfoCmdCounter; ///< Blood leak embedded mode informative command counter. +static OVERRIDE_U32_T bloodLeakEmbModeIntensityOverride; ///< Blood leak embedded mode intensity override. +static OVERRIDE_U32_T bloodLeakEmbModeDetectOverride; ///< Blood leak embedded mode blood detect override. // ********** private function prototypes ********** static BLOOD_LEAK_STATE_T handleBloodLeakWaitForPostState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCheckSetPointState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakInitState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCheckZeroAndSelfTestState( void ); +static BLOOD_LEAK_STATE_T handleBloodLeakVerifyIntensityAfterZeroingState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakNormalState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakRecoverBloodDetectState( void ); @@ -208,6 +243,11 @@ static void resetEmbModeCmdRqstCount( U08 cmd ); static BLOOD_LEAK_STATUS_T getFPGABloodDetectProcessedStatus( void ); static BOOL isDialysateLineInBypass( void ); +static void processBloodLeakIntensityData( void ); +static void resetEmbModeCmdRespConsumedFlag( U08 cmd ); +static U32 getEmbModeInfoValue( U08 cmd ); +static BOOL isLowerRangeIntensityDriftZeroingNeeded( void ); +static BOOL isUpperIntensityZeroingNeeded( void ); /*********************************************************************//** * @brief @@ -223,6 +263,7 @@ * bloodLeakExitNormalRequested, bloodLeakEmbModeCmdSeqLength, * bloodLeakEmbModeHasRxRqstBeenSent, bloodLeakEmbModeInfoCmdEnqLastTimeStamp, * bloodLeakEmbModeInfoCmdCounter, bloodLeakRecoveryStartTimeMS, + * bloodLeakZeroingStatus * @return none *************************************************************************/ void initBloodLeak( void ) @@ -269,6 +310,18 @@ // Initialize the blood leak embedded mode command sequence memset( bloodLeakEmbModeCmdSeq, 0x0, BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); + // Initialize the blood leak zeroing sequence status structure + memset( &bloodLeakZeroingStatus, 0x0, sizeof( BLOOD_LEAK_ZEROING_STATUS_T ) ); + + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.data = BLD_ZERO_MIN_INTERVAL_MS; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.ovInitData = BLD_ZERO_MIN_INTERVAL_MS; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.ovData = 0; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.override = 0; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.data = BLD_UPPER_INTENSITY_INTERVAL_MS; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.ovInitData = BLD_UPPER_INTENSITY_INTERVAL_MS; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.ovData = 0; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.override = 0; + // Enqueue the commands to set the embedded mode and request the set point of the blood leak sensor enqueueEmbModeCmd( CS_EMB_MODE_CMD ); enqueueEmbModeCmd( D_EMB_MODE_CMD ); @@ -290,6 +343,8 @@ getNVRecord2Driver( GET_CAL_BLOOD_LEAK_SENSOR, (U08*)&bloodLeakCalRecord, length, 0, ALARM_ID_HD_BLOOD_LEAK_INVALID_CAL_RECORD ); } + processBloodLeakIntensityData(); + switch( bloodLeakState ) { case BLOOD_LEAK_WAIT_FOR_POST_STATE: @@ -308,6 +363,10 @@ bloodLeakState = handleBloodLeakCheckZeroAndSelfTestState(); break; + case BLOOD_LEAK_VERIFY_INTENSITY_AFTER_ZEROING_STATE: + bloodLeakState = handleBloodLeakVerifyIntensityAfterZeroingState(); + break; + case BLOOD_LEAK_NORMAL_STATE: bloodLeakState = handleBloodLeakNormalState(); break; @@ -370,7 +429,7 @@ *************************************************************************/ BOOL zeroBloodLeak( void ) { - BOOL status = TRUE; + BOOL status = FALSE; if ( getAvailableEmbModeQueueCount() >= BLOOD_LEAK_EMB_MODE_ZERO_CMD_RQRD_Q ) { @@ -386,6 +445,8 @@ enqueueEmbModeCmd( Z_EMB_MODE_CMD ); enqueueEmbModeCmd( Q_EMB_MODE_CMD ); enqueueEmbModeCmd( T_EMB_MODE_CMD ); + + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_BLOOD_LEAK_ZEROING_REQUEST, 0, 0 ) } else if ( ++bloodLeakEmbModeCmdEnqueueCount > BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { @@ -431,6 +492,78 @@ /*********************************************************************//** * @brief + * The getBloodLeakStatus function gets the current reading for the blood + * leak detector. + * @details Inputs: bloodLeakStatus + * @details Outputs: none + * @return the current blood leak status. + *************************************************************************/ +BLOOD_LEAK_STATUS_T getBloodLeakStatus( void ) +{ + BLOOD_LEAK_STATUS_T result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.data; + + if ( OVERRIDE_KEY == bloodLeakStatus.override ) + { + result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getBloodLeakSelfTestStatus function gets the status for the blood + * leak detector self-test. + * @details Inputs: bloodLeakSelfTestStatus + * @details Outputs: none + * @return status of blood leak detector self-test. + *************************************************************************/ +SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ) +{ +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) + { + bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; + } +#endif + + return bloodLeakSelfTestStatus; +} + +/*********************************************************************//** + * @brief + * The isBloodLeakZeroingNeeded function checks whether blood leak zeroing + * is needed in terms of drift. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if blood leak zeroing is needed otherwise, FALSE + *************************************************************************/ +BOOL isBloodLeakZeroingNeeded( void ) +{ + BOOL status = FALSE; + HD_OP_MODE_T opMode = getCurrentOperationMode(); + + if ( MODE_PRET == opMode ) + { + U32 intensity = getEmbModeInfoValue( I_EMB_MODE_CMD ); + + if ( ( intensity <= BLD_START_OF_TX_MIN_INTENSITY_DRIFT ) || ( intensity >= BLD_MAX_UPPER_INTENSITY_DRIFT ) ) + { + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_BLOOD_LEAK_ZEROING_REQUIRED, intensity, opMode ) + status = TRUE; + } + } + else if ( MODE_TREA == opMode ) + { + status |= isLowerRangeIntensityDriftZeroingNeeded(); + status |= isUpperIntensityZeroingNeeded(); + } + + return status; +} + +/*********************************************************************//** + * @brief * The exitBloodLeakNormalState requests that the blood leak sensor to exit * its normal state. * @details Inputs: bloodLeakState @@ -652,25 +785,62 @@ // Pass self-test if entire sequence was successful if ( FALSE == hasCmdSqncFailed ) { - // Done with zero sequence, transition to other states - zeroBloodLeakReset(); - bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; - state = BLOOD_LEAK_NORMAL_STATE; + // Done with the commands, request a fresh intensity read to check its range + enqueueEmbModeCmd( I_EMB_MODE_CMD ); + state = BLOOD_LEAK_VERIFY_INTENSITY_AFTER_ZEROING_STATE; } // If not successful, retry if we've not run out else { bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; state = BLOOD_LEAK_INIT_STATE; + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_BLOOD_LEAK_SELF_TEST_RESULT, bloodLeakSelfTestStatus, state ) } - SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_BLOOD_LEAK_SELF_TEST_RESULT, bloodLeakSelfTestStatus, state ); } return state; } /*********************************************************************//** * @brief + * The handleBloodLeakVerifyIntensityAfterZeroingState function checks the + * blood leak sensor's intensity after zeroing the sensor. + * @details Inputs: bloodLeakEmbModeCmd + * @details Outputs: bloodLeakSelfTestStatus + * @return next state + *************************************************************************/ +static BLOOD_LEAK_STATE_T handleBloodLeakVerifyIntensityAfterZeroingState( void ) +{ + BLOOD_LEAK_STATE_T state = BLOOD_LEAK_VERIFY_INTENSITY_AFTER_ZEROING_STATE; + + if ( TRUE == bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].isCmdRespRdy ) + { + U32 intensity = getEmbModeInfoValue( I_EMB_MODE_CMD ); + + state = BLOOD_LEAK_INIT_STATE; + bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; + + if ( abs( BLD_NOMINAL_INTENSITY - intensity ) <= BLD_MAX_INTENSITY_DRFT_AFTER_ZEROING ) + { + // Done with zero sequence, transition to other states + zeroBloodLeakReset(); + bloodLeakZeroingStatus.lastZeroingStartTimeMS = getMSTimerCount(); + bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; + state = BLOOD_LEAK_NORMAL_STATE; + + if ( TRUE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ) ) + { + state = BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE; + } + } + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_BLOOD_LEAK_SELF_TEST_RESULT, bloodLeakSelfTestStatus, state ) + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleBloodLeakNormalState function handles the Blood Leak module * in normal state. * @details Inputs: bloodLeakStatus, bloodLeakPersistenceCtr, @@ -792,46 +962,6 @@ /*********************************************************************//** * @brief - * The getBloodLeakStatus function gets the current reading for the blood - * leak detector. - * @details Inputs: bloodLeakStatus - * @details Outputs: none - * @return the current blood leak status. - *************************************************************************/ -BLOOD_LEAK_STATUS_T getBloodLeakStatus( void ) -{ - BLOOD_LEAK_STATUS_T result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.data; - - if ( OVERRIDE_KEY == bloodLeakStatus.override ) - { - result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The getBloodLeakSelfTestStatus function gets the status for the blood - * leak detector self-test. - * @details Inputs: bloodLeakSelfTestStatus - * @details Outputs: none - * @return status of blood leak detector self-test. - *************************************************************************/ -SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ) -{ -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) - { - bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; - } -#endif - - return bloodLeakSelfTestStatus; -} - -/*********************************************************************//** - * @brief * The handleBloodLeakEmbModeWaitForCommandState function handles the wait for * command state. The state prepares the message to be sent to the blood leak * sensor. @@ -1318,8 +1448,8 @@ * @brief * The publishBloodLeakData function publishes blood leak data at the set interval. * @details Inputs: bloodLeakDataPublicationTimerCounter - * @details Outputs: bloodLeakDataPublicatimerCouonTinter, bloodLeakPersistenceCtr, - * bloodLeakState + * @details Outputs: bloodLeakDataPublicationTimerCounter, bloodLeakPersistenceCtr, + * bloodLeakState, bloodLeakZeroingStatus * @return none *************************************************************************/ static void publishBloodLeakData( void ) @@ -1329,10 +1459,17 @@ { BLOOD_LEAK_DATA_T data; - data.bloodLeakStatus = (U32)getBloodLeakStatus(); - data.bloodLeakState = (U32)bloodLeakState; - data.bloodLeakPersistentCounter = bloodLeakPersistenceCtr; - data.bloodLeakSerialCommState = bloodLeakEmbModeSubstate; + data.bloodLeakStatus = (U32)getBloodLeakStatus(); + data.bloodLeakState = (U32)bloodLeakState; + data.bloodLeakPersistentCounter = bloodLeakPersistenceCtr; + data.bloodLeakSerialCommState = bloodLeakEmbModeSubstate; + data.bloodLeakIntensity = getEmbModeInfoValue( I_EMB_MODE_CMD ); + data.bloodLeakDetect = getEmbModeInfoValue( V_EMB_MODE_CMD ); + data.bloodLeakIntensityMovingAvg = getF32OverrideValue( &bloodLeakZeroingStatus.intensityMovingAverage ); + data.bloodLeakTimeSinceZeroMS = calcTimeSince( bloodLeakZeroingStatus.lastZeroingStartTimeMS ); + data.driftInRangeStatus = bloodLeakZeroingStatus.driftInRangeStatus; + data.driftUpperRangeStatus = bloodLeakZeroingStatus.driftUpperRangeStatus; + bloodLeakDataPublicationCounter = 0; broadcastData( MSG_ID_HD_BLOOD_LEAK_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( BLOOD_LEAK_DATA_T ) ); @@ -1554,28 +1691,34 @@ *************************************************************************/ static void enqueueInfoEmbModeCmds( void ) { - if ( ( TRUE == didTimeout( bloodLeakEmbModeInfoCmdEnqLastTimeStamp, BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMOUE_MS ) ) && - ( bloodLeakState >= BLOOD_LEAK_INIT_STATE ) && ( bloodLeakState != BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE ) ) + if ( TRUE == didTimeout( bloodLeakEmbModeInfoCmdEnqLastTimeStamp, BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMEOUT_MS ) ) { - // Enqueue the next command. Make sure the blood leak state is greater than init state and it is not the zero and self test state - // to make sure setting the embedded mode and getting the set point and zero sequence should go undisturbed. - if ( 0 == bloodLeakEmbModeInfoCmdCounter ) + switch ( bloodLeakState ) { - enqueueEmbModeCmd( I_EMB_MODE_CMD ); - } - else if ( 1 == bloodLeakEmbModeInfoCmdCounter ) - { - enqueueEmbModeCmd( V_EMB_MODE_CMD ); - } - else if ( 2 == bloodLeakEmbModeInfoCmdCounter ) - { - enqueueEmbModeCmd( D_EMB_MODE_CMD ); - } + case BLOOD_LEAK_INIT_STATE: + case BLOOD_LEAK_NORMAL_STATE: + case BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE: + // Enqueue the next command. Make sure the blood leak state is greater than init state and it is not the zero and self test state + // to make sure setting the embedded mode and getting the set point and zero sequence should go undisturbed. + if ( 0 == bloodLeakEmbModeInfoCmdCounter ) + { + enqueueEmbModeCmd( I_EMB_MODE_CMD ); + } + else if ( 1 == bloodLeakEmbModeInfoCmdCounter ) + { + enqueueEmbModeCmd( V_EMB_MODE_CMD ); + } - // Set the timer for the next time out to enqueue - // Reset the counter. The counter starts from 0 - bloodLeakEmbModeInfoCmdEnqLastTimeStamp = getMSTimerCount(); - bloodLeakEmbModeInfoCmdCounter = INC_WRAP( bloodLeakEmbModeInfoCmdCounter, 0, BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS - 1 ); + // Set the timer for the next time out to enqueue + // Reset the counter. The counter starts from 0 + bloodLeakEmbModeInfoCmdEnqLastTimeStamp = getMSTimerCount(); + bloodLeakEmbModeInfoCmdCounter = INC_WRAP( bloodLeakEmbModeInfoCmdCounter, 0, BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS - 1 ); + break; + + default: + // Do nothing as the other commands are ignored + break; + } } } @@ -1626,7 +1769,161 @@ return status; } +/*********************************************************************//** + * @brief + * The processBloodLeakIntensityData function calculates the moving average + * of blood leak intensity data. + * @details Inputs: none + * @details Outputs: bloodLeakZeroingStatus + * @return none + *************************************************************************/ +static void processBloodLeakIntensityData( void ) +{ + if ( ( TRUE == bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].isCmdRespRdy ) && ( bloodLeakState != BLOOD_LEAK_VERIFY_INTENSITY_AFTER_ZEROING_STATE ) ) + { + U32 index = bloodLeakZeroingStatus.rawIntensityNextIndex; + U32 indexValue = bloodLeakZeroingStatus.rawIntensity[ index ]; + U32 newIntensity = getEmbModeInfoValue( I_EMB_MODE_CMD ); + bloodLeakZeroingStatus.rawIntensity[ index ] = newIntensity; + bloodLeakZeroingStatus.intensityRunningSum = bloodLeakZeroingStatus.intensityRunningSum - indexValue + newIntensity; + bloodLeakZeroingStatus.intensityMovingAverage.data = (F32)bloodLeakZeroingStatus.intensityRunningSum / (F32)BLD_ZERO_MVG_AVG_NUM_OF_SAMPLES; + bloodLeakZeroingStatus.rawIntensityNextIndex = INC_WRAP( index, 0, BLD_ZERO_MVG_AVG_NUM_OF_SAMPLES - 1 ); + + resetEmbModeCmdRespConsumedFlag( I_EMB_MODE_CMD ); + } +} +/*********************************************************************//** + * @brief + * The resetEmbModeCmdRespConsumedFlag function sets the cmd response ready flag + * to false its flag that fresh data is ready. + * @details Inputs: none + * @details Outputs: bloodLeakEmbModeCmd + * @param cmd the command to signal its data has been consumed + * @return none + *************************************************************************/ +static void resetEmbModeCmdRespConsumedFlag( U08 cmd ) +{ + bloodLeakEmbModeCmd[ cmd ].isCmdRespRdy = FALSE; +} + +/*********************************************************************//** + * @brief + * The getEmbModeInfoValue function gets the data of the embedded info cmds. + * This is only for the info values (I, V). + * @details Inputs: bloodLeakEmbModeIntensityOverride, + * bloodLeakEmbModeDetectOverride + * @details Outputs: bloodLeakEmbModeCmd + * @param cmd the command to get the read data + * @return the value of the read command + *************************************************************************/ +static U32 getEmbModeInfoValue( U08 cmd ) +{ + U32 value = bloodLeakEmbModeCmd[ cmd ].commandResp; + + switch( cmd ) + { + case I_EMB_MODE_CMD: + if ( OVERRIDE_KEY == bloodLeakEmbModeIntensityOverride.override ) + { + value = bloodLeakEmbModeIntensityOverride.ovData; + } + break; + + case V_EMB_MODE_CMD: + if ( OVERRIDE_KEY == bloodLeakEmbModeDetectOverride.override ) + { + value = bloodLeakEmbModeDetectOverride.ovData; + } + break; + + default: + // Do nothing with the rest of the commands + break; + } + + return value; +} + +/*********************************************************************//** + * @brief + * The isLowerRangeIntensityDriftZeroingNeeded function checks whether blood + * leak zeroing is needed in terms of drift in range drift (35-40%). + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return TRUE if blood leak zeroing is needed otherwise, FALSE + *************************************************************************/ +static BOOL isLowerRangeIntensityDriftZeroingNeeded( void ) +{ + /* + * Nominal intensity = 930 + * Set point is queried from the blood leak detector + * Min drift from top = 930 - (setpoint * 40%) + * Max drift from top = 930 - (setpoint * 35%) + * If Min drift from top ≤ moving average intensity ≤ Max drift from top then the debounce timer is set + * If the debounce time has been elapsed the signal to zero the BLD is set + */ + BOOL status = FALSE; + BOOL isZeroingNeeded = TRUE; + U32 setPoint = bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandResp; + F32 driftMinFromTop = BLD_NOMINAL_INTENSITY - ( setPoint * BLD_MAX_INTENSITY_OUT_OF_RANGE ); + F32 driftMaxFromTop = BLD_NOMINAL_INTENSITY - ( setPoint * BLD_MIN_INTENSITY_OUT_OF_RANGE ); + U32 zeroingIntervalMS = getU32OverrideValue( &bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS ); + BOOL isZeroingAllowed = didTimeout( bloodLeakZeroingStatus.lastZeroingStartTimeMS, zeroingIntervalMS ); + F32 intensityMvgAvg = getF32OverrideValue( &bloodLeakZeroingStatus.intensityMovingAverage ); + + isZeroingNeeded &= ( intensityMvgAvg >= driftMinFromTop ? TRUE : FALSE ); + isZeroingNeeded &= ( intensityMvgAvg <= driftMaxFromTop ? TRUE : FALSE ); + + if ( FALSE == isZeroingNeeded ) + { + // Intensity drift is not in range so reset the debounce timer + bloodLeakZeroingStatus.driftInRangeDebounceTimeMS = getMSTimerCount(); + } + + if ( ( TRUE == isZeroingAllowed ) && ( TRUE == didTimeout( bloodLeakZeroingStatus.driftInRangeDebounceTimeMS, BLD_ZERO_IN_RANGE_DRIFT_TIMEOUT_MS ) ) ) + { + // If the moving average intensity is set and then the debounce time has elapsed the signal to zero is set to true. + status = TRUE; + } + + bloodLeakZeroingStatus.driftInRangeStatus = status; + + return status; +} + +/*********************************************************************//** + * @brief + * The isUpperIntensityZeroingNeeded function checks whether blood + * leak zeroing is needed in terms of drift upper range intensity (>= 950). + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return TRUE if blood leak zeroing is needed otherwise, FALSE + *************************************************************************/ +static BOOL isUpperIntensityZeroingNeeded( void ) +{ + BOOL status = FALSE; + U32 zeroingUpperIntervalMS = getU32OverrideValue( &bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS ); + BOOL isZeroingAllowed = didTimeout( bloodLeakZeroingStatus.lastZeroingStartTimeMS, zeroingUpperIntervalMS ); + F32 intensityMvgAvg = getF32OverrideValue( &bloodLeakZeroingStatus.intensityMovingAverage ); + BOOL isUpperZeroingNeeded = ( intensityMvgAvg >= BLD_MAX_UPPER_INTENSITY_DRIFT ? TRUE : FALSE ); + + if ( FALSE == isUpperZeroingNeeded ) + { + bloodLeakZeroingStatus.driftUpperRangeDebounceTimeMS = getMSTimerCount(); + } + + if ( ( TRUE == isZeroingAllowed ) && ( TRUE == didTimeout( bloodLeakZeroingStatus.driftUpperRangeDebounceTimeMS, BLD_ZERO_UPPER_RANGE_DRIFT_TIMEOUT_MS ) ) ) + { + status = TRUE; + } + + bloodLeakZeroingStatus.driftUpperRangeStatus = status; + + return status; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -1783,4 +2080,193 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetBloodLeakEmbeddedModeInfoOverride function overrides the + * blood leak embedded mode info values. + * @details Inputs: none + * @details Outputs: bloodLeakEmbModeIntensityOverride, + * bloodLeakEmbModeDetectOverride + * @param command the command to override its value + * @param value the value that the command is overridden to + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodLeakEmbeddedModeInfoOverride( U08 command, U32 value ) +{ + BOOL result = FALSE; + + if ( ( TRUE == isTestingActivated() ) && ( command < NUM_OF_EMB_CMDS ) ) + { + switch( command ) + { + case I_EMB_MODE_CMD: + result = TRUE; + bloodLeakEmbModeIntensityOverride.ovData = value; + bloodLeakEmbModeIntensityOverride.override = OVERRIDE_KEY; + break; + + case V_EMB_MODE_CMD: + result = TRUE; + bloodLeakEmbModeDetectOverride.ovData = value; + bloodLeakEmbModeDetectOverride.override = OVERRIDE_KEY; + break; + + default: + // Do nothing with the rest of the commands. They cannot be overridden. + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetBloodLeakEmbeddedModeInfoOverride function reset the overrides + * of the blood leak embedded mode info values. + * @details Inputs: none + * @details Outputs: bloodLeakEmbModeIntensityOverride, + * bloodLeakEmbModeDetectOverride + * @param command the command to reset its override value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetBloodLeakEmbeddedModeInfoOverride( U08 command ) +{ + BOOL result = FALSE; + + if ( ( TRUE == isTestingActivated() ) && ( command < NUM_OF_EMB_CMDS ) ) + { + switch( command ) + { + case I_EMB_MODE_CMD: + result = TRUE; + bloodLeakEmbModeIntensityOverride.ovData = 0; + bloodLeakEmbModeIntensityOverride.override = OVERRIDE_RESET; + break; + + case V_EMB_MODE_CMD: + result = TRUE; + bloodLeakEmbModeDetectOverride.ovData = 0; + bloodLeakEmbModeDetectOverride.override = OVERRIDE_RESET; + break; + + default: + // Do nothing with the rest of the commands. They cannot be overridden. + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetBloodLeakIntensityMovingAverageOverride function overrides the + * blood leak intensity moving average. + * @details Inputs: none + * @details Outputs: bloodLeakZeroingStatus + * @param value intensity moving average + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodLeakIntensityMovingAverageOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + bloodLeakZeroingStatus.intensityMovingAverage.ovData = value; + bloodLeakZeroingStatus.intensityMovingAverage.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetBloodLeakIntensityMovingAverageOverride function resets the + * override of the blood leak intensity moving average. + * @details Inputs: none + * @details Outputs: bloodLeakZeroingStatus + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetBloodLeakIntensityMovingAverageOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + bloodLeakZeroingStatus.intensityMovingAverage.ovData = bloodLeakZeroingStatus.intensityMovingAverage.ovInitData; + bloodLeakZeroingStatus.intensityMovingAverage.override = OVERRIDE_RESET; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetBloodLeakZeroingIntervalInMinsOverride function overrides the + * blood leak zeroing interval in minutes. + * @details Inputs: none + * @details Outputs: bloodLeakZeroingStatus + * @param drift check interval or upper range intensity boolean flag + * @param value zeroing interval in minutes + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodLeakZeroingIntervalInMinsOverride( BOOL upperRangeInterval, U32 valueMins ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( FALSE == upperRangeInterval ) + { + result = TRUE; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.ovData = ( valueMins * SEC_PER_MIN * MS_PER_SECOND ); + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.override = OVERRIDE_KEY; + } + else + { + result = TRUE; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.ovData = ( valueMins * SEC_PER_MIN * MS_PER_SECOND ); + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetBloodLeakZeroingIntervalInMinsOverride function resets the + * override of the blood leak zeroing interval + * @details Inputs: none + * @details Outputs: bloodLeakZeroingStatus + * @param boolean flag to indicate to reset upper range interval or the drift + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetBloodLeakZeroingIntervalInMinsOverride( BOOL upperRangeInterval ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( FALSE == upperRangeInterval ) + { + result = TRUE; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.ovData = bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.ovInitData; + bloodLeakZeroingStatus.zeroingDriftIntervalTimeMS.override = OVERRIDE_RESET; + } + else + { + result = TRUE; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.ovData = bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.ovInitData; + bloodLeakZeroingStatus.zeroingUpperRangeIntervalTimeMS.override = OVERRIDE_RESET; + } + } + + return result; +} + /**@}*/