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; +} + /**@}*/ Index: firmware/App/Controllers/BloodLeak.h =================================================================== diff -u -r20d0c02f453b6dae1884fb1b5ba542053852ffc1 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision 20d0c02f453b6dae1884fb1b5ba542053852ffc1) +++ firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -14,67 +14,83 @@ * @date (original) 18-Mar-2021 * ***************************************************************************/ - -#ifndef __BLOOD_LEAK_H__ -#define __BLOOD_LEAK_H__ - -#include "HDCommon.h" - -/** - * @defgroup BloodLeak BloodLeak - * @brief Blood Leak detector monitor module. Monitors the - * blood leak detector. + +#ifndef __BLOOD_LEAK_H__ +#define __BLOOD_LEAK_H__ + +#include "HDCommon.h" + +/** + * @defgroup BloodLeak BloodLeak + * @brief Blood Leak detector monitor module. Monitors the + * blood leak detector. * * INTROTEK - Blood Component Detector Part No. 105-0002 - * - * @addtogroup BloodLeak - * @{ - */ - -// ********** public definitions ********** - -/// Enumeration of blood leak detector status. -typedef enum BloodLeakDetectorStatus -{ - BLOOD_LEAK_DETECTED = 0, ///< Blood leak detector senses blood. - BLOOD_LEAK_NOT_DETECTED, ///< Blood leak detector does not sense any blood. - NUM_OF_BLOOD_LEAK_STATUS ///< Number of blood leak detector status. -} BLOOD_LEAK_STATUS_T; + * + * @addtogroup BloodLeak + * @{ + */ +// ********** public definitions ********** + +/// Enumeration of blood leak detector status. +typedef enum BloodLeakDetectorStatus +{ + BLOOD_LEAK_DETECTED = 0, ///< Blood leak detector senses blood. + BLOOD_LEAK_NOT_DETECTED, ///< Blood leak detector does not sense any blood. + NUM_OF_BLOOD_LEAK_STATUS ///< Number of blood leak detector status. +} BLOOD_LEAK_STATUS_T; + /// Blood leak detector data publish typedef struct { U32 bloodLeakStatus; ///< Blood leak detector status. U32 bloodLeakState; ///< Blood leak detector state. U32 bloodLeakPersistentCounter; ///< Blood leak detector persistent counter. U32 bloodLeakSerialCommState; ///< Blood leak detector serial communication state. + U32 bloodLeakIntensity; ///< Blood leak detector intensity. + U32 bloodLeakDetect; ///< Blood leak detector detect. + F32 bloodLeakIntensityMovingAvg; ///< Blood leak detector intensity moving average. + U32 bloodLeakTimeSinceZeroMS; ///< Blood leak detector time since last zero in milliseconds. + U32 driftInRangeStatus; ///< Blood leak detector drift in range status. + U32 driftUpperRangeStatus; ///< Blood leak detector drift upper range status. } BLOOD_LEAK_DATA_T; -// ********** public function prototypes ********** - +// ********** public function prototypes ********** + void initBloodLeak( void ); void execBloodLeak( void ); void execBloodLeakEmbModeCommand( void ); BOOL zeroBloodLeak( void ); -void zeroBloodLeakReset (void ); +void zeroBloodLeakReset( void ); BOOL hasBloodLeakZeroSequenceFailed( void ); +BOOL isBloodLeakZeroingNeeded( void ); void exitBloodLeakNormalState( void ); SELF_TEST_STATUS_T execBloodLeakSelfTest( void ); - + BLOOD_LEAK_STATUS_T getBloodLeakStatus( void ); SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ); -BOOL testSetBloodLeakDataPublishIntervalOverride( U32 value ); +BOOL testSetBloodLeakDataPublishIntervalOverride( U32 value ); BOOL testResetBloodLeakDataPublishIntervalOverride( void ); - -BOOL testSetBloodLeakStatusOverride( BLOOD_LEAK_STATUS_T status ); + +BOOL testSetBloodLeakStatusOverride( BLOOD_LEAK_STATUS_T status ); BOOL testResetBloodLeakStatusOverride( void ); BOOL testSetBloodLeak2EmbeddedMode( void ); BOOL testSetBloodLeakEmbeddedModeCommand( U08 command, U16 setPointPayload ); -/**@}*/ - -#endif +BOOL testSetBloodLeakEmbeddedModeInfoOverride( U08 command, U32 value ); +BOOL testResetBloodLeakEmbeddedModeInfoOverride( U08 command ); + +BOOL testSetBloodLeakIntensityMovingAverageOverride( F32 value ); +BOOL testResetBloodLeakIntensityMovingAverageOverride( void ); + +BOOL testSetBloodLeakZeroingIntervalInMinsOverride( BOOL upperRangeInterval, U32 valueMins ); +BOOL testResetBloodLeakZeroingIntervalInMinsOverride( BOOL upperRangeInterval ); + +/**@}*/ + +#endif Index: firmware/App/HDCommon.h =================================================================== diff -u -r7c79b8922e7799a46b1f10626ad985c58f61f12d -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 7c79b8922e7799a46b1f10626ad985c58f61f12d) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -35,6 +35,7 @@ // #define BOARD_WITH_NO_HARDWARE 1 // Target is a PCB w/ no hardware // #define SIMULATE_UI 1 // Build w/o requirement that UI be there // #define TASK_TIMING_OUTPUT_ENABLED 1 // Re-purposes alarm lamp pins for task timing +// #define CARTRIDGE_TEST_BUILD 1 // Build to support cartridge testing #include #include Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r736cc5b56cc9c784ab1d8fc8687a73d190c35759 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 736cc5b56cc9c784ab1d8fc8687a73d190c35759) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -19,6 +19,7 @@ #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodLeak.h" #include "Buttons.h" #include "Dialysis.h" #include "DialInFlow.h" @@ -51,16 +52,40 @@ #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. +// 3.07 + 12.28 has been received from the mechanical team and extra volume as margin has been added for safety +#define DPI_2_BLD_VOLUME_ML ( 3.07F + 12.28F + 8.0F ) ///< Dialysate inlet pump to blood detect sensor volume in milliliters. +#define RSRVR_2_DPI_VOLUME_ML ( 70.0 + 5.0F ) ///< Reservoir to dialysate inlet pump volume in milliliters. + /// Defined states for the Load Cell cycles. typedef enum Reservoir_Steady_Cycle { - RESERVOIR_STEADY_CYCLE_START = 0, ///< Reservoir steady cycle load cell reading at Start - RESERVOIR_STEADY_CYCLE_FINAL, ///< Reservoir steady cycle load cell reading at Final - NUM_OF_RESERVOIR_STEADY_CYCLES ///< Number of Reservoir steady cycle load cell readings + RESERVOIR_STEADY_CYCLE_START = 0, ///< Reservoir steady cycle load cell reading at Start. + RESERVOIR_STEADY_CYCLE_FINAL, ///< Reservoir steady cycle load cell reading at Final. + NUM_OF_RESERVOIR_STEADY_CYCLES ///< Number of Reservoir steady cycle load cell readings. } RESERVOIR_STEADY_CYCLE_T; +/// Blood leak zeroing request status +typedef enum BLD_Zeroing_Request_Status +{ + BLOOD_LEAK_ZEROING_RQST_READY = 0, ///< Blood leak zeroing request ready. + BLOOD_LEAK_ZEROING_RQST_REQUESTED, ///< Blood leak zeroing request requested. + BLOOD_LEAK_ZEROING_RQST_IN_PROGRESS, ///< Blood leak zeroing request in progress. + NUM_OF_BLOOD_LEAK_ZEROING_RQST ///< Number of blood leak zeroing request. +} BLOOD_LEAK_ZEROING_RQST_T; + // ********** private data ********** +/// Blood leak treatment zeroing data structure +typedef struct +{ + F32 DPi2BLDFlushedVolML; ///< Dialysate inlet pump to blood leak flushed volume in milliliters. + F32 rsrvr2DPiFlushedVolML; ///< Active reservoir to dialysate inlet pump flushed volume in milliliters. + BOOL hasBloodLeakZeroingBeenRequested; ///< Flag to indicate blood leak zeroing has been requested. + BOOL isZeroingRequestedFromTreatmentStop; ///< Flag to indicate blood leak zeroing has been requested from treatment stop. + BLOOD_LEAK_ZEROING_RQST_T zeroingRequestState; ///< Blood leak zeroing request state. + BLOOD_LEAK_ZEROING_STATE_T bloodLeakZeroingState; ///< Blood leak zeroing state. +} BLOOD_LEAK_ZEROING_T ; + static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. @@ -90,11 +115,13 @@ static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. +static BLOOD_LEAK_ZEROING_T bloodLeakZeroingStatus; ///< Blood leak zeroing status. // ********** private function prototypes ********** static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ); +static DIALYSIS_STATE_T handleDialysisBloodLeakZeroingState( void ); static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); @@ -104,6 +131,13 @@ static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushReservoir2DPiState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushDPi2BLDState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingZeroState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingVerifyZeroingState( void ); +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingCompleteState( DIALYSIS_STATE_T *dialysisState ); + static void checkUFControl( void ); static void updateUFVolumes( void ); @@ -160,10 +194,10 @@ resFinalRefVolume[ i ] = 0.0F; resCurrVolume[ i ] = 0.0F; resLastVolume[ i ] = 0.0F; - } resetSalineBolus(); + resetBloodLeakZeroingVariables(); } /*********************************************************************//** @@ -218,6 +252,9 @@ resetReservoirsVariables(); + // Reset the blood leak zeroing variables + resetBloodLeakZeroingVariables(); + // Set valves for dialysis setValvePosition( VDI, VALVE_POSITION_B_OPEN ); setValvePosition( VDO, VALVE_POSITION_B_OPEN ); @@ -502,6 +539,19 @@ /*********************************************************************//** * @brief + * The getBloodLeakZeroingState function gets the current blood leak zeroing + * state of the state machine. + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: none + * @return Current state of the blood leak zeroing state machine + *************************************************************************/ +BLOOD_LEAK_ZEROING_STATE_T getBloodLeakZeroingState( void ) +{ + return bloodLeakZeroingStatus.bloodLeakZeroingState; +} + +/*********************************************************************//** + * @brief * The getUltrafiltrationVolumeCollected function gets the current ultrafiltration * volume collected so far for current treatment. * @details Inputs: measUFVolume @@ -659,6 +709,23 @@ // Check ultrafiltration control during dialysis (even when ultrafiltration is paused). checkUFControl(); + if ( ( TRUE == isBloodLeakZeroingNeeded() ) && ( BLOOD_LEAK_ZEROING_RQST_READY == bloodLeakZeroingStatus.zeroingRequestState ) ) + { + bloodLeakZeroingStatus.zeroingRequestState = BLOOD_LEAK_ZEROING_RQST_REQUESTED; + } + + if ( ( BLOOD_LEAK_ZEROING_RQST_REQUESTED == bloodLeakZeroingStatus.zeroingRequestState ) && ( DIALYSIS_UF_STATE == currentDialysisState ) ) + { + if ( TRUE == checkHasReservoirBeenSwitched() ) + { + requestBloodLeakZeroing( FALSE ); + } + } + + // NOTE: do not move this function this function needs to be after the check for blood leak zeroing logic above. + // If the blood leak logic is no longer needed, the reset function below can be removed. + resetReservoirSwitchFlag(); + // Dialysis state machine switch ( currentDialysisState ) { @@ -670,6 +737,10 @@ currentDialysisState = handleDialysisSalineBolusState(); break; + case DIALYSIS_BLOOD_LEAK_ZEROING_STATE: + currentDialysisState = handleDialysisBloodLeakZeroingState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_STATE, currentDialysisState ) break; @@ -785,6 +856,23 @@ /*********************************************************************//** * @brief + * The handleDialysisBloodLeakZeroingState function handles the blood leak + * zeroing sub state of the state machine. + * @details Inputs: none + * @details Outputs: none + * @return next Dialysis state. + *************************************************************************/ +static DIALYSIS_STATE_T handleDialysisBloodLeakZeroingState( void ) +{ + DIALYSIS_STATE_T result = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + + result = execBloodLeakZeroing(); + + return result; +} + +/*********************************************************************//** + * @brief * The handleUFPausedState function handles the Paused state of the * ultrafiltration state machine. * @details Inputs: salineBolusStartRequested @@ -811,6 +899,19 @@ salineBolusStartRequested = FALSE; } } + else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + autoResumeUF = FALSE; + if ( BLD_ZEROING_IDLE_STATE == bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + *dialysisState = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + } + else + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + } + } return result; } @@ -863,6 +964,20 @@ salineBolusStartRequested = FALSE; } } + else if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + if ( BLD_ZEROING_IDLE_STATE == bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + autoResumeUF = TRUE; + result = UF_PAUSED_STATE; + *dialysisState = DIALYSIS_BLOOD_LEAK_ZEROING_STATE; + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + } + else + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + } + } return result; } @@ -1008,7 +1123,6 @@ setCurrentSubState( (U32)DIALYSIS_UF_STATE ); setCurrent4thLevelState( (U32)currentUFState ); sendOperationStatusEvent(); - } signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Resume dialysis @@ -1041,6 +1155,183 @@ /*********************************************************************//** * @brief + * The handleBloodLeakZeroingIdleState function handles the blood leak zeroing + * idle state. In this state the actuators and parameters are set to run + * the blood leak zeroing state machine. + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingIdleState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_IDLE_STATE; + + if ( TRUE == bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested ) + { + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + state = BLD_ZEROING_FLUSH_RSRVR_2_DPI_STATE; + + if ( TRUE == bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop ) + { + // Cmd DPo to stop + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + + state = BLD_ZEROING_ZERO_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingFlushReservoir2DPiState function handles the + * blood leak zeroing flush reservoir to dialysate inlet pump state. + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushReservoir2DPiState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_FLUSH_RSRVR_2_DPI_STATE; + F32 measuredDPiMLPM = getMeasuredDialInFlowRate(); + + bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML += ( (F32)( measuredDPiMLPM * TASK_GENERAL_INTERVAL ) / (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); + + if ( bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML > RSRVR_2_DPI_VOLUME_ML ) + { + // Cmd DPo to stop + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + stopSyringePump(); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + + state = BLD_ZEROING_FLUSH_DPI_2_BLD_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingFlushDPi2BLDState function handles the blood + * leak zeroing + * flush state. In this state, the line in between the dialysate inlet pump + * to blood leak detector is flushed with new dialysate. + * @details Inputs: bloodLeakZeroingStatus + * @details Outputs: bloodLeakZeroingStatus + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingFlushDPi2BLDState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_FLUSH_DPI_2_BLD_STATE; + F32 measuredDPiMLPM = getMeasuredDialInFlowRate(); + + bloodLeakZeroingStatus.DPi2BLDFlushedVolML += ( (F32)( measuredDPiMLPM * TASK_GENERAL_INTERVAL ) / (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); + + if ( bloodLeakZeroingStatus.DPi2BLDFlushedVolML > DPI_2_BLD_VOLUME_ML ) + { + state = BLD_ZEROING_ZERO_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingZeroState function handles the blood leak zeroing + * zero state. In this state, the zero blood leak command is issued. + * @details Inputs: none + * @details Outputs: none + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingZeroState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_ZERO_STATE; + + if ( TRUE == zeroBloodLeak() ) + { + state = BLD_ZEROING_VERIFY_ZEROING_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingVerifyZeroingState function handles the blood + * leak verifying whether zeroing was successful or not. Based on the pass + * or fail status of the blood leak zeroing the state transition occurs. + * @details Inputs: none + * @details Outputs: none + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingVerifyZeroingState( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_VERIFY_ZEROING_STATE; + SELF_TEST_STATUS_T zeroSelfTestStatus = getBloodLeakSelfTestStatus(); + + if ( SELF_TEST_STATUS_PASSED == zeroSelfTestStatus ) + { + state = BLD_ZEROING_COMPLETE_STATE; + } + else if ( SELF_TEST_STATUS_FAILED == zeroSelfTestStatus ) + { + if ( TRUE == hasBloodLeakZeroSequenceFailed() ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); + } + else + { + state = BLD_ZEROING_ZERO_STATE; + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingCompleteState function handles the blood + * leak complete state. The state requests a transition back to dialysis + * if the request to zero the blood leak was issued from the dialysis sub-mode. + * @details Inputs: bloodLeakZeroingStatus, autoResumeUF + * @details Outputs: bloodLeakZeroingStatus, autoResumeUF, currentUFState + * @param pointer to the local dialysis state + * @return next state of the blood leak zeroing state + *************************************************************************/ +static BLOOD_LEAK_ZEROING_STATE_T handleBloodLeakZeroingCompleteState( DIALYSIS_STATE_T *dialysisState ) +{ + BLOOD_LEAK_ZEROING_STATE_T state = BLD_ZEROING_COMPLETE_STATE; + + if ( FALSE == bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop ) + { + *dialysisState = DIALYSIS_UF_STATE; + + // Resume UF if appropriate + if ( TRUE == autoResumeUF ) + { + autoResumeUF = FALSE; + currentUFState = UF_RUNNING_STATE; + //Set substate for event + setCurrentSubState( (U32)DIALYSIS_UF_STATE ); + setCurrent4thLevelState( (U32)currentUFState ); + sendOperationStatusEvent(); + } + + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Resume dialysis + transitionToDialysis(); + } + + return state; +} + +/*********************************************************************//** + * @brief * The publishSalineBolusData function handles the max saline delivered * state of the saline bolus state machine. This is a terminal state. * @details Inputs: none @@ -1054,9 +1345,13 @@ { SALINE_BOLUS_DATA_PAYLOAD_T data; - data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; - data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; + data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; + data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; + data.bloodLeakZeroingDPi2BLDFlushVolumeML = bloodLeakZeroingStatus.DPi2BLDFlushedVolML; + data.bloodLeakZeroingRsrvr2DPiFlushVolumeML = bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML; + data.bloodLeakZeroingNeededAfterRsrvrSwitch = (U32)bloodLeakZeroingStatus.zeroingRequestState; + broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); salineBolusBroadcastTimerCtr = 0; } @@ -1233,6 +1528,100 @@ /*********************************************************************//** * @brief + * The execBloodLeakZeroing function handles the blood leak zeroing sequence + * @details Inputs: bloodLeakZeroing + * @details Outputs: bloodLeakZeroing + * @return next state of the dialysis state machine + *************************************************************************/ +DIALYSIS_STATE_T execBloodLeakZeroing( void ) +{ + BLOOD_LEAK_ZEROING_STATE_T prevState = bloodLeakZeroingStatus.bloodLeakZeroingState; + DIALYSIS_STATE_T dialysisState = currentDialysisState; + + switch( bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + case BLD_ZEROING_IDLE_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingIdleState(); + break; + + case BLD_ZEROING_FLUSH_RSRVR_2_DPI_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingFlushReservoir2DPiState(); + break; + + case BLD_ZEROING_FLUSH_DPI_2_BLD_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingFlushDPi2BLDState(); + break; + + case BLD_ZEROING_ZERO_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingZeroState(); + break; + + case BLD_ZEROING_VERIFY_ZEROING_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingVerifyZeroingState(); + break; + + case BLD_ZEROING_COMPLETE_STATE: + bloodLeakZeroingStatus.bloodLeakZeroingState = handleBloodLeakZeroingCompleteState( &dialysisState ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_BLOOD_LEAK_ZEROING_STATE, + bloodLeakZeroingStatus.bloodLeakZeroingState ) + break; + } + + if ( prevState != bloodLeakZeroingStatus.bloodLeakZeroingState ) + { + setCurrent4thLevelState( (U32)bloodLeakZeroingStatus.bloodLeakZeroingState ); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, prevState, bloodLeakZeroingStatus.bloodLeakZeroingState ) + } + + return dialysisState; +} + +/*********************************************************************//** + * @brief + * The requestBloodLeakZeroing function sets the flag the requests the + * blood leak zeroing. + * @details Inputs: none + * @details Outputs: bloodLeakZeroing + * @return none + *************************************************************************/ +void requestBloodLeakZeroing( BOOL isRequestFromTreatmentStop ) +{ + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = TRUE; + bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop = isRequestFromTreatmentStop; + bloodLeakZeroingStatus.zeroingRequestState = BLOOD_LEAK_ZEROING_RQST_IN_PROGRESS; + bloodLeakZeroingStatus.bloodLeakZeroingState = BLD_ZEROING_IDLE_STATE; + + if ( FALSE == isRequestFromTreatmentStop ) + { + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + } + + SEND_EVENT_WITH_2_F32_DATA( HD_EVENT_BLOOD_LEAK_ZEROING_REQUIRED, 0, 0 ) +} + +/*********************************************************************//** + * @brief + * The resetBloodLeakZeroingVariables function resets the blood leak zeroing + * variables. + * @details Inputs: none + * @details Outputs: bloodLeakZeroing + * @return none + *************************************************************************/ +void resetBloodLeakZeroingVariables( void ) +{ + bloodLeakZeroingStatus.DPi2BLDFlushedVolML = 0.0F; + bloodLeakZeroingStatus.rsrvr2DPiFlushedVolML = 0.0F; + bloodLeakZeroingStatus.bloodLeakZeroingState = BLD_ZEROING_IDLE_STATE; + bloodLeakZeroingStatus.hasBloodLeakZeroingBeenRequested = FALSE; + bloodLeakZeroingStatus.isZeroingRequestedFromTreatmentStop = FALSE; + bloodLeakZeroingStatus.zeroingRequestState = BLOOD_LEAK_ZEROING_RQST_READY; +} + +/*********************************************************************//** + * @brief * The checkLoadCellsStablePrimaryBackupDriftOutOfRange function checks the * load cells' primary and backup drift when the reservoir level has been stable * for greater than large filter time. Index: firmware/App/Modes/Dialysis.h =================================================================== diff -u -r20d0c02f453b6dae1884fb1b5ba542053852ffc1 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 20d0c02f453b6dae1884fb1b5ba542053852ffc1) +++ firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -44,6 +44,9 @@ U32 tgtSalineVolumeMl; ///< Target saline volume in mL. F32 cumSalineVolumeMl; ///< Cumulative saline volume in mL. F32 bolSalineVolumeMl; ///< Bolus saline volume in mL. + F32 bloodLeakZeroingDPi2BLDFlushVolumeML; ///< Blood leak zeroing DPi to BLD flush volume in mL. + F32 bloodLeakZeroingRsrvr2DPiFlushVolumeML; ///< Blood leak zeroing reservoir to DPi flush volume in mL. + U32 bloodLeakZeroingNeededAfterRsrvrSwitch; ///< Blood leak zeroing needed after reservoir switch. } SALINE_BOLUS_DATA_PAYLOAD_T; #pragma pack(pop) @@ -66,6 +69,7 @@ DIALYSIS_STATE_T getDialysisState( void ); UF_STATE_T getUltrafiltrationState( void ); SALINE_BOLUS_STATE_T getSalineBolusState( void ); +BLOOD_LEAK_ZEROING_STATE_T getBloodLeakZeroingState( void ); F32 getUltrafiltrationVolumeCollected( void ); F32 getUltrafiltrationReferenceVolume( void ); @@ -80,6 +84,10 @@ void setFinalReservoirVolume( void ); F32 getReservoirUltrafiltrationVol( DG_RESERVOIR_ID_T reservoirID ); +DIALYSIS_STATE_T execBloodLeakZeroing( void ); +void requestBloodLeakZeroing( BOOL isRequestFromTreatmentStop ); +void resetBloodLeakZeroingVariables( void ); + /**@}*/ #endif Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -re8edb83fcba5c355198efc30944d51c54814bdbe -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision e8edb83fcba5c355198efc30944d51c54814bdbe) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -1176,6 +1176,12 @@ { DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + if ( TRUE == isBloodLeakZeroingNeeded() ) + { + // If the sensor has drifted request a zero prior to transitioning to treatment + zeroBloodLeak(); + } + patientConnectionConfirm = FALSE; doorOpened = FALSE; setStartReservoirVolume( activeRes ); Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r42c6233847246407d81549a66458b12d3e3a27ac -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 42c6233847246407d81549a66458b12d3e3a27ac) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -77,6 +77,12 @@ /// Interval (in task intervals) at which to publish standby mode data to CAN bus. static OVERRIDE_U32_T standbyModePublishInterval = { DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, 0 }; +#ifdef CARTRIDGE_TEST_BUILD // Variables and definitions used only for cartridge test build. +#define CARTRIDGE_TEST_COMPLETE_TIME ( ( 10 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) +static BOOL testCartridgesMode = FALSE; // Flag indicates we are testing cartridges. +static U32 testCartridgesTimerCtr = 0; // Test timer counter. +#endif + // ********** private function prototypes ********** static HD_STANDBY_STATE_T handleStandbyModeStartState( void ); @@ -231,6 +237,49 @@ break; } +#ifdef CARTRIDGE_TEST_BUILD + if ( TRUE == testCartridgesMode ) + { + if ( ++testCartridgesTimerCtr >= CARTRIDGE_TEST_COMPLETE_TIME ) + { + stop = TRUE; // Stop cartridge test after 10 hrs + } + if ( TRUE == isAlarmActive( ALARM_ID_HD_FLUID_LEAK_DETECTED ) ) + { + stop = TRUE; // Stop cartridge test if a fluid leak is detected + } + } + + if ( TRUE == stop ) + { + if ( testCartridgesMode != TRUE ) + { + testSetBloodPumpTargetDutyCycle( 0.652F ); + testSetDialInPumpTargetDutyCycle( 0.701F ); + testSetDialOutPumpTargetDutyCycle( 0.566F ); + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + setValveAirTrap( STATE_CLOSED ); + testCartridgesMode = TRUE; + } + else + { + signalBloodPumpHardStop(); + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); + setValveAirTrap( STATE_OPEN ); + testCartridgesMode = FALSE; + testCartridgesTimerCtr = 0; + } + } +#endif + return currentStandbyState; } Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r8cf0fafa78ce14b5dbdf95510e957846660ac2b9 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 8cf0fafa78ce14b5dbdf95510e957846660ac2b9) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -18,6 +18,7 @@ #include "AirTrap.h" #include "AlarmLamp.h" #include "BloodFlow.h" +#include "BloodLeak.h" #include "Buttons.h" #include "DGInterface.h" #include "DialInFlow.h" @@ -787,10 +788,24 @@ U32 msSinceLast = calcTimeBetween( lastTreatmentTimeStamp, newTime ); DIALYSIS_STATE_T dialysisState = getDialysisState(); - // Update treatment time (unless delivering a saline bolus) - if ( dialysisState != DIALYSIS_SALINE_BOLUS_STATE ) + // Update treatment time (unless delivering a saline bolus or is in blood leak zeroing state other than flush reservoir to DPi state) + switch ( dialysisState ) { - treatmentTimeMS += msSinceLast; + case DIALYSIS_START_STATE: + case DIALYSIS_UF_STATE: + treatmentTimeMS += msSinceLast; + break; + + case DIALYSIS_BLOOD_LEAK_ZEROING_STATE: + if ( BLD_ZEROING_FLUSH_RSRVR_2_DPI_STATE == getBloodLeakZeroingState() ) + { + treatmentTimeMS += msSinceLast; + } + + case DIALYSIS_SALINE_BOLUS_STATE: + default: + // Do not accumulate treatment time + break; } lastTreatmentTimeStamp = newTime; @@ -1495,6 +1510,7 @@ payload.txEndState = getCurrentTreatmentEndState(); payload.heparinState = getHeparinState(); payload.dialysisState = getDialysisState(); + payload.bloodLeakZeroingState = (U32)getBloodLeakZeroingState(); broadcastData( MSG_ID_TREATMENT_STATE_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TREATMENT_STATE_DATA_T ) ); treatmentStateBroadcastTimerCtr = 0; Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -r20d0c02f453b6dae1884fb1b5ba542053852ffc1 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 20d0c02f453b6dae1884fb1b5ba542053852ffc1) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -54,6 +54,7 @@ U32 txEndState; ///< Treatment end state. U32 txStopState; ///< Treatment stop state. U32 dialysisState; ///< Dialysis state. + U32 bloodLeakZeroingState; ///< Blood leak zeroing state. } TREATMENT_STATE_DATA_T; /// Payload record structure for an ultrafiltration volume change confirmation message. Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -r736cc5b56cc9c784ab1d8fc8687a73d190c35759 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 736cc5b56cc9c784ab1d8fc8687a73d190c35759) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -118,6 +118,9 @@ // Reset saline bolus state in case alarm interrupted one resetSalineBolus(); + // Reset blood leak zeroing params + resetBloodLeakZeroingVariables(); + // Enable venous bubble detection (in case returning from mid-treatment rinseback) setVenousBubbleDetectionEnabled( TRUE ); @@ -201,6 +204,7 @@ doorClosedRequired( TRUE, TRUE ); cmdStartDGTrimmerHeater(); setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_BLOOD_DETECT_RECOVERY_MLPM, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + requestBloodLeakZeroing( TRUE ); } /*********************************************************************//** @@ -302,41 +306,48 @@ TREATMENT_STOP_STATE_T result = state; BOOL bloodRecircBlocked = isBloodRecircBlocked(); BOOL dialysateRecircBlocked = isDialysateRecircBlocked(); + BOOL bldAlarmsStatus = ( ( TRUE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ) ) && + ( FALSE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_DETECTED ) ? TRUE : FALSE ) ); - if ( ( TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE != state ) && ( dialysateRecircBlocked != TRUE ) && - ( TRUE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ) ) && ( FALSE == isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_DETECTED ) ) ) + if ( TRUE == bldAlarmsStatus ) { - setupForRecoverBloodDetectState(); - result = TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE; + if ( ( TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE != state ) && ( dialysateRecircBlocked != TRUE ) ) + { + setupForRecoverBloodDetectState(); + result = TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE; + } } - // Both unblocked and not in recirculate both state - else if ( ( TREATMENT_STOP_RECIRC_STATE != state ) && ( FALSE == dialysateRecircBlocked ) && ( FALSE == bloodRecircBlocked ) ) + else { - setupForBloodRecirculationState(); - setupForDialysateRecirculationState(); - result = TREATMENT_STOP_RECIRC_STATE; + // Both unblocked and not in recirculate both state + if ( ( TREATMENT_STOP_RECIRC_STATE != state ) && ( FALSE == dialysateRecircBlocked ) && ( FALSE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationState(); + setupForDialysateRecirculationState(); + result = TREATMENT_STOP_RECIRC_STATE; + } + // Both blocked and not in stopped state + else if ( ( TREATMENT_STOP_NO_RECIRC_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && ( TRUE == bloodRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_NO_RECIRC_STATE; + } + // Dialysate recirculation blocked and not in blood recirc state + else if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && + ( FALSE == bloodRecircBlocked ) ) + { + setupForDialysateRecirculationStopState(); + result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; + } + // Blood recirculation blocked and not in dialysate recirc state + else if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) && ( TRUE == bloodRecircBlocked ) && + ( FALSE == dialysateRecircBlocked ) ) + { + setupForBloodRecirculationStopState(); + result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; + } } - // Both blocked and not in stopped state - else if ( ( TREATMENT_STOP_NO_RECIRC_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && ( TRUE == bloodRecircBlocked ) ) - { - setupForBloodRecirculationStopState(); - setupForDialysateRecirculationStopState(); - result = TREATMENT_STOP_NO_RECIRC_STATE; - } - // Dialysate recirculation blocked and not in blood recirc state - else if ( ( TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE != state ) && ( TRUE == dialysateRecircBlocked ) && - ( FALSE == bloodRecircBlocked ) ) - { - setupForDialysateRecirculationStopState(); - result = TREATMENT_STOP_RECIRC_BLOOD_ONLY_STATE; - } - // Blood recirculation blocked and not in dialysate recirc state - else if ( ( TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE != state ) && ( TRUE == bloodRecircBlocked ) && - ( FALSE == dialysateRecircBlocked ) ) - { - setupForBloodRecirculationStopState(); - result = TREATMENT_STOP_RECIRC_DIALYSATE_ONLY_STATE; - } return result; } @@ -427,6 +438,8 @@ { TREATMENT_STOP_STATE_T result = TREATMENT_STOP_RECOVER_BLOOD_DETECT_STATE; + execBloodLeakZeroing(); + // Keep reseting the blood sitting timer handleTreatmentStopBloodSittingTimer(); result = handleTreatmentStopAlarmsAndSignals( result ); Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -rf5d4fecd7b937ddf8e8b4ef3372541e79c7a44fc -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision f5d4fecd7b937ddf8e8b4ef3372541e79c7a44fc) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -14,82 +14,82 @@ * @date (original) 20-May-2021 * ***************************************************************************/ - -#ifndef __ALARM_MGMT_SW_FAULTS_H__ -#define __ALARM_MGMT_SW_FAULTS_H__ - -/** - * @addtogroup AlarmManagement - * @{ - */ - -// ********** public definitions ********** - -/// Listing of specific software faults for logging purposes. -typedef enum -{ - SW_FAULT_ID_NONE = 0, - SW_FAULT_ID_ALARM_LAMP_INVALID_PATTERN_REQUESTED, - SW_FAULT_ID_ALARM_LAMP_INVALID_SELF_TEST_STATE, - SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, - SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_STATE, - SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_DIRECTION, // 5 - SW_FAULT_ID_BUTTONS_INVALID_SELF_TEST_STATE, - SW_FAULT_ID_BUTTONS_STOP_BUTTON_NOT_CONSUMED, - SW_FAULT_ID_INT_ADC_DATA_OVERRUN, - SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED, - SW_FAULT_ID_MODE_INIT_POST_INVALID_POST_STATE, // 10 - SW_FAULT_ID_OP_MODES_ILLEGAL_MODE_TRANSITION_REQUESTED, - SW_FAULT_ID_OP_MODES_INVALID_MODE_STATE, - SW_FAULT_ID_OP_MODES_INVALID_MODE_REQUESTED, - SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, - SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, // 15 - SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, - SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, - SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, - SW_FAULT_ID_COMM_BUFFERS_ADD_INVALID_BUFFER, - SW_FAULT_ID_COMM_BUFFERS_GET_INVALID_BUFFER, // 20 - SW_FAULT_ID_COMM_BUFFERS_PEEK_INVALID_BUFFER, - SW_FAULT_ID_COMM_BUFFERS_COUNT_INVALID_BUFFER, - SW_FAULT_ID_FPGA_INVALID_IN_STATE, - SW_FAULT_ID_FPGA_INVALID_OUT_STATE, - SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, // 25 - SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, - SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, - SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, - SW_FAULT_ID_MSG_QUEUES_ADD_QUEUE_FULL, - SW_FAULT_ID_MSG_QUEUES_ADD_INVALID_QUEUE, // 30 - SW_FAULT_ID_MSG_QUEUES_GET_INVALID_QUEUE, - SW_FAULT_ID_MSG_QUEUES_IS_EMPTY_INVALID_QUEUE, - SW_FAULT_ID_MSG_QUEUES_IS_FULL_INVALID_QUEUE, - SW_FAULT_ID_WATCHDOG_INVALID_SELF_TEST_STATE, - SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, // 35 - SW_FAULT_ID_DIAL_IN_FLOW_INVALID_DIAL_IN_PUMP_DIRECTION, - SW_FAULT_ID_DIAL_IN_FLOW_INVALID_DIAL_IN_PUMP_STATE, - SW_FAULT_ID_DIAL_IN_FLOW_SET_TOO_HIGH, - SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_DIRECTION, - SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_STATE, // 40 - SW_FAULT_ID_DIAL_OUT_FLOW_SET_TOO_HIGH, - SW_FAULT_ID_ALARM_MGMT_AUDIO_INVALID_ALARM_STATE, - SW_FAULT_ID_FPGA_INVALID_ALARM_AUDIO_PARAM, - SW_FAULT_ID_RTC_EXEC_INVALID_STATE, - SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, // 45 - SW_FAULT_ID_RTC_TRANSACTION_SERVICE_INVALID_STATE, - SW_FAULT_ID_PRES_OCCL_INVALID_STATE, - SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_SIGNAL_ACTION, - SW_FAULT_ID_ALARM_MGMT_INVALID_USER_ACTION, - SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL, // 50 - SW_FAULT_ID_PI_CTRL_INVALID_CONTROLLER, - SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL, - SW_FAULT_ID_MODE_TREATMENT_INVALID_ALARM_ACTION, - SW_FAULT_ID_MODE_PRE_TREATMENT_RESERVOIR_MGMT_INVALID_STATE, - SW_FAULT_ID_DIALYSIS_INVALID_STATE, // 55 - SW_FAULT_ID_DIALYSIS_INVALID_UF_STATE, - SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, - SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, - SW_FAULT_ID_MODE_TREATMENT_INVALID_STATE, - SW_FAULT_ID_INTERRUPTS_INVALID_EDGE_DETECTED, // 60 - SW_FAULT_ID_INVALID_DG_PRESSURE_ID, + +#ifndef __ALARM_MGMT_SW_FAULTS_H__ +#define __ALARM_MGMT_SW_FAULTS_H__ + +/** + * @addtogroup AlarmManagement + * @{ + */ + +// ********** public definitions ********** + +/// Listing of specific software faults for logging purposes. +typedef enum +{ + SW_FAULT_ID_NONE = 0, + SW_FAULT_ID_ALARM_LAMP_INVALID_PATTERN_REQUESTED, + SW_FAULT_ID_ALARM_LAMP_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, + SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_STATE, + SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_DIRECTION, // 5 + SW_FAULT_ID_BUTTONS_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_BUTTONS_STOP_BUTTON_NOT_CONSUMED, + SW_FAULT_ID_INT_ADC_DATA_OVERRUN, + SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED, + SW_FAULT_ID_MODE_INIT_POST_INVALID_POST_STATE, // 10 + SW_FAULT_ID_OP_MODES_ILLEGAL_MODE_TRANSITION_REQUESTED, + SW_FAULT_ID_OP_MODES_INVALID_MODE_STATE, + SW_FAULT_ID_OP_MODES_INVALID_MODE_REQUESTED, + SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, + SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, // 15 + SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, + SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, + SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, + SW_FAULT_ID_COMM_BUFFERS_ADD_INVALID_BUFFER, + SW_FAULT_ID_COMM_BUFFERS_GET_INVALID_BUFFER, // 20 + SW_FAULT_ID_COMM_BUFFERS_PEEK_INVALID_BUFFER, + SW_FAULT_ID_COMM_BUFFERS_COUNT_INVALID_BUFFER, + SW_FAULT_ID_FPGA_INVALID_IN_STATE, + SW_FAULT_ID_FPGA_INVALID_OUT_STATE, + SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, // 25 + SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, + SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, + SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, + SW_FAULT_ID_MSG_QUEUES_ADD_QUEUE_FULL, + SW_FAULT_ID_MSG_QUEUES_ADD_INVALID_QUEUE, // 30 + SW_FAULT_ID_MSG_QUEUES_GET_INVALID_QUEUE, + SW_FAULT_ID_MSG_QUEUES_IS_EMPTY_INVALID_QUEUE, + SW_FAULT_ID_MSG_QUEUES_IS_FULL_INVALID_QUEUE, + SW_FAULT_ID_WATCHDOG_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, // 35 + SW_FAULT_ID_DIAL_IN_FLOW_INVALID_DIAL_IN_PUMP_DIRECTION, + SW_FAULT_ID_DIAL_IN_FLOW_INVALID_DIAL_IN_PUMP_STATE, + SW_FAULT_ID_DIAL_IN_FLOW_SET_TOO_HIGH, + SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_DIRECTION, + SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_STATE, // 40 + SW_FAULT_ID_DIAL_OUT_FLOW_SET_TOO_HIGH, + SW_FAULT_ID_ALARM_MGMT_AUDIO_INVALID_ALARM_STATE, + SW_FAULT_ID_FPGA_INVALID_ALARM_AUDIO_PARAM, + SW_FAULT_ID_RTC_EXEC_INVALID_STATE, + SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, // 45 + SW_FAULT_ID_RTC_TRANSACTION_SERVICE_INVALID_STATE, + SW_FAULT_ID_PRES_OCCL_INVALID_STATE, + SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_SIGNAL_ACTION, + SW_FAULT_ID_ALARM_MGMT_INVALID_USER_ACTION, + SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL, // 50 + SW_FAULT_ID_PI_CTRL_INVALID_CONTROLLER, + SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL, + SW_FAULT_ID_MODE_TREATMENT_INVALID_ALARM_ACTION, + SW_FAULT_ID_MODE_PRE_TREATMENT_RESERVOIR_MGMT_INVALID_STATE, + SW_FAULT_ID_DIALYSIS_INVALID_STATE, // 55 + SW_FAULT_ID_DIALYSIS_INVALID_UF_STATE, + SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, + SW_FAULT_ID_MODE_TREATMENT_INVALID_STATE, + SW_FAULT_ID_INTERRUPTS_INVALID_EDGE_DETECTED, // 60 + SW_FAULT_ID_INVALID_DG_PRESSURE_ID, SW_FAULT_ID_CAN_PARITY_ERROR, SW_FAULT_ID_CAN_PASSIVE_WARNING, SW_FAULT_ID_CAN_OFF_ERROR, @@ -189,9 +189,10 @@ SW_FAULT_ID_BATTERY_INVALID_MANAGEMENT_DATA_STATE, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MIN_LIMIT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MAX_LIMIT, // 160 - NUM_OF_SW_FAULT_IDS -} SW_FAULT_ID_T; - + SW_FAULT_ID_MODE_TREATMENT_INVALID_BLOOD_LEAK_ZEROING_STATE, + NUM_OF_SW_FAULT_IDS +} SW_FAULT_ID_T; + /**@}*/ -#endif +#endif Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -ra36a3feca5d35137f1db0293882af0f49ebb9f03 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision a36a3feca5d35137f1db0293882af0f49ebb9f03) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -96,6 +96,7 @@ static F32 previousUFFlowMLP; ///< Previous ultrafiltration flow rate in mL/min. static DG_MIXING_RATIOS_T ratios; ///< Mixing ratios and fill prep time in milliseconds structure. static U32 prevTargetFillVolumeML[ NUM_OF_DG_RESERVOIRS ]; ///< Previous target fill volume in milliliters. +static BOOL hasReservoirBeenSwitched; ///< Flag to indicate reservoir has been recently switched. static const F32 RESERVOIR_DILUTION_RATIO = MAX_RESERVOIR_DILUTION / ( 1.0 - MAX_RESERVOIR_DILUTION ); ///< Reservoir dilution ratio. @@ -127,7 +128,7 @@ * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, * timeReservoirInUse, volSpentUFML, activeReservoir, recirculationLevelPct, * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM, ratios - * previousDialysateFlowRate, prevTargetFillVolumeML + * previousDialysateFlowRate, prevTargetFillVolumeML, hasReservoirBeenSwitched * @return none *************************************************************************/ void initReservoirs( void ) @@ -155,6 +156,7 @@ ratios.acidMixingRatio = 0.0F; ratios.bicarbMixingRatio = 0.0F; ratios.timeFillPrepMS = 0; + hasReservoirBeenSwitched = FALSE; // Initialize the previous reservoir fill volume prevTargetFillVolumeML[ DG_RESERVOIR_1 ] = FILL_RESERVOIR_TO_VOLUME_ML; @@ -270,6 +272,32 @@ timeReservoirInUF += TASK_GENERAL_INTERVAL; } +/*********************************************************************//** + * @brief + * The checkHasReservoirBeenSwitched function returns the reservoir has been + * switched flag. + * @details Inputs: hasReservoirBeenSwitched + * @details Outputs: hasReservoirBeenSwitched + * @return reservoir has been switched flag + *************************************************************************/ +BOOL checkHasReservoirBeenSwitched( void ) +{ + return hasReservoirBeenSwitched; +} + +/*********************************************************************//** + * @brief + * The resetReservoirSwitchFlag function resets the reservoir has been + * switched flag. + * @details Inputs: none + * @details Outputs: hasReservoirBeenSwitched + * @return none + *************************************************************************/ +void resetReservoirSwitchFlag( void ) +{ + hasReservoirBeenSwitched = FALSE; +} + // ********** private functions ********** /*********************************************************************//** @@ -675,7 +703,8 @@ * The handleReservoirMgmtWaitForSwitchSettleState function executes the reservoir * management wait for switch to settle state. * @details Inputs: reservoirSwitchStartTimeMS - * @details Outputs: timeReservoirInUse + * @details Outputs: timeReservoirInUse, lastTimeReservoirInUF, timeReservoirInUF + * hasReservoirBeenSwitched * @return next reservoir management state of the state machine *************************************************************************/ static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtWaitForSwitchSettleState( void ) @@ -685,9 +714,10 @@ if ( TRUE == didTimeout( reservoirSwitchStartTimeMS, RESERVOIR_USED_SETTLE_TIME_MS ) ) { // Switching the active reservoir so reset the reservoir in use timer - lastTimeReservoirInUF = timeReservoirInUF; - timeReservoirInUF = 0; - timeReservoirInUse = 0; + lastTimeReservoirInUF = timeReservoirInUF; + timeReservoirInUF = 0; + timeReservoirInUse = 0; + hasReservoirBeenSwitched = TRUE; // Signal dialysis sub-mode to capture final volume of prior reservoir after settling. setFinalReservoirVolume(); Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r20d0c02f453b6dae1884fb1b5ba542053852ffc1 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 20d0c02f453b6dae1884fb1b5ba542053852ffc1) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -56,6 +56,9 @@ void updateReservoirUFTime( void ); // Update time spent doing ultrafiltration for currently active reservoir U32 getLastReservoirUFTimeInMs( void ); // Get the time spent doing ultrafiltration on the previously active reservoir +BOOL checkHasReservoirBeenSwitched( void ); +void resetReservoirSwitchFlag( void ); + BOOL testSetRecirculationLevelPctOverride( F32 value ); // Set override for reciruclation percentage BOOL testResetRecirculationLevelPctOverride( void ); // Reset override for recirulation percentage /**@}*/ Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r8cf0fafa78ce14b5dbdf95510e957846660ac2b9 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 8cf0fafa78ce14b5dbdf95510e957846660ac2b9) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -14,236 +14,236 @@ * @date (original) 05-Nov-2019 * ***************************************************************************/ - -#include // For memcpy() - -#include "can.h" -#include "sci.h" -#include "sys_dma.h" - -#include "Comm.h" -#include "Interrupts.h" + +#include // For memcpy() + +#include "can.h" +#include "sci.h" +#include "sys_dma.h" + +#include "Comm.h" +#include "Interrupts.h" #include "OperationModes.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "Interrupts.h" -#include "OperationModes.h" -#include "Timers.h" -#include "Utilities.h" - +#include "OperationModes.h" +#include "Timers.h" +#include "Utilities.h" + /** * @addtogroup SystemComm * @{ */ -// ********** private definitions ********** - -#define NUM_OF_CAN_OUT_BUFFERS 5 ///< Number of CAN buffers for transmit -#define NUM_OF_CAN_IN_BUFFERS 7 ///< Number of CAN buffers for receiving +// ********** private definitions ********** + +#define NUM_OF_CAN_OUT_BUFFERS 5 ///< Number of CAN buffers for transmit +#define NUM_OF_CAN_IN_BUFFERS 7 ///< Number of CAN buffers for receiving #define NUM_OF_MSG_IN_BUFFERS 7 ///< Number of Msg buffers for receiving - -#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< If transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on + +#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< If transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on #define MAX_XMIT_RETRIES 5 ///< Maximum number of retries on no transmit complete interrupt timeout - + #define UI_COMM_TIMEOUT_IN_MS 7500 ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD. -#define UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS (2 * SEC_PER_MIN * MS_PER_SECOND) ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD when in service mode. -#define DG_COMM_TIMEOUT_IN_MS 1000 ///< DG has not checked in for this much time - -#define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm -#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window - -#define MSG_NOT_ACKED_TIMEOUT_MS 250 ///< Maximum time for a Denali message that requires ACK to be ACK'd +#define UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS (2 * SEC_PER_MIN * MS_PER_SECOND) ///< Maximum time (in ms) that UI is allowed to wait before checking in with HD when in service mode. +#define DG_COMM_TIMEOUT_IN_MS 1000 ///< DG has not checked in for this much time -#define MSG_NOT_ACKED_MAX_RETRIES 10 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm -#define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time +#define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm +#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window +#define MSG_NOT_ACKED_TIMEOUT_MS 250 ///< Maximum time for a Denali message that requires ACK to be ACK'd + +#define MSG_NOT_ACKED_MAX_RETRIES 10 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm +#define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time + #define MAX_FPGA_CLOCK_SPEED_ERRORS 3 ///< maximum number of FPGA clock speed errors within window period before alarm #define MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< FPGA clock speed error window #define PENDING_ACK_LIST_OVERRIDE_UI_CHANNEL 1 ///< Value for determining UI channel when Pending ACKs are overriden. #define PENDING_ACK_LIST_OVERRIDE_DG_CHANNEL 2 ///< Value for determining DG channel when Pending ACKs are overriden. -#pragma pack(push, 1) - +#pragma pack(push, 1) + /// Record for transmitted message that is pending acknowledgment from receiver. -typedef struct -{ - BOOL used; ///< Used. - U16 seqNo; ///< Message sequence number. - U16 retries; ///< Number of retries. - U32 timeStamp; ///< Time stamp. - COMM_BUFFER_T channel; ///< Channel ID. - U32 msgSize; ///< Message size. - U08 msg[ MAX_ACK_MSG_SIZE ]; ///< Message. -} PENDING_ACK_RECORD_T; - -#pragma pack(pop) - -// ********** private data ********** - +typedef struct +{ + BOOL used; ///< Used. + U16 seqNo; ///< Message sequence number. + U16 retries; ///< Number of retries. + U32 timeStamp; ///< Time stamp. + COMM_BUFFER_T channel; ///< Channel ID. + U32 msgSize; ///< Message size. + U08 msg[ MAX_ACK_MSG_SIZE ]; ///< Message. +} PENDING_ACK_RECORD_T; + +#pragma pack(pop) + +// ********** private data ********** + /// Array of out-going CAN buffers. -const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = -{ - COMM_BUFFER_OUT_CAN_HD_ALARM, - COMM_BUFFER_OUT_CAN_HD_2_DG, - COMM_BUFFER_OUT_CAN_HD_2_UI, - COMM_BUFFER_OUT_CAN_HD_BROADCAST, - COMM_BUFFER_OUT_CAN_PC -}; - +const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = +{ + COMM_BUFFER_OUT_CAN_HD_ALARM, + COMM_BUFFER_OUT_CAN_HD_2_DG, + COMM_BUFFER_OUT_CAN_HD_2_UI, + COMM_BUFFER_OUT_CAN_HD_BROADCAST, + COMM_BUFFER_OUT_CAN_PC +}; + /// Array of in-coming CAN buffers. -const COMM_BUFFER_T MSG_IN_BUFFERS[ NUM_OF_MSG_IN_BUFFERS ] = -{ - COMM_BUFFER_IN_CAN_DG_ALARM, - COMM_BUFFER_IN_CAN_UI_ALARM, - COMM_BUFFER_IN_CAN_DG_2_HD, - COMM_BUFFER_IN_CAN_DG_BROADCAST, - COMM_BUFFER_IN_CAN_UI_2_HD, - COMM_BUFFER_IN_CAN_UI_BROADCAST, - COMM_BUFFER_IN_CAN_PC, -}; - -static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. -static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. -static U32 lastCANPacketSentTimeStamp = 0; ///< Keep time last packet sent on CAN bus so we can timeout on transmission attempt. - -static volatile PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; ///< List of outgoing messages that are awaiting an ACK - +const COMM_BUFFER_T MSG_IN_BUFFERS[ NUM_OF_MSG_IN_BUFFERS ] = +{ + COMM_BUFFER_IN_CAN_DG_ALARM, + COMM_BUFFER_IN_CAN_UI_ALARM, + COMM_BUFFER_IN_CAN_DG_2_HD, + COMM_BUFFER_IN_CAN_DG_BROADCAST, + COMM_BUFFER_IN_CAN_UI_2_HD, + COMM_BUFFER_IN_CAN_UI_BROADCAST, + COMM_BUFFER_IN_CAN_PC, +}; + +static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. +static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. +static U32 lastCANPacketSentTimeStamp = 0; ///< Keep time last packet sent on CAN bus so we can timeout on transmission attempt. + +static volatile PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; ///< List of outgoing messages that are awaiting an ACK + static volatile BOOL hdIsOnlyCANNode = TRUE; ///< Flag indicating whether HD is alone on CAN bus. static U32 canXmitRetryCtr = 0; ///< Counter for CAN transmit retries. -static volatile BOOL dgIsCommunicating = FALSE; ///< Has DG sent a message since last check -static U32 timeOfLastDGCheckIn = 0; ///< Last time DG checked in -static volatile BOOL uiIsCommunicating = FALSE; ///< Has UI sent a message since last check -static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in +static volatile BOOL dgIsCommunicating = FALSE; ///< Has DG sent a message since last check +static U32 timeOfLastDGCheckIn = 0; ///< Last time DG checked in +static volatile BOOL uiIsCommunicating = FALSE; ///< Has UI sent a message since last check +static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in static volatile BOOL uiDidCommunicate = FALSE; ///< Has UI every sent a message -static OVERRIDE_U32_T pendingACKOverride = { 0, 0, 0, 0 }; ///< Pending ACK override data structure. - -// ********** private function prototypes ********** - -static void clearCANXmitBuffers( void ); - -static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); -static U32 transmitNextCANPacket( void ); - -static void processIncomingData( void ); -static S32 parseMessageFromBuffer( U08 *data, U32 len ); -static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); -static void processReceivedMessages( void ); -static void processReceivedMessage( MESSAGE_T *message ); - -static void checkForCommTimeouts( void ); -static void checkTooManyBadMsgCRCs( void ); - -static BOOL matchACKtoPendingACKList( S16 seqNo ); -static void checkPendingACKList( void ); - -/*********************************************************************//** - * @brief - * The initSystemComm function initializes the SystemComm module. - * @details Inputs: none - * @details Outputs: SystemComm module initialized. - * @return none - *************************************************************************/ -void initSystemComm( void ) -{ - U32 i; - +static OVERRIDE_U32_T pendingACKOverride = { 0, 0, 0, 0 }; ///< Pending ACK override data structure. + +// ********** private function prototypes ********** + +static void clearCANXmitBuffers( void ); + +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); +static U32 transmitNextCANPacket( void ); + +static void processIncomingData( void ); +static S32 parseMessageFromBuffer( U08 *data, U32 len ); +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); +static void processReceivedMessages( void ); +static void processReceivedMessage( MESSAGE_T *message ); + +static void checkForCommTimeouts( void ); +static void checkTooManyBadMsgCRCs( void ); + +static BOOL matchACKtoPendingACKList( S16 seqNo ); +static void checkPendingACKList( void ); + +/*********************************************************************//** + * @brief + * The initSystemComm function initializes the SystemComm module. + * @details Inputs: none + * @details Outputs: SystemComm module initialized. + * @return none + *************************************************************************/ +void initSystemComm( void ) +{ + U32 i; + // Initialize bad message CRC time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC, MAX_COMM_CRC_FAILURES, MAX_COMM_CRC_FAILURE_WINDOW_MS ); // Initialize FPGA clock speed error time windowed count initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CLOCK_SPEED_ERROR, MAX_FPGA_CLOCK_SPEED_ERRORS, MAX_FPGA_CLOCK_SPEED_ERROR_WINDOW_MS); - - // Initialize pending ACK list - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - pendingAckList[ i ].used = FALSE; - } -} - -/*********************************************************************//** - * @brief - * The checkInFromDG function checks in the DG with the HD - indicating that - * the DG is communicating. - * @details Inputs: none - * @details Outputs: dgIsCommunicating - * @return none - *************************************************************************/ -void checkInFromDG( void ) -{ - dgIsCommunicating = TRUE; + + // Initialize pending ACK list + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + pendingAckList[ i ].used = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The checkInFromDG function checks in the DG with the HD - indicating that + * the DG is communicating. + * @details Inputs: none + * @details Outputs: dgIsCommunicating + * @return none + *************************************************************************/ +void checkInFromDG( void ) +{ + dgIsCommunicating = TRUE; timeOfLastDGCheckIn = getMSTimerCount(); if ( TRUE == isAlarmActive( ALARM_ID_HD_DG_COMM_TIMEOUT ) ) { clearAlarmCondition( ALARM_ID_HD_DG_COMM_TIMEOUT ); - } -} - -/*********************************************************************//** - * @brief - * The checkInFromUI function checks in the UI with the HD - indicating that - * the UI is communicating. - * @details Inputs: none - * @details Outputs: uiIsCommunicating - * @return none - *************************************************************************/ -void checkInFromUI( void ) -{ + } +} + +/*********************************************************************//** + * @brief + * The checkInFromUI function checks in the UI with the HD - indicating that + * the UI is communicating. + * @details Inputs: none + * @details Outputs: uiIsCommunicating + * @return none + *************************************************************************/ +void checkInFromUI( void ) +{ if ( FALSE == uiDidCommunicate ) { // Start DG check-in timer when UI first communicates timeOfLastDGCheckIn = getMSTimerCount(); } - - uiIsCommunicating = TRUE; - timeOfLastUICheckIn = getMSTimerCount(); - uiDidCommunicate = TRUE; -} - -/*********************************************************************//** - * @brief - * The isDGCommunicating function determines whether the DG is communicating - * with the HD. - * @details Inputs: dgIsCommunicating - * @details Outputs: none - * @return TRUE if DG has checked in since last call, FALSE if not - *************************************************************************/ -BOOL isDGCommunicating( void ) -{ - return dgIsCommunicating; -} - -/*********************************************************************//** - * @brief - * The isUICommunicating function determines whether the UI is communicating - * with the HD. - * @details Inputs: uiIsCommunicating - * @details Outputs: none - * @return TRUE if UI has checked in since last call, FALSE if not - *************************************************************************/ -BOOL isUICommunicating( void ) -{ - BOOL result = uiIsCommunicating; - - uiIsCommunicating = FALSE; - - return result; -} - -/*********************************************************************//** - * @brief - * The uiCommunicated function determines whether the UI has communicated. - * @details Inputs: none - * @details Outputs: none - * @return TRUE if UI has communicated since power up, FALSE if not - *************************************************************************/ -BOOL uiCommunicated( void ) + + uiIsCommunicating = TRUE; + timeOfLastUICheckIn = getMSTimerCount(); + uiDidCommunicate = TRUE; +} + +/*********************************************************************//** + * @brief + * The isDGCommunicating function determines whether the DG is communicating + * with the HD. + * @details Inputs: dgIsCommunicating + * @details Outputs: none + * @return TRUE if DG has checked in since last call, FALSE if not + *************************************************************************/ +BOOL isDGCommunicating( void ) { + return dgIsCommunicating; +} + +/*********************************************************************//** + * @brief + * The isUICommunicating function determines whether the UI is communicating + * with the HD. + * @details Inputs: uiIsCommunicating + * @details Outputs: none + * @return TRUE if UI has checked in since last call, FALSE if not + *************************************************************************/ +BOOL isUICommunicating( void ) +{ + BOOL result = uiIsCommunicating; + + uiIsCommunicating = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief + * The uiCommunicated function determines whether the UI has communicated. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if UI has communicated since power up, FALSE if not + *************************************************************************/ +BOOL uiCommunicated( void ) +{ #ifdef SIMULATE_UI uiDidCommunicate = TRUE; #endif - - return uiDidCommunicate; + + return uiDidCommunicate; } /*********************************************************************//** @@ -257,46 +257,48 @@ BOOL isHDOnlyCANNode( void ) { return hdIsOnlyCANNode; -} - -/*********************************************************************//** - * @brief - * The execSystemCommRx function manages received data from other sub-systems. - * @details Inputs: none - * @details Outputs: Incoming messages parsed and processed. - * @return none - *************************************************************************/ -void execSystemCommRx( void ) +} + +/*********************************************************************//** + * @brief + * The execSystemCommRx function manages received data from other sub-systems. + * @details Inputs: none + * @details Outputs: Incoming messages parsed and processed. + * @return none + *************************************************************************/ +void execSystemCommRx( void ) { - // Parse messages from comm buffers and queue them - processIncomingData(); - - // Process received messages in the queue - processReceivedMessages(); - - // Check for sub-system comm timeouts - checkForCommTimeouts(); - - // Check ACK list for messages that need to be re-sent because they have not been ACK'd + // Parse messages from comm buffers and queue them + processIncomingData(); + + // Process received messages in the queue + processReceivedMessages(); + + // Check for sub-system comm timeouts + checkForCommTimeouts(); + + // Check ACK list for messages that need to be re-sent because they have not been ACK'd checkPendingACKList(); +#ifndef CARTRIDGE_TEST_BUILD if ( TRUE == hasDialinCheckInExpired() ) { // It has been a while since the user logged in but not activity has been received from Dialin so set the tester's status to log out setTesterStatusToLoggedOut(); - } -} - -/*********************************************************************//** - * @brief - * The execSystemCommTx function manages data to be transmitted to other - * sub-systems. - * @details Inputs: none - * @details Outputs: Outgoing messages transmitted. - * @return none - *************************************************************************/ -void execSystemCommTx( void ) -{ + } +#endif +} + +/*********************************************************************//** + * @brief + * The execSystemCommTx function manages data to be transmitted to other + * sub-systems. + * @details Inputs: none + * @details Outputs: Outgoing messages transmitted. + * @return none + *************************************************************************/ +void execSystemCommTx( void ) +{ // Do not transmit if no other nodes on CAN bus if ( FALSE == hdIsOnlyCANNode ) { @@ -330,112 +332,112 @@ } // end - pending xmit timeout? } // end - transmit in progress or not } // end - DG not alone on CAN bus -} - -/*********************************************************************//** - * @brief - * The handleCANMsgInterrupt function handles a CAN message interrupt. - * This may have occurred because a CAN packet transmission has completed - * or because a CAN packet has been received. The appropriate handler is - * called. - * @details Inputs: none - * @details Outputs: message interrupt handled - * @param srcCANBox which CAN message box triggered this interrupt - * @return none - *************************************************************************/ -void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) -{ - // Message interrupt is for a transmit message box? - if ( TRUE == isCANBoxForXmit( srcCANBox ) ) - { +} + +/*********************************************************************//** + * @brief + * The handleCANMsgInterrupt function handles a CAN message interrupt. + * This may have occurred because a CAN packet transmission has completed + * or because a CAN packet has been received. The appropriate handler is + * called. + * @details Inputs: none + * @details Outputs: message interrupt handled + * @param srcCANBox which CAN message box triggered this interrupt + * @return none + *************************************************************************/ +void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) +{ + // Message interrupt is for a transmit message box? + if ( TRUE == isCANBoxForXmit( srcCANBox ) ) + { U32 bytesXmitted; - bytesXmitted = transmitNextCANPacket(); - - // If nothing more to send, signal that transmitter is available - if ( 0 == bytesXmitted ) - { - signalCANXmitsCompleted(); + bytesXmitted = transmitNextCANPacket(); + + // If nothing more to send, signal that transmitter is available + if ( 0 == bytesXmitted ) + { + signalCANXmitsCompleted(); } - } - else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) - { - U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - - // Get CAN packet received on given CAN message box - if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) - { - U32 result = canGetData( canREG1, srcCANBox, data ); - - // If packet retrieved, add to buffer - if ( result != 0 ) - { - // Add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) - addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); - } - } - } - else - { + } + else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + + // Get CAN packet received on given CAN message box + if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) + { + U32 result = canGetData( canREG1, srcCANBox, data ); + + // If packet retrieved, add to buffer + if ( result != 0 ) + { + // Add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) + addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); + } + } + } + else + { // Should not get here - not an active message box - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_BOX, srcCANBox ) - } -} - -/*********************************************************************//** - * @brief - * The isCANBoxForXmit function determines whether a given CAN message box - * is configured for transmit. - * @details Inputs: CAN_OUT_BUFFERS[] - * @details Outputs: none - * @param srcCANBox which CAN message box to check - * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. - *************************************************************************/ -BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) -{ - BOOL result = FALSE; - U32 i; - - for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) - { - if ( CAN_OUT_BUFFERS[ i ] == srcCANBox ) - { - result = TRUE; - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The isCANBoxForRecv function determines whether a given CAN message box - * is configured for receiving. - * @details Inputs: MSG_IN_BUFFERS[] - * @details Outputs: none - * @param srcCANBox which CAN message box to check - * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. - *************************************************************************/ -BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) -{ - BOOL result = FALSE; - U32 i; - - for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) - { - if ( MSG_IN_BUFFERS[ i ] == srcCANBox ) - { - result = TRUE; - break; - } - } - - return result; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_BOX, srcCANBox ) + } } /*********************************************************************//** * @brief + * The isCANBoxForXmit function determines whether a given CAN message box + * is configured for transmit. + * @details Inputs: CAN_OUT_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check + * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( CAN_OUT_BUFFERS[ i ] == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isCANBoxForRecv function determines whether a given CAN message box + * is configured for receiving. + * @details Inputs: MSG_IN_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check + * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) + { + if ( MSG_IN_BUFFERS[ i ] == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief * The clearCANXmitBuffers function clears all CAN transmit buffers. * @details Inputs: CAN_OUT_BUFFERS[] * @details Outputs: CAN transmit buffers cleared. @@ -449,154 +451,154 @@ { clearBuffer( CAN_OUT_BUFFERS[ i ] ); } -} - - -/************************************************************************* -********************** TRANSMIT SUPPORT FUNCTIONS ************************ -*************************************************************************/ - - -/*********************************************************************//** - * @brief - * The findNextHighestPriorityCANPacketToTransmit function gets the next - * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. - * @details Inputs: Output CAN Comm Buffer(s) - * @details Outputs: none - * @return buffer with highest priority CAN packet to transmit, - * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found - *************************************************************************/ -static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) -{ - COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; - U32 i; - - // Search for next priority CAN packet to transmit - for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) - { - if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[ i ] ) >= CAN_MESSAGE_PAYLOAD_SIZE ) - { - result = CAN_OUT_BUFFERS[ i ]; - break; // Found highest priority packet to transmit - we are done - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The transmitNextCANPacket function gets the next 8 byte packet and initiates - * a CAN transmit on the appropriate CAN channel. - * @details Inputs: Output CAN Comm Buffers - * @details Outputs: CAN packet transmit initiated. - * @return number of bytes transmitted - *************************************************************************/ -static U32 transmitNextCANPacket( void ) -{ - U32 result = 0; - COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); - - // If a buffer is found with a packet to transmit, get packet from buffer and transmit it - if ( buffer != COMM_BUFFER_NOT_USED ) - { - U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); - CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned - - // If there is another CAN packet to send, send it - if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) - { - // We are transmitting another packet - signal transmitter is busy - signalCANXmitsInitiated(); - // Remember packet data being transmitted here in case transmission fails and we need to re-send - memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); - lastCANPacketSentChannel = mBox; - lastCANPacketSentTimeStamp = getMSTimerCount(); - if ( 0 != canTransmit( canREG1, mBox, data ) ) - { - result = CAN_MESSAGE_PAYLOAD_SIZE; - } - else - { - signalCANXmitsCompleted(); - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, (U32)mBox ) - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, ((U32)buffer << 16) | dataSize ) - } - } - - return result; -} - - -/************************************************************************* -********************** RECEIVE SUPPORT FUNCTIONS ************************* -*************************************************************************/ - - -/*********************************************************************//** - * @brief - * The processIncomingData function parses out messages from the Input - * Comm Buffers and adds them to the Received Message Queue. - * @details Inputs: none +} + + +/************************************************************************* +********************** TRANSMIT SUPPORT FUNCTIONS ************************ +*************************************************************************/ + + +/*********************************************************************//** + * @brief + * The findNextHighestPriorityCANPacketToTransmit function gets the next + * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. + * @details Inputs: Output CAN Comm Buffer(s) + * @details Outputs: none + * @return buffer with highest priority CAN packet to transmit, + * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found + *************************************************************************/ +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) +{ + COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; + U32 i; + + // Search for next priority CAN packet to transmit + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[ i ] ) >= CAN_MESSAGE_PAYLOAD_SIZE ) + { + result = CAN_OUT_BUFFERS[ i ]; + break; // Found highest priority packet to transmit - we are done + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The transmitNextCANPacket function gets the next 8 byte packet and initiates + * a CAN transmit on the appropriate CAN channel. + * @details Inputs: Output CAN Comm Buffers + * @details Outputs: CAN packet transmit initiated. + * @return number of bytes transmitted + *************************************************************************/ +static U32 transmitNextCANPacket( void ) +{ + U32 result = 0; + COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); + + // If a buffer is found with a packet to transmit, get packet from buffer and transmit it + if ( buffer != COMM_BUFFER_NOT_USED ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); + CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned + + // If there is another CAN packet to send, send it + if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) + { + // We are transmitting another packet - signal transmitter is busy + signalCANXmitsInitiated(); + // Remember packet data being transmitted here in case transmission fails and we need to re-send + memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); + lastCANPacketSentChannel = mBox; + lastCANPacketSentTimeStamp = getMSTimerCount(); + if ( 0 != canTransmit( canREG1, mBox, data ) ) + { + result = CAN_MESSAGE_PAYLOAD_SIZE; + } + else + { + signalCANXmitsCompleted(); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, (U32)mBox ) + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, ((U32)buffer << 16) | dataSize ) + } + } + + return result; +} + + +/************************************************************************* +********************** RECEIVE SUPPORT FUNCTIONS ************************* +*************************************************************************/ + + +/*********************************************************************//** + * @brief + * The processIncomingData function parses out messages from the Input + * Comm Buffers and adds them to the Received Message Queue. + * @details Inputs: none * @details Outputs:hdIsOnlyCANNode, rcvMsg, dgIsCommunicating, - * timeOfLastDGCheckIn, timeOfLastUICheckIn, uiDidCommunicate - * @return none - *************************************************************************/ -static void processIncomingData( void ) -{ - U08 data[ 512 ]; // Message work space - U32 i; - BOOL badCRCDetected = FALSE; - - // Queue any received messages - for ( i = 0; i < NUM_OF_MSG_IN_BUFFERS; i++ ) - { - BOOL messagesInBuffer = TRUE; // Assume true at first to get into while loop - - while ( TRUE == messagesInBuffer ) - { - U32 numOfBytesInBuffer; - - // Assume false so we do not get stuck in loop. Set to true only if we find another complete message in buffer - messagesInBuffer = FALSE; - - // Since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer - consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[ i ] ); - // Do we have enough bytes in buffer for smallest message? - numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[ i ] ); - if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) - { // Peek at minimum of all bytes available or max message size (+1 for sync byte) - U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[ i ], data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); + * timeOfLastDGCheckIn, timeOfLastUICheckIn, uiDidCommunicate + * @return none + *************************************************************************/ +static void processIncomingData( void ) +{ + U08 data[ 512 ]; // Message work space + U32 i; + BOOL badCRCDetected = FALSE; + + // Queue any received messages + for ( i = 0; i < NUM_OF_MSG_IN_BUFFERS; i++ ) + { + BOOL messagesInBuffer = TRUE; // Assume true at first to get into while loop + + while ( TRUE == messagesInBuffer ) + { + U32 numOfBytesInBuffer; + + // Assume false so we do not get stuck in loop. Set to true only if we find another complete message in buffer + messagesInBuffer = FALSE; + + // Since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer + consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[ i ] ); + // Do we have enough bytes in buffer for smallest message? + numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[ i ] ); + if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) + { // Peek at minimum of all bytes available or max message size (+1 for sync byte) + U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[ i ], data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); S32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); hdIsOnlyCANNode = FALSE; // Since we are getting a message, this indicates we are not the only node on the CAN bus - canXmitRetryCtr = 0; - - if ( msgSize > 0 ) // Valid, complete message found? - { - MESSAGE_WRAPPER_T rcvMsg; - U08 *dataPtr = data+1; // Skip over sync byte - - // Consume message (+sync byte) - msgSize = getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, msgSize + 1 ); - // Convert received message data to a message and add to message queue - messagesInBuffer = TRUE; // Keep processing this buffer - // Blank the new message record - blankMessageInWrapper( &rcvMsg ); - // Copy message header portion of message data to the new message - memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof( MESSAGE_HEADER_T ) ); - dataPtr += sizeof( MESSAGE_HEADER_T ); - // Copy message payload portion of message data to the new message - memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); - dataPtr += rcvMsg.msg.hdr.payloadLen; - // Copy CRC portion of message data to the new message - rcvMsg.crc = *dataPtr; - // Add new message to queue for later processing + canXmitRetryCtr = 0; + + if ( msgSize > 0 ) // Valid, complete message found? + { + MESSAGE_WRAPPER_T rcvMsg; + U08 *dataPtr = data+1; // Skip over sync byte + + // Consume message (+sync byte) + msgSize = getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, msgSize + 1 ); + // Convert received message data to a message and add to message queue + messagesInBuffer = TRUE; // Keep processing this buffer + // Blank the new message record + blankMessageInWrapper( &rcvMsg ); + // Copy message header portion of message data to the new message + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof( MESSAGE_HEADER_T ) ); + dataPtr += sizeof( MESSAGE_HEADER_T ); + // Copy message payload portion of message data to the new message + memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); + dataPtr += rcvMsg.msg.hdr.payloadLen; + // Copy CRC portion of message data to the new message + rcvMsg.crc = *dataPtr; + // Add new message to queue for later processing addToMsgQueue( MSG_Q_IN, &rcvMsg ); // If message from DG broadcast channel, update DG comm status if ( COMM_BUFFER_IN_CAN_DG_BROADCAST == MSG_IN_BUFFERS[ i ] ) @@ -609,180 +611,180 @@ { timeOfLastUICheckIn = getMSTimerCount(); uiDidCommunicate = TRUE; - } - } - else if ( -1 == msgSize ) // Candidate message with bad CRC found? - { - badCRCDetected = TRUE; - getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // Consume sync byte so we can re-sync - messagesInBuffer = TRUE; // Keep processing this buffer - } // Looks like there is a complete message in the comm buffer - } // Enough data left in comm buffer to possibly be a complete message - } // While loop to get all complete messages for each comm buffer - } // For loop to check all comm buffers for messages - - // If any bad CRCs detected, see if too many - if ( TRUE == badCRCDetected ) - { - checkTooManyBadMsgCRCs(); - } -} - -/*********************************************************************//** - * @brief - * The consumeBufferPaddingBeforeSync function removes any bytes in a given - * buffer that lie before a sync byte. - * @details Inputs: none - * @details Outputs: Any padding at front of buffer is consumed. - * @param buffer the comm buffer to process - * @return none - *************************************************************************/ -static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) -{ - U08 data; - U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); - - // Consume bytes out of buffer 1 at a time until we find the sync byte or it is empty - while ( numOfBytesInBuffer > 0 ) - { - peekFromCommBuffer( buffer, &data, 1 ); - if ( MESSAGE_SYNC_BYTE == data ) - { - break; // We found a sync - we are done - } - else // Not a sync byte, so consume it - { - getFromCommBuffer( buffer, &data, 1 ); - numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); - } - } -} - -/*********************************************************************//** - * @brief - * The parseMessageFromBuffer function looks for a complete message in a - * given buffer. If a message is found, its size is returned. - * @details Inputs: none - * @details Outputs: none - * @param data pointer to byte array to search for a message - * @param len number of bytes in the data to search - * @return size of message if found, zero if no complete message found, - * -1 if message found but CRC fails. - *************************************************************************/ -static S32 parseMessageFromBuffer( U08 *data, U32 len ) -{ - U32 i; - U32 payloadSize; - U32 msgSize; - S32 result = 0; - - for ( i = 0; i < len; i++ ) - { - // Find sync byte - if ( MESSAGE_SYNC_BYTE == data[ i ] ) - { - U32 pos = i + 1; // Skip past sync byte implemented - U32 remSize = len - pos; - - // If a minimum sized msg would fit in remaining, continue - if ( remSize >= MESSAGE_OVERHEAD_SIZE ) - { - payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; - msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; - // We now know the size of the message - we can now know if full message is contained in buffer - if ( msgSize <= remSize ) - { // Check CRC to make sure it is a valid message - if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) - { - result = msgSize; // We found a complete, valid message of this size - } - else // CRC failed - { - result = -1; // We found a complete, invalid message - } - } - } - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The processReceivedMessages function processes any messages in the - * received message queues. - * @details Inputs: Received Message Queues - * @details Outputs: Message(s) processed. - * @return none - *************************************************************************/ -static void processReceivedMessages( void ) -{ - BOOL isThereMsgRcvd = TRUE; // Assume TRUE at first to get into while loop - MESSAGE_WRAPPER_T message; + } + } + else if ( -1 == msgSize ) // Candidate message with bad CRC found? + { + badCRCDetected = TRUE; + getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // Consume sync byte so we can re-sync + messagesInBuffer = TRUE; // Keep processing this buffer + } // Looks like there is a complete message in the comm buffer + } // Enough data left in comm buffer to possibly be a complete message + } // While loop to get all complete messages for each comm buffer + } // For loop to check all comm buffers for messages - while ( TRUE == isThereMsgRcvd ) - { - // See if any messages received - isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); - if ( TRUE == isThereMsgRcvd ) - { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure - if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) - { - // If ACK, mark pending message ACK'd - if ( MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK == message.msg.hdr.msgID ) - { - matchACKtoPendingACKList( message.msg.hdr.seqNo ); - } - else - { - // If received message requires ACK, queue one up - if ( message.msg.hdr.seqNo < 0 ) - { - sendACKMsg( &message.msg ); - } - // Process the received message - processReceivedMessage( &message.msg ); - } - } - else // CRC failed - { - checkTooManyBadMsgCRCs(); - } - } - } -} - -/*********************************************************************//** - * @brief - * The checkForCommTimeouts function checks for sub-system communication - * timeout errors. - * @details Inputs: timeOfLastDGCheckIn, timeOfLastUICheckIn - * @details Outputs: possibly a comm t/o alarm - * @return none - *************************************************************************/ -static void checkForCommTimeouts( void ) -{ - if ( TRUE == uiDidCommunicate ) + // If any bad CRCs detected, see if too many + if ( TRUE == badCRCDetected ) { + checkTooManyBadMsgCRCs(); + } +} + +/*********************************************************************//** + * @brief + * The consumeBufferPaddingBeforeSync function removes any bytes in a given + * buffer that lie before a sync byte. + * @details Inputs: none + * @details Outputs: Any padding at front of buffer is consumed. + * @param buffer the comm buffer to process + * @return none + *************************************************************************/ +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) +{ + U08 data; + U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + + // Consume bytes out of buffer 1 at a time until we find the sync byte or it is empty + while ( numOfBytesInBuffer > 0 ) + { + peekFromCommBuffer( buffer, &data, 1 ); + if ( MESSAGE_SYNC_BYTE == data ) + { + break; // We found a sync - we are done + } + else // Not a sync byte, so consume it + { + getFromCommBuffer( buffer, &data, 1 ); + numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + } + } +} + +/*********************************************************************//** + * @brief + * The parseMessageFromBuffer function looks for a complete message in a + * given buffer. If a message is found, its size is returned. + * @details Inputs: none + * @details Outputs: none + * @param data pointer to byte array to search for a message + * @param len number of bytes in the data to search + * @return size of message if found, zero if no complete message found, + * -1 if message found but CRC fails. + *************************************************************************/ +static S32 parseMessageFromBuffer( U08 *data, U32 len ) +{ + U32 i; + U32 payloadSize; + U32 msgSize; + S32 result = 0; + + for ( i = 0; i < len; i++ ) + { + // Find sync byte + if ( MESSAGE_SYNC_BYTE == data[ i ] ) + { + U32 pos = i + 1; // Skip past sync byte implemented + U32 remSize = len - pos; + + // If a minimum sized msg would fit in remaining, continue + if ( remSize >= MESSAGE_OVERHEAD_SIZE ) + { + payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; + msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; + // We now know the size of the message - we can now know if full message is contained in buffer + if ( msgSize <= remSize ) + { // Check CRC to make sure it is a valid message + if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) + { + result = msgSize; // We found a complete, valid message of this size + } + else // CRC failed + { + result = -1; // We found a complete, invalid message + } + } + } + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The processReceivedMessages function processes any messages in the + * received message queues. + * @details Inputs: Received Message Queues + * @details Outputs: Message(s) processed. + * @return none + *************************************************************************/ +static void processReceivedMessages( void ) +{ + BOOL isThereMsgRcvd = TRUE; // Assume TRUE at first to get into while loop + MESSAGE_WRAPPER_T message; + + while ( TRUE == isThereMsgRcvd ) + { + // See if any messages received + isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); + if ( TRUE == isThereMsgRcvd ) + { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure + if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) + { + // If ACK, mark pending message ACK'd + if ( MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK == message.msg.hdr.msgID ) + { + matchACKtoPendingACKList( message.msg.hdr.seqNo ); + } + else + { + // If received message requires ACK, queue one up + if ( message.msg.hdr.seqNo < 0 ) + { + sendACKMsg( &message.msg ); + } + // Process the received message + processReceivedMessage( &message.msg ); + } + } + else // CRC failed + { + checkTooManyBadMsgCRCs(); + } + } + } +} + +/*********************************************************************//** + * @brief + * The checkForCommTimeouts function checks for sub-system communication + * timeout errors. + * @details Inputs: timeOfLastDGCheckIn, timeOfLastUICheckIn + * @details Outputs: possibly a comm t/o alarm + * @return none + *************************************************************************/ +static void checkForCommTimeouts( void ) +{ + if ( TRUE == uiDidCommunicate ) + { HD_OP_MODE_T opMode = getCurrentOperationMode(); U32 uiTO_MS = UI_COMM_TIMEOUT_IN_MS; // in service mode, allow up to 2 minutes for UI to check-in (for lock-down) if ( MODE_SERV == opMode ) { uiTO_MS = UI_COMM_SERVICE_MODE_TIMEOUT_IN_MS; - } - if ( TRUE == didTimeout( timeOfLastUICheckIn, uiTO_MS ) ) + } + if ( TRUE == didTimeout( timeOfLastUICheckIn, uiTO_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_COMM_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif - { + { activateAlarmNoData( ALARM_ID_HD_UI_COMM_TIMEOUT ); } - } + } if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) { @@ -802,89 +804,89 @@ #endif } } -} - -/*********************************************************************//** - * @brief - * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs - * within a set period of time. Assumed function is being called when a new - * bad CRC is detected so a new bad CRC will be added to the list. - * @details Inputs: badCRCTimeStamps[], badCRCListIdx, badCRCListCount - * @details Outputs: possibly a "too many bad CRCs" alarm - * @return none - *************************************************************************/ -static void checkTooManyBadMsgCRCs( void ) -{ +} + +/*********************************************************************//** + * @brief + * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs + * within a set period of time. Assumed function is being called when a new + * bad CRC is detected so a new bad CRC will be added to the list. + * @details Inputs: badCRCTimeStamps[], badCRCListIdx, badCRCListCount + * @details Outputs: possibly a "too many bad CRCs" alarm + * @return none + *************************************************************************/ +static void checkTooManyBadMsgCRCs( void ) +{ if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); } -} - -/*********************************************************************//** - * @brief - * The addMsgToPendingACKList function adds a given message to the pending - * ACK list. Messages in this list will require receipt of an ACK message - * for this particular message within a limited time. - * @details Inputs: pendingAckList[] - * @details Outputs: pendingAckList[] - * @param msg pointer to msg within the message data - * @param msgData pointer to message data to add to pending ACK list - * @param len number of bytes of message data - * @return TRUE if message added successfully, FALSE if not - *************************************************************************/ -BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) -{ - BOOL result = FALSE; - U32 i; - - // Find first open slot in pending ACK list and add given msg data to it - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - _disable_IRQ(); // Slot selection needs interrupt protection - if ( FALSE == pendingAckList[ i ].used ) - { - S16 seqNo = msg->hdr.seqNo * -1; // Remove ACK bit from seq # - - pendingAckList[ i ].used = TRUE; - _enable_IRQ(); - pendingAckList[ i ].seqNo = seqNo; - pendingAckList[ i ].channel = channel; - pendingAckList[ i ].timeStamp = getMSTimerCount(); - pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; - pendingAckList[ i ].msgSize = len; - memcpy( (U08*)pendingAckList[ i ].msg, msgData, len ); - result = TRUE; - break; - } - else - { - _enable_IRQ(); - } +} + +/*********************************************************************//** + * @brief + * The addMsgToPendingACKList function adds a given message to the pending + * ACK list. Messages in this list will require receipt of an ACK message + * for this particular message within a limited time. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param msg pointer to msg within the message data + * @param msgData pointer to message data to add to pending ACK list + * @param len number of bytes of message data + * @return TRUE if message added successfully, FALSE if not + *************************************************************************/ +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) +{ + BOOL result = FALSE; + U32 i; + + // Find first open slot in pending ACK list and add given msg data to it + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + _disable_IRQ(); // Slot selection needs interrupt protection + if ( FALSE == pendingAckList[ i ].used ) + { + S16 seqNo = msg->hdr.seqNo * -1; // Remove ACK bit from seq # + + pendingAckList[ i ].used = TRUE; + _enable_IRQ(); + pendingAckList[ i ].seqNo = seqNo; + pendingAckList[ i ].channel = channel; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; + pendingAckList[ i ].msgSize = len; + memcpy( (U08*)pendingAckList[ i ].msg, msgData, len ); + result = TRUE; + break; + } + else + { + _enable_IRQ(); + } } - return result; -} - -/*********************************************************************//** - * @brief - * The matchACKtoPendingACKList function searches the pending ACK list to - * see if the sequence # from a received ACK msg matches any. If found, - * the list entry is removed. - * @details Inputs: pendingAckList[] - * @details Outputs: pendingAckList[] - * @param seqNo sequence # to match to an entry in the list - * @return TRUE if a match was found, FALSE if not - *************************************************************************/ -static BOOL matchACKtoPendingACKList( S16 seqNo ) -{ - BOOL result = FALSE; + return result; +} + +/*********************************************************************//** + * @brief + * The matchACKtoPendingACKList function searches the pending ACK list to + * see if the sequence # from a received ACK msg matches any. If found, + * the list entry is removed. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param seqNo sequence # to match to an entry in the list + * @return TRUE if a match was found, FALSE if not + *************************************************************************/ +static BOOL matchACKtoPendingACKList( S16 seqNo ) +{ + BOOL result = FALSE; U32 i; - - // Find match - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) + + // Find match + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) { result = TRUE; // Remove message pending ACK from list @@ -893,42 +895,42 @@ { pendingAckList[ i ].used = FALSE; } - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The checkPendingACKList function searches the pending ACK list to - * see if any have expired. Any such messages will be queued for retransmission - * and if max retries reached a fault is triggered. - * @details Inputs: pendingAckList[] - * @details Outputs: pendingAckList[] - * @return none - *************************************************************************/ -static void checkPendingACKList( void ) -{ - U32 i; - - // Find expired messages pending ACK - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { // Pending ACK expired? - if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) - { // If retries left, reset and resend pending message - if ( pendingAckList[ i ].retries > 0 ) - { // Re-queue message for transmit - pendingAckList[ i ].retries--; - pendingAckList[ i ].timeStamp = getMSTimerCount(); - addToCommBuffer( pendingAckList[ i ].channel, (U08*)pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The checkPendingACKList function searches the pending ACK list to + * see if any have expired. Any such messages will be queued for retransmission + * and if max retries reached a fault is triggered. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @return none + *************************************************************************/ +static void checkPendingACKList( void ) +{ + U32 i; + + // Find expired messages pending ACK + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { // Pending ACK expired? + if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) + { // If retries left, reset and resend pending message + if ( pendingAckList[ i ].retries > 0 ) + { // Re-queue message for transmit + pendingAckList[ i ].retries--; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + addToCommBuffer( pendingAckList[ i ].channel, (U08*)pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); } - // If no retries left, alarm - else - { - U16 msgID; - + // If no retries left, alarm + else + { + U16 msgID; + memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); if ( pendingAckList[ i ].channel != COMM_BUFFER_OUT_CAN_HD_2_DG ) @@ -940,30 +942,30 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_CAN_MESSAGE_NOT_ACKED_BY_DG, (U32)msgID ); } pendingAckList[ i ].used = FALSE; // Take pending message off of list - } - } - } -} - -/*********************************************************************//** - * @brief - * The processReceivedMessage function processes a given message. - * @details Inputs: none - * @details Outputs: message processed - * @param message pointer to message to process - * @return none - *************************************************************************/ -static void processReceivedMessage( MESSAGE_T *message ) -{ - U16 msgID = message->hdr.msgID; - - // Handle any messages from other sub-systems - switch ( msgID ) - { - case MSG_ID_OFF_BUTTON_PRESS_REQUEST: - handleOffButtonConfirmMsgFromUI( message ); - break; - + } + } + } +} + +/*********************************************************************//** + * @brief + * The processReceivedMessage function processes a given message. + * @details Inputs: none + * @details Outputs: message processed + * @param message pointer to message to process + * @return none + *************************************************************************/ +static void processReceivedMessage( MESSAGE_T *message ) +{ + U16 msgID = message->hdr.msgID; + + // Handle any messages from other sub-systems + switch ( msgID ) + { + case MSG_ID_OFF_BUTTON_PRESS_REQUEST: + handleOffButtonConfirmMsgFromUI( message ); + break; + case MSG_ID_ALARM_TRIGGERED: handleAlarmTriggered( message ); break; @@ -974,42 +976,42 @@ case MSG_ID_UI_ALARM_USER_ACTION_REQUEST: handleAlarmUserAction( message ); - break; - - case MSG_ID_UI_CHECK_IN: - handleUICheckIn( message ); - break; - - case MSG_ID_LOAD_CELL_READINGS_DATA: - handleLoadCellReadingsFromDG( message ); - break; - - case MSG_ID_USER_UF_PAUSE_RESUME_REQUEST: - handleUFPauseResumeRequest( message ); - break; - - case MSG_ID_USER_UF_SETTINGS_CHANGE_REQUEST: - handleChangeUFSettingsRequest( message ); break; + case MSG_ID_UI_CHECK_IN: + handleUICheckIn( message ); + break; + + case MSG_ID_LOAD_CELL_READINGS_DATA: + handleLoadCellReadingsFromDG( message ); + break; + + case MSG_ID_USER_UF_PAUSE_RESUME_REQUEST: + handleUFPauseResumeRequest( message ); + break; + + case MSG_ID_USER_UF_SETTINGS_CHANGE_REQUEST: + handleChangeUFSettingsRequest( message ); + break; + case MSG_ID_USER_SALINE_BOLUS_REQUEST: handleSalineBolusRequest( message ); - break; - - case MSG_ID_USER_CONFIRM_UF_SETTINGS_CHANGE_REQUEST: - handleChangeUFSettingsConfirmation( message ); - break; - - case MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST: - handleChangeTreatmentDurationRequest( message ); - break; - - case MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST: - handleChangeBloodDialysateRateChangeRequest( message ); - break; - - case MSG_ID_FW_VERSIONS_REQUEST: - handleFWVersionRequest( message ); + break; + + case MSG_ID_USER_CONFIRM_UF_SETTINGS_CHANGE_REQUEST: + handleChangeUFSettingsConfirmation( message ); + break; + + case MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST: + handleChangeTreatmentDurationRequest( message ); + break; + + case MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST: + handleChangeBloodDialysateRateChangeRequest( message ); + break; + + case MSG_ID_FW_VERSIONS_REQUEST: + handleFWVersionRequest( message ); handleHDSerialNumberRequest(); break; @@ -1019,24 +1021,24 @@ case MSG_ID_DG_HEATERS_DATA: handleDGHeatersData( message ); - break; - - case MSG_ID_DG_TEMPERATURE_DATA: - handleDGTemperatureData( message ); - break; - + break; + + case MSG_ID_DG_TEMPERATURE_DATA: + handleDGTemperatureData( message ); + break; + case MSG_ID_DG_FLOW_SENSORS_DATA: handleDialysateFlowData( message ); - break; - - case MSG_ID_DG_OP_MODE_DATA: - handleDGOpMode( message ); - break; - - case MSG_ID_DG_RESERVOIRS_DATA: - handleDGReservoirData( message ); - break; - + break; + + case MSG_ID_DG_OP_MODE_DATA: + handleDGOpMode( message ); + break; + + case MSG_ID_DG_RESERVOIRS_DATA: + handleDGReservoirData( message ); + break; + case MSG_ID_USER_ALARM_SILENCE_REQUEST: handleUIAlarmSilenceRequest( message ); break; @@ -1222,164 +1224,164 @@ handleTesterLogInRequest( message ); break; - default: - // Un-recognized or un-handled message ID received - ignore + default: + // Un-recognized or un-handled message ID received - ignore break; - } - - // Handle any test messages if tester has logged in successfully - if ( ( msgID > MSG_ID_FIRST_TESTER_MESSAGE ) && ( TRUE == isTestingActivated() ) ) - { - switch ( msgID ) - { - case MSG_ID_OFF_BUTTON_STATE_OVERRIDE: - handleTestOffButtonStateOverrideRequest( message ); - break; - - case MSG_ID_STOP_BUTTON_STATE_OVERRIDE: - handleTestStopButtonStateOverrideRequest( message ); - break; - - case MSG_ID_ALARM_LAMP_PATTERN_OVERRIDE: - handleTestAlarmLampPatternOverrideRequest( message ); - break; - - case MSG_ID_WATCHDOG_TASK_CHECKIN_OVERRIDE: - handleTestWatchdogCheckInStateOverrideRequest( message ); - break; - - case MSG_ID_ALARM_STATE_OVERRIDE: - handleTestAlarmStateOverrideRequest( message ); - break; - - case MSG_ID_ALARM_TIME_OVERRIDE: - handleTestAlarmTimeOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_FLOW_SET_PT_OVERRIDE: - handleTestBloodFlowSetPointOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE: - handleTestBloodFlowMeasuredOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE: - handleTestBloodPumpMCMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_PUMP_MC_MEAS_CURR_OVERRIDE: - handleTestBloodPumpMCMeasuredCurrentOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE: - handleTestBloodFlowBroadcastIntervalOverrideRequest( message ); + } + + // Handle any test messages if tester has logged in successfully + if ( ( msgID > MSG_ID_FIRST_TESTER_MESSAGE ) && ( TRUE == isTestingActivated() ) ) + { + switch ( msgID ) + { + case MSG_ID_OFF_BUTTON_STATE_OVERRIDE: + handleTestOffButtonStateOverrideRequest( message ); break; + case MSG_ID_STOP_BUTTON_STATE_OVERRIDE: + handleTestStopButtonStateOverrideRequest( message ); + break; + + case MSG_ID_ALARM_LAMP_PATTERN_OVERRIDE: + handleTestAlarmLampPatternOverrideRequest( message ); + break; + + case MSG_ID_WATCHDOG_TASK_CHECKIN_OVERRIDE: + handleTestWatchdogCheckInStateOverrideRequest( message ); + break; + + case MSG_ID_ALARM_STATE_OVERRIDE: + handleTestAlarmStateOverrideRequest( message ); + break; + + case MSG_ID_ALARM_TIME_OVERRIDE: + handleTestAlarmTimeOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_SET_PT_OVERRIDE: + handleTestBloodFlowSetPointOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE: + handleTestBloodFlowMeasuredOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestBloodPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestBloodPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestBloodFlowBroadcastIntervalOverrideRequest( message ); + break; + case MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: handleTestTreatmentTimeRemainingOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE: - handleTestBloodPumpMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_BLOOD_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: - handleTestBloodPumpRotorMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_FLOW_SET_PT_OVERRIDE: - handleTestDialInFlowSetPointOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE: - handleTestDialInFlowMeasuredOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE: - handleTestDialInPumpMCMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_PUMP_MC_MEAS_CURR_OVERRIDE: - handleTestDialInPumpMCMeasuredCurrentOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_FLOW_SEND_INTERVAL_OVERRIDE: - handleTestDialInFlowBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE: - handleTestDialInPumpMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_IN_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: - handleTestDialInPumpRotorMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_PRESSURE_ARTERIAL_OVERRIDE: - handleTestArterialPressureOverrideRequest( message ); - break; - - case MSG_ID_PRESSURE_VENOUS_OVERRIDE: - handleTestVenousPressureOverrideRequest( message ); - break; - - case MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE: - handleTestBloodPumpOcclusionOverrideRequest( message ); break; + case MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE: + handleTestBloodPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestBloodPumpRotorMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_SET_PT_OVERRIDE: + handleTestDialInFlowSetPointOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE: + handleTestDialInFlowMeasuredOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestDialInPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestDialInPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestDialInFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE: + handleTestDialInPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestDialInPumpRotorMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_ARTERIAL_OVERRIDE: + handleTestArterialPressureOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_VENOUS_OVERRIDE: + handleTestVenousPressureOverrideRequest( message ); + break; + + case MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE: + handleTestBloodPumpOcclusionOverrideRequest( message ); + break; + case MSG_ID_HD_PARTIAL_OCCLUSION_BLOOD_PUMP_OVERRIDE: handleTestFilteredBloodPumpOcclusionOverrideRequest( message ); break; case MSG_ID_HD_PARTIAL_OCCL_BLOOD_PUMP_BASELINE_OVERRIDE: handleTestBloodPumpOcclusionBaselineOverrideRequest( message ); - break; - - case MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE: - handleTestPresOcclBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_SET_RTC_DATE_TIME: - handleSetRTCTimestamp( message ); - break; - - case MSG_ID_DIAL_OUT_FLOW_SEND_INTERVAL_OVERRIDE: - handleTestDialOutFlowBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_UF_REF_VOLUME_OVERRIDE: - handleTestDialOutUFReferenceVolumeOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_UF_MEAS_VOLUME_OVERRIDE: - handleTestDialOutUFMeasuredVolumeOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_SPEED_OVERRIDE: - handleTestDialOutPumpMCMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_CURR_OVERRIDE: - handleTestDialOutPumpMCMeasuredCurrentOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_PUMP_MEAS_SPEED_OVERRIDE: - handleTestDialOutPumpMeasuredSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: - handleTestDialOutPumpMeasuredRotorSpeedOverrideRequest( message ); - break; - - case MSG_ID_DIAL_OUT_LOAD_CELL_WEIGHT_OVERRIDE: - handleTestDialOutLoadCellWeightOverrideRequest( message ); - break; - - case MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE: - handleTestHDSafetyShutdownOverrideRequest( message ); - break; - + break; + + case MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE: + handleTestPresOcclBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_SET_RTC_DATE_TIME: + handleSetRTCTimestamp( message ); + break; + + case MSG_ID_DIAL_OUT_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestDialOutFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_UF_REF_VOLUME_OVERRIDE: + handleTestDialOutUFReferenceVolumeOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_UF_MEAS_VOLUME_OVERRIDE: + handleTestDialOutUFMeasuredVolumeOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestDialOutPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestDialOutPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MEAS_SPEED_OVERRIDE: + handleTestDialOutPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestDialOutPumpMeasuredRotorSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_LOAD_CELL_WEIGHT_OVERRIDE: + handleTestDialOutLoadCellWeightOverrideRequest( message ); + break; + + case MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE: + handleTestHDSafetyShutdownOverrideRequest( message ); + break; + case MSG_ID_HD_ACCEL_OVERRIDE: handleTestHDAccelOverrideRequest( message ); break; @@ -1844,13 +1846,25 @@ handleSetHDInstitutionalRecord( message ); break; + case MSG_ID_HD_BLOOD_LEAK_EMB_MODE_INFO_VALUES_OVERRIDE: + handleBloodLeakEmbModeInfoValuesOverride( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_INTENSITY_MVG_AVERAGE_OVERRIDE: + handleBloodLeakIntensityMovingAverageOverride( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_ZEROING_INTERVAL_IN_MINS_OVERRIDE: + handleBloodLeakZeroingIntervalInMinutesOverride( message ); + break; + // The default cannot be reached in VectorCAST since the cases are run in a for loop - default: - // Unrecognized message ID received - ignore + default: + // Unrecognized message ID received - ignore break; - } - } -} + } + } +} /************************************************************************* Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -refead43ba16292aa173f72ebfa2b73aebfd2a587 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision efead43ba16292aa173f72ebfa2b73aebfd2a587) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision fb714597ad515d3774d69b94808f065788504724) @@ -46,7 +46,7 @@ #include "Valves.h" #include "WatchdogMgmt.h" #include "HDDefs.h" -#include "TaskPriority.h" +#include "TaskPriority.h" /** * @addtogroup SystemCommMessages @@ -96,7 +96,11 @@ // ********** private data ********** +#ifndef CARTRIDGE_TEST_BUILD static BOOL testerLoggedIn = FALSE; ///< Flag indicates whether an external tester (connected PC) has sent a valid login message. +#else +static BOOL testerLoggedIn = TRUE; ///< Flag indicates whether an external tester (connected PC) has sent a valid login message. +#endif static volatile U16 nextSeqNo = 1; ///< Value of sequence number to use for next transmitted message. /// List of message IDs that are requested not to be transmitted. @@ -8895,4 +8899,100 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); } +/*********************************************************************//** +* @brief +* The handleBloodLeakEmbModeInfoValuesOverride function handles the blood +* leak embedded mode info commands override. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleBloodLeakEmbModeInfoValuesOverride( MESSAGE_T* message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodLeakEmbeddedModeInfoOverride( payload.index, payload.state.u32 ); + } + else + { + result = testResetBloodLeakEmbeddedModeInfoOverride( payload.index ); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakIntensityMovingAverageOverride function handles a + * request to override the blood leak intensity moving average. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleBloodLeakIntensityMovingAverageOverride( MESSAGE_T* message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodLeakIntensityMovingAverageOverride( payload.state.f32 ); + } + else + { + result = testResetBloodLeakIntensityMovingAverageOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleBloodLeakZeroingIntervalInMinutesOverride function handles a + * request to override the blood leak zeroing interval in minutes. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleBloodLeakZeroingIntervalInMinutesOverride( MESSAGE_T* message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodLeakZeroingIntervalInMinsOverride( payload.index, payload.state.u32 ); + } + else + { + result = testResetBloodLeakZeroingIntervalInMinsOverride( payload.index ); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -ra1a0187daedaf2c12e6f9eccfbf9e423d952e029 -rfb714597ad515d3774d69b94808f065788504724 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision a1a0187daedaf2c12e6f9eccfbf9e423d952e029) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision fb714597ad515d3774d69b94808f065788504724) @@ -14,11 +14,11 @@ * @date (original) 05-Nov-2019 * ***************************************************************************/ - -#ifndef __SYSTEM_COMM_MESSAGES_H__ -#define __SYSTEM_COMM_MESSAGES_H__ -#include "AirPump.h" +#ifndef __SYSTEM_COMM_MESSAGES_H__ +#define __SYSTEM_COMM_MESSAGES_H__ + +#include "AirPump.h" #include "AirTrap.h" #include "BloodFlow.h" #include "BloodLeak.h" @@ -27,13 +27,13 @@ #include "CommBuffers.h" #include "DGInterface.h" #include "DialInFlow.h" -#include "DialOutFlow.h" +#include "DialOutFlow.h" #include "Dialysis.h" -#include "Fans.h" +#include "Fans.h" #include "FluidLeak.h" #include "HDCommon.h" #include "MessageSupport.h" -#include "ModeInitPOST.h" +#include "ModeInitPOST.h" #include "ModePostTreat.h" #include "ModePreTreat.h" #include "ModeStandby.h" @@ -49,7 +49,7 @@ #include "Temperatures.h" #include "Valves.h" #include "Voltages.h" - + /** * @defgroup SystemCommMessages SystemCommMessages * @brief The system communication messages module provides helper functions @@ -62,7 +62,7 @@ // ********** public definitions ********** #define ACK_REQUIRED TRUE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. -#define ACK_NOT_REQUIRED FALSE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. +#define ACK_NOT_REQUIRED FALSE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. #pragma pack(push, 1) /// Payload record structure for ACK response. @@ -136,22 +136,22 @@ U32 minDialRate; ///< Minimum dialysate flow rate (in mL/min) U32 maxDialRate; ///< Maximum dialysate flow rate (in mL/min) } TREATMENT_PARAM_BROADCAST_PAYLOAD_T; - -// ********** public function prototypes ********** -// Serialize message +// ********** public function prototypes ********** + +// Serialize message U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); -// ACK MSG +// ACK MSG BOOL sendACKMsg( MESSAGE_T *message ); -// MSG_ID_DG_CHECK_IN -void handleDGCheckIn( MESSAGE_T *message ); - -// MSG_ID_UI_CHECK_IN -void handleUICheckIn( MESSAGE_T *message ); - -// MSG_ID_REQUEST_FW_VERSIONS +// MSG_ID_DG_CHECK_IN +void handleDGCheckIn( MESSAGE_T *message ); + +// MSG_ID_UI_CHECK_IN +void handleUICheckIn( MESSAGE_T *message ); + +// MSG_ID_REQUEST_FW_VERSIONS void handleFWVersionRequest( MESSAGE_T *message ); // MSG_ID_REQUEST_FW_VERSIONS @@ -170,8 +170,8 @@ void handleHDServiceScheduleRequest( MESSAGE_T *message ); // MSG_ID_REQUEST_HD_USAGE_INFO -void handleHDUsageInfoRequest( MESSAGE_T *message ); - +void handleHDUsageInfoRequest( MESSAGE_T *message ); + // MSG_ID_DG_VERSION void handleDGVersionResponse( MESSAGE_T *message ); @@ -181,16 +181,16 @@ // MSG_ID_HD_EVENT BOOL sendEvent( HD_EVENT_ID_T event, EVENT_DATA_T dat1, EVENT_DATA_T dat2 ); -// MSG_ID_OFF_BUTTON_PRESS -BOOL sendOffButtonMsgToUI( U08 cmd ); -void handleOffButtonConfirmMsgFromUI( MESSAGE_T *message ); +// MSG_ID_OFF_BUTTON_PRESS +BOOL sendOffButtonMsgToUI( U08 cmd ); +void handleOffButtonConfirmMsgFromUI( MESSAGE_T *message ); // MSG_ID_ALARM_TRIGGERED void handleAlarmTriggered( MESSAGE_T *message ); // MSG_ID_ALARM_CLEARED void handleAlarmCleared( MESSAGE_T *message ); - + // MSG_ID_USER_REQUEST_ALARM_SILENCE void handleUIAlarmSilenceRequest( MESSAGE_T *message ); @@ -212,19 +212,19 @@ // MSG_ID_UI_POST_FINAL_TEST_RESULT void handleUIPOSTFinalResult( MESSAGE_T *message ); -// MSG_ID_LOAD_CELL_READINGS +// MSG_ID_LOAD_CELL_READINGS void handleLoadCellReadingsFromDG( MESSAGE_T *message ); // MSG_ID_DG_HEATERS_DATA -void handleDGHeatersData( MESSAGE_T *message ); - -// MSG_ID_DG_TEMPERATURE_DATA: -void handleDGTemperatureData( MESSAGE_T *message ); - +void handleDGHeatersData( MESSAGE_T *message ); + +// MSG_ID_DG_TEMPERATURE_DATA: +void handleDGTemperatureData( MESSAGE_T *message ); + // MSG_ID_DG_FLOW_SENSORS_DATA -void handleDialysateFlowData( MESSAGE_T *message ); - -// MSG_ID_DG_RESERVOIR_DATA: +void handleDialysateFlowData( MESSAGE_T *message ); + +// MSG_ID_DG_RESERVOIR_DATA: void handleDGReservoirData( MESSAGE_T *message ); // MSG_ID_UI_INITIATE_TREATMENT_REQUEST @@ -237,8 +237,8 @@ void handleTreatmentParametersFromUI( MESSAGE_T *message ); // MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE -BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ); - +BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ); + // MSG_ID_UI_SET_UF_VOLUME_PARAMETER void handleUFVolumeSetRequest( MESSAGE_T *message ); @@ -248,40 +248,40 @@ // MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS void handleUIUserConfirmTreatmentParameters( MESSAGE_T *message ); -// MSG_ID_USER_UF_PAUSE_RESUME_REQUEST -void handleUFPauseResumeRequest( MESSAGE_T *message ); +// MSG_ID_USER_UF_PAUSE_RESUME_REQUEST +void handleUFPauseResumeRequest( MESSAGE_T *message ); -// MSG_ID_USER_UF_PAUSE_RESUME_RESPONSE +// MSG_ID_USER_UF_PAUSE_RESUME_RESPONSE BOOL sendUFPauseResumeResponse( BOOL accepted, U32 reason, U32 ufState ); -// MSG_ID_USER_UF_SETTINGS_CHANGE_REQUEST -void handleChangeUFSettingsRequest( MESSAGE_T *message ); - -// MSG_ID_USER_UF_SETTINGS_CHANGE_RESPONSE -BOOL sendChangeUFSettingsResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min, S32 timeDiff, F32 rateDiff, F32 oldUFRate_mL_min ); - -// MSG_ID_USER_CONFIRM_UF_SETTINGS_CHANGE -void handleChangeUFSettingsConfirmation( MESSAGE_T *message ); - -// MSG_ID_USER_UF_SETTINGS_CHANGE_CONFIRMATION_RESPONSE -BOOL sendChangeUFSettingsOptionResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min ); - -// MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST -void handleChangeTreatmentDurationRequest( MESSAGE_T *message ); - -// MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE -BOOL sendChangeTreatmentDurationResponse( BOOL accepted, U32 reason, U32 time_min, F32 volume_mL ); - +// MSG_ID_USER_UF_SETTINGS_CHANGE_REQUEST +void handleChangeUFSettingsRequest( MESSAGE_T *message ); + +// MSG_ID_USER_UF_SETTINGS_CHANGE_RESPONSE +BOOL sendChangeUFSettingsResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min, S32 timeDiff, F32 rateDiff, F32 oldUFRate_mL_min ); + +// MSG_ID_USER_CONFIRM_UF_SETTINGS_CHANGE +void handleChangeUFSettingsConfirmation( MESSAGE_T *message ); + +// MSG_ID_USER_UF_SETTINGS_CHANGE_CONFIRMATION_RESPONSE +BOOL sendChangeUFSettingsOptionResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min ); + +// MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST +void handleChangeTreatmentDurationRequest( MESSAGE_T *message ); + +// MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE +BOOL sendChangeTreatmentDurationResponse( BOOL accepted, U32 reason, U32 time_min, F32 volume_mL ); + // MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: void handleTestTreatmentTimeRemainingOverrideRequest( MESSAGE_T *message ); -// MSG_ID_TREATMENT_PARAM_CHANGE_RANGES -BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, F32 minUFVol, F32 maxUFVol, U32 minDialRate, U32 maxDialRate ); +// MSG_ID_TREATMENT_PARAM_CHANGE_RANGES +BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, F32 minUFVol, F32 maxUFVol, U32 minDialRate, U32 maxDialRate ); // MSG_ID_HD_TREATMENT_LOG_PERIODIC_DATA BOOL sendTreatmentPeriodicDataToUI( TREATMENT_LOG_DATA_PERIODIC_T * periodDataPtr ); -// MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST +// MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST void handleChangeBloodDialysateRateChangeRequest( MESSAGE_T *message ); // MSG_ID_USER_SALINE_BOLUS_REQUEST @@ -290,9 +290,9 @@ // MSG_ID_USER_SALINE_BOLUS_RESPONSE BOOL sendSalineBolusResponse( BOOL accepted, U32 rejReason, U32 bolusVol ); -// MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_RESPONSE -BOOL sendChangeBloodDialysateRateChangeResponse( BOOL accepted, U32 reason, U32 bloodRate, U32 dialRate ); - +// MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_RESPONSE +BOOL sendChangeBloodDialysateRateChangeResponse( BOOL accepted, U32 reason, U32 bloodRate, U32 dialRate ); + // MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST void handleChangePressureLimitsRequest( MESSAGE_T *message ); @@ -427,37 +427,37 @@ // *********** public DG command functions ********** -// MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS -BOOL sendDialysateHeatingParamsToDG( DG_CMD_DIALYSATE_HEATING_PARAMS_T *params ); - -// MSG_ID_DG_SWITCH_RESERVOIR_CMD -BOOL sendDGSwitchReservoirCommand( DG_SWITCH_RSRVRS_CMD_T *cmd ); +// MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS +BOOL sendDialysateHeatingParamsToDG( DG_CMD_DIALYSATE_HEATING_PARAMS_T *params ); +// MSG_ID_DG_SWITCH_RESERVOIR_CMD +BOOL sendDGSwitchReservoirCommand( DG_SWITCH_RSRVRS_CMD_T *cmd ); + // MSG_ID_DG_CHANGE_VALVE_SETTING_CMD BOOL sendDGChangeValveSettingCommand( U32 valveSettingCmd ); - -// MSG_ID_DG_FILL_CMD -BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl, F32 targetFlowRateLPM ); - -// MSG_ID_DG_DRAIN_CMD -BOOL sendDGDrainCommand( DRAIN_RESERVOIR_CMD_PAYLOAD_T *drainCmdPtr ); - -// MSG_ID_STARTING_STOPPING_TREATMENT_CMD -BOOL sendDGStartStopCommand( BOOL start ); - -// MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD -BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ); - -// MSG_ID_DG_SAMPLE_WATER_CMD -BOOL sendDGSampleWaterCommand( SAMPLE_WATER_CMD_T cmd ); +// MSG_ID_DG_FILL_CMD +BOOL sendDGFillCommand( U32 cmd, U32 fillToVolumeMl, F32 targetFlowRateLPM ); + +// MSG_ID_DG_DRAIN_CMD +BOOL sendDGDrainCommand( DRAIN_RESERVOIR_CMD_PAYLOAD_T *drainCmdPtr ); + +// MSG_ID_STARTING_STOPPING_TREATMENT_CMD +BOOL sendDGStartStopCommand( BOOL start ); + +// MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ); + +// MSG_ID_DG_SAMPLE_WATER_CMD +BOOL sendDGSampleWaterCommand( SAMPLE_WATER_CMD_T cmd ); + // MSG_ID_DG_COMMAND_RESPONSE void handleDGCmdResp( MESSAGE_T *messagePtr ); // MSG_ID_UI_HD_SET_RTC_REQUEST: void handleUIClockSyncRequest( MESSAGE_T *message ); - -// MSG_ID_DG_OP_MODE + +// MSG_ID_DG_OP_MODE void handleDGOpMode( MESSAGE_T *message ); // MSG_ID_DG_START_STOP_FLUSH @@ -484,7 +484,7 @@ // MSG_ID_UI_REQUEST_SERVICE_MODE void handleUIServiceModeRequest( MESSAGE_T *message ); -// MSG_ID_ALARM_STATUS +// MSG_ID_ALARM_STATUS BOOL broadcastAlarmStatus( COMP_ALARM_STATUS_T almStatus ); // MSG_ID_HD_SEND_CALIBRATION_RECORD @@ -567,130 +567,130 @@ // MSG_ID_DG_START_STOP_PASSIVE_COOL_HEAT_DISINFECT BOOL sendDGStartHeatDisinfectPassiveCoolModeCommand( BOOL start ); -// *********** public test support message functions ********** - -// MSG_TESTER_LOG_IN -void handleTesterLogInRequest( MESSAGE_T *message ); +// *********** public test support message functions ********** + +// MSG_TESTER_LOG_IN +void handleTesterLogInRequest( MESSAGE_T *message ); BOOL isTestingActivated( void ); -void setTesterStatusToLoggedOut( void ); - -// MSG_ID_OFF_BUTTON_STATE_OVERRIDE -void handleTestOffButtonStateOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_STOP_BUTTON_STATE_OVERRIDE -void handleTestStopButtonStateOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_ALARM_LAMP_PATTERN_OVERRIDE -void handleTestAlarmLampPatternOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_WATCHDOG_TASK_CHECKIN_OVERRIDE: -void handleTestWatchdogCheckInStateOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_ALARM_STATE_OVERRIDE -void handleTestAlarmStateOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_ALARM_TIME_OVERRIDE -void handleTestAlarmTimeOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_FLOW_SET_PT_OVERRIDE -void handleTestBloodFlowSetPointOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE -void handleTestBloodFlowMeasuredOverrideRequest( MESSAGE_T *message ); - +void setTesterStatusToLoggedOut( void ); + +// MSG_ID_OFF_BUTTON_STATE_OVERRIDE +void handleTestOffButtonStateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_STOP_BUTTON_STATE_OVERRIDE +void handleTestStopButtonStateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_ALARM_LAMP_PATTERN_OVERRIDE +void handleTestAlarmLampPatternOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_WATCHDOG_TASK_CHECKIN_OVERRIDE: +void handleTestWatchdogCheckInStateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_ALARM_STATE_OVERRIDE +void handleTestAlarmStateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_ALARM_TIME_OVERRIDE +void handleTestAlarmTimeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_FLOW_SET_PT_OVERRIDE +void handleTestBloodFlowSetPointOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE +void handleTestBloodFlowMeasuredOverrideRequest( MESSAGE_T *message ); + // MSG_ID_BLOOD_ROTOR_COUNT_OVERRIDE void handleHDBloodPumpRotorCountOverrideRequest( MESSAGE_T *message ); // MSG_ID_DIALYSATE_INLET_PUMP_ROTOR_COUNT_OVERRIDE void handleHDDialInPumpRotorCountOverrideRequest( MESSAGE_T *message ); -// MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE -void handleTestBloodPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_PUMP_MC_MEAS_CURR_OVERRIDE -void handleTestBloodPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE -void handleTestBloodFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE -void handleTestBloodPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_BLOOD_PUMP_MEAS_ROTOR_SPEED_OVERRIDE -void handleTestBloodPumpRotorMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_FLOW_SET_PT_OVERRIDE +// MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE +void handleTestBloodPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_PUMP_MC_MEAS_CURR_OVERRIDE +void handleTestBloodPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE +void handleTestBloodFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE +void handleTestBloodPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_BLOOD_PUMP_MEAS_ROTOR_SPEED_OVERRIDE +void handleTestBloodPumpRotorMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_FLOW_SET_PT_OVERRIDE void handleTestDialInFlowSetPointOverrideRequest( MESSAGE_T *message ); // MSG_ID_DIAL_OUT_FLOW_SET_PT_OVERRIDE -void handleTestDialOutFlowSetPointOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE -void handleTestDialInFlowMeasuredOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE -void handleTestDialInPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_PUMP_MC_MEAS_CURR_OVERRIDE -void handleTestDialInPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_FLOW_SEND_INTERVAL_OVERRIDE -void handleTestDialInFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE -void handleTestDialInPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_IN_PUMP_MEAS_ROTOR_SPEED_OVERRIDE -void handleTestDialInPumpRotorMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_PRESSURE_ARTERIAL_OVERRIDE -void handleTestArterialPressureOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_PRESSURE_VENOUS_OVERRIDE -void handleTestVenousPressureOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE +void handleTestDialOutFlowSetPointOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE +void handleTestDialInFlowMeasuredOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE +void handleTestDialInPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_PUMP_MC_MEAS_CURR_OVERRIDE +void handleTestDialInPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_FLOW_SEND_INTERVAL_OVERRIDE +void handleTestDialInFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE +void handleTestDialInPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_IN_PUMP_MEAS_ROTOR_SPEED_OVERRIDE +void handleTestDialInPumpRotorMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_PRESSURE_ARTERIAL_OVERRIDE +void handleTestArterialPressureOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_PRESSURE_VENOUS_OVERRIDE +void handleTestVenousPressureOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE void handleTestBloodPumpOcclusionOverrideRequest( MESSAGE_T *message ); //MSG_ID_HD_PARTIAL_OCCLUSION_BLOOD_PUMP_OVERRIDE void handleTestFilteredBloodPumpOcclusionOverrideRequest( MESSAGE_T *message ); //MSG_ID_HD_PARTIAL_OCCL_BLOOD_PUMP_BASELINE_OVERRIDE -void handleTestBloodPumpOcclusionBaselineOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE -void handleTestPresOcclBroadcastIntervalOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_SET_RTC_TIMESTAMP -void handleSetRTCTimestamp( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_FLOW_SEND_INTERVAL_OVERRIDE -void handleTestDialOutFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_UF_REF_VOLUME_OVERRIDE -void handleTestDialOutUFReferenceVolumeOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_UF_MEAS_VOLUME_OVERRIDE -void handleTestDialOutUFMeasuredVolumeOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_PUMP_MC_MEAS_SPEED_OVERRIDE -void handleTestDialOutPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_PUMP_MC_MEAS_CURR_OVERRIDE -void handleTestDialOutPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_PUMP_MEAS_SPEED_OVERRIDE -void handleTestDialOutPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_PUMP_MEAS_ROTOR_SPEED_OVERRIDE -void handleTestDialOutPumpMeasuredRotorSpeedOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_DIAL_OUT_LOAD_CELL_WEIGHT_OVERRIDE -void handleTestDialOutLoadCellWeightOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE: -void handleTestHDSafetyShutdownOverrideRequest( MESSAGE_T *message ); +void handleTestBloodPumpOcclusionBaselineOverrideRequest( MESSAGE_T *message ); +// MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE +void handleTestPresOcclBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_SET_RTC_TIMESTAMP +void handleSetRTCTimestamp( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_FLOW_SEND_INTERVAL_OVERRIDE +void handleTestDialOutFlowBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_UF_REF_VOLUME_OVERRIDE +void handleTestDialOutUFReferenceVolumeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_UF_MEAS_VOLUME_OVERRIDE +void handleTestDialOutUFMeasuredVolumeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_PUMP_MC_MEAS_SPEED_OVERRIDE +void handleTestDialOutPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_PUMP_MC_MEAS_CURR_OVERRIDE +void handleTestDialOutPumpMCMeasuredCurrentOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_PUMP_MEAS_SPEED_OVERRIDE +void handleTestDialOutPumpMeasuredSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_PUMP_MEAS_ROTOR_SPEED_OVERRIDE +void handleTestDialOutPumpMeasuredRotorSpeedOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DIAL_OUT_LOAD_CELL_WEIGHT_OVERRIDE +void handleTestDialOutLoadCellWeightOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE: +void handleTestHDSafetyShutdownOverrideRequest( MESSAGE_T *message ); + // MSG_ID_HD_ACCEL_OVERRIDE: void handleTestHDAccelOverrideRequest( MESSAGE_T *message ); @@ -1033,6 +1033,15 @@ // MSG_ID_HD_SET_INSTITUTIONAL_RECORD void handleSetHDInstitutionalRecord( MESSAGE_T *message ); +// MSG_ID_HD_BLOOD_LEAK_EMB_MODE_INFO_VALUES_OVERRIDE +void handleBloodLeakEmbModeInfoValuesOverride( MESSAGE_T* message ); + +// MSG_ID_HD_BLOOD_LEAK_INTENSITY_MVG_AVERAGE_OVERRIDE +void handleBloodLeakIntensityMovingAverageOverride( MESSAGE_T* message ); + +// MSG_ID_HD_BLOOD_LEAK_ZEROING_INTERVAL_IN_MINS_OVERRIDE +void handleBloodLeakZeroingIntervalInMinutesOverride( MESSAGE_T* message ); + /**@}*/ -#endif +#endif