Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -15,7 +15,7 @@ * ***************************************************************************/ -#include +#include // Used for fabs() and pow() functions #include "can.h" #include "etpwm.h" @@ -56,7 +56,8 @@ #define BP_I_COEFFICIENT 0.00075 ///< I term for blood pump control #define BP_HOME_RATE 100 ///< Target pump speed (in estimate mL/min) for homing. -#define BP_HOME_TIMEOUT_MS 10000 ///< Maximum time allowed for homing to complete (in ms). +#define BP_HOME_TIMEOUT_MS 10000 ///< Maximum time (in ms) allowed for homing to complete. +#define BP_MAX_ROTOR_HALL_INTERVAL_MS 20000 ///< Maximum time (in ms) allowed between rotor hall sensor detects (50 mL/min worst case). /// Interval (ms/task time) at which the blood pump speed is calculated (every 40 ms). #define BP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) /// Number of hall sensor counts kept in buffer to hold last 1 second of count data. @@ -65,64 +66,58 @@ #define BP_MAX_FLOW_RATE 1320.0 ///< Maximum measured BP flow rate allowed. #define BP_MIN_FLOW_RATE -1320.0 ///< Minimum measured BP flow rate allowed. -#define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured speed and speed implied by measured flow. #define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -/// Persist time (task intervals) for flow vs. motor speed error condition. +#define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured speed and speed implied by measured flow. + +/// Persist time (task intervals) for flow vs. motor speed error condition. static const U32 BP_FLOW_VS_SPEED_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) for motor off error condition. static const U32 BP_OFF_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) motor speed error condition. static const U32 BP_MOTOR_SPEED_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) rotor speed error condition. -static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ( 12 * MS_PER_SECOND ); +static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ( 22 * MS_PER_SECOND ); /// Persist time (task intervals) pump direction error condition. static const U32 BP_DIRECTION_ERROR_PERSIST = ( 250 ); /// Persist time period blood pump rotor speed too fast error condition. static const U32 BP_MAX_ROTOR_SPEED_ERROR_PERSIST = ( 1 * MS_PER_SECOND ); /// Persist time (task intervals) blood flow rate out of range error condition. static const U32 BP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST = ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); -#define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped -#define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running -#define BP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm +#define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. +#define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. +#define BP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. -#define BP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for blood pump motor -#define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000238 ///< ~42 BP motor RPM = 1% PWM duty cycle -#define BP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for blood pump motor +#define BP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for blood pump motor. +#define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000238 ///< ~42 BP motor RPM = 1% PWM duty cycle. +#define BP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for blood pump motor. -#define BP_REV_PER_LITER 150.0 ///< Rotor revolutions per liter +#define BP_REV_PER_LITER 146.84 ///< Rotor revolutions per liter. +#define BP_ML_PER_ROTOR_REV 6.81 ///< Milliliters per rotor revolusion. #define BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( BP_REV_PER_LITER / ML_PER_LITER ) ///< Conversion factor from mL/min to motor RPM. -#define BP_GEAR_RATIO 32.0 ///< Blood pump motor to blood pump gear ratio -#define BP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed +#define BP_GEAR_RATIO 32.0 ///< Blood pump motor to blood pump gear ratio. +#define BP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. /// Conversion macro from mL/min to estimated PWM duty cycle %. #define BP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * BP_GEAR_RATIO * BP_MOTOR_RPM_TO_PWM_DC_FACTOR + BP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. #define BP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - BP_PWM_ZERO_OFFSET) * 4000.0 ) -#define BLOODPUMP_ADC_FULL_SCALE_V 3.0 ///< BP analog signals are 0-3V (while int. ADC ref may be different) +#define BLOODPUMP_ADC_FULL_SCALE_V 3.0 ///< BP analog signals are 0-3V (while int. ADC ref may be different). #define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. /// Macro converts 12 bit ADC value to signed 16-bit value. #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)BLOODPUMP_ADC_ZERO ) -/// Measured blood flow is filtered w/ moving average -#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) -/// Blood flow sensor signal strength low alarm persistence. -#define FLOW_SIG_STRGTH_ALARM_PERSIST ( BP_CONTROL_INTERVAL_SEC * MS_PER_SECOND ) -#define MIN_FLOW_SIG_STRENGTH 0.9 ///< Minimum flow sensor signal strength (90%). +/// Measured blood flow is filtered w/ moving average. +#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 1 ) -/// Blood flow fast read timeout alarm persistence. -#define BLOOD_FLOW_FAST_READ_TO_PERSIST 100 -/// Blood flow slow read timeout alarm persistence. -#define BLOOD_FLOW_SLOW_READ_TO_PERSIST ( MS_PER_SECOND * 3 ) -/// Blood flow comm error persistence. -#define BLOOD_FLOW_COMM_ERROR_PERSIST MS_PER_SECOND - -#define BFM_SENSOR_CONNECTED_STATUS 0x00 ///< Blood flow meter connected status. -#define BFM_SENSOR_PARAM_CORRUPT_STATUS 0x07 ///< Blood flow meter NVM parameter status. - #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. + +#define BP_FLOW_ALPHA_Y_INTERCEPT 1.218 ///< Y intercept used for alpha flow coefficient calculation. +#define BP_FLOW_WEAR_A_TERM 0.000000007474 ///< A term used for wear portion of alpha flow coefficient. +#define BP_FLOW_WEAR_B_TERM 0.0006053 ///< B term used for wear portion of alpha flow coefficient. +#define BP_MAX_ROTOR_COUNT_FOR_WEAR 25000 ///< Maximum rotor count for determining wear of the cartridge (negligible affect beyond this threshold). /// Enumeration of blood pump controller states. typedef enum BloodPump_States @@ -166,18 +161,25 @@ /// Interval (in task intervals) at which to publish blood flow data to CAN bus. static OVERRIDE_U32_T bloodFlowDataPublishInterval = { BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, 0 }; -static S32 targetBloodFlowRate = 0; ///< Requested blood flow rate -static OVERRIDE_F32_T measuredBloodFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood flow rate -static OVERRIDE_F32_T bloodPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump rotor speed -static OVERRIDE_F32_T bloodPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor speed -static OVERRIDE_F32_T adcBloodPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor controller speed -static OVERRIDE_F32_T adcBloodPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor controller current -static OVERRIDE_F32_T bloodFlowSignalStrength = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood flow signal strength (%) +static S32 targetBloodFlowRate = 0; ///< Requested blood flow rate. +static OVERRIDE_F32_T measuredBloodFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< Measured (calculated now) blood flow rate. +static OVERRIDE_F32_T bloodPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump rotor speed. +static OVERRIDE_F32_T bloodPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor speed. +static OVERRIDE_F32_T adcBloodPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor controller speed. +static OVERRIDE_F32_T adcBloodPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood pump motor controller current. +static U08 lastBloodPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. + +static F32 rpmReadings[ SIZE_OF_ROLLING_AVG ]; ///< Holds RPM samples for a rolling average. +static U32 rpmReadingsIdx = 0; ///< Index for next sample in rolling average array. +static F32 rpmReadingsTotal = 0.0; ///< Rolling total - used to calc average. +static U32 rpmReadingsCount = 0; ///< Number of samples in RPM rolling average buffer. +static F32 filteredBloodPumpSpeed = 0.0; ///< Filtered blood pump speed used in blood flow estimation. + static U32 bpControlTimerCounter = 0; ///< Determines when to perform control on blood flow static U32 bpRotorRevStartTime = 0; ///< Blood pump rotor rotation start time (in ms) -static U32 bloodPumpRotorCounter = 0; ///< Running counter for blood pump rotor revolutions +static OVERRIDE_U32_T bloodPumpRotorCounter = { 0, 0, 0, 0 }; ///< Running counter for blood pump rotor revolutions static BOOL bpStopAtHomePosition = FALSE; ///< Stop blood pump at next home position static U32 bpHomeStartTime = 0; ///< When did blood pump home command begin? (in ms) @@ -186,17 +188,6 @@ static U32 bpMotorSpeedCalcIdx = 0; ///< Index into 1 second buffer of motor speed hall sensor counts static U32 bpMotorSpeedCalcTimerCtr = 0; ///< Counter determines interval for calculating blood pump motor speed from hall sensor count. -static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< Holds flow samples for a rolling average. -static U32 flowReadingsIdx = 0; ///< Index for next sample in rolling average array. -static F32 flowReadingsTotal = 0.0; ///< Rolling total - used to calc average. -static U32 flowReadingsCount = 0; ///< Number of samples in flow rolling average buffer. - -static U08 lastBloodFlowFastPacketReadCtr = 0; ///< Previous read counter for the blood flow fast packets. -static U08 lastBloodFlowSlowPacketReadCtr = 0; ///< Previous read counter for the blood flow slow packets. -static U08 lastBloodPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. -static U08 lastBloodFlowCommErrorCount = 0; ///< Previous BP flow sensor comm error count. -static HD_FLOW_SENSORS_CAL_RECORD_T bloodFlowCalRecord; ///< Blood flow sensor calibration record. - // ********** private function prototypes ********** static BLOOD_PUMP_STATE_T handleBloodPumpOffState( void ); @@ -208,17 +199,17 @@ static void releaseBloodPumpStop( void ); static void setBloodPumpDirection( MOTOR_DIR_T dir ); static void publishBloodFlowData( void ); -static void resetBloodFlowMovingAverage( void ); -static void filterBloodFlowReadings( F32 flow ); static void updateBloodPumpSpeedAndDirectionFromHallSensors( void ); static void checkBloodPumpRotor( void ); static void checkBloodPumpDirection( void ); static void checkBloodPumpSpeeds( void ); -static void checkBloodPumpFlowAgainstSpeed( void ); static void checkBloodPumpMCCurrent( void ); -static void checkBloodFlowSensorSignalStrength( void ); -static BOOL processCalibrationData( void ); - +static void checkBloodPumpFlowRate( void ); + +static F32 calcBloodFlow( void ); +static void resetBloodPumpRPMMovingAverage( void ); +static void filterBloodPumpRPMReadings( F32 rpm ); + /*********************************************************************//** * @brief * The initBloodFlow function initializes the BloodFlow module. @@ -233,30 +224,30 @@ stopBloodPump(); setBloodPumpDirection( MOTOR_DIR_FORWARD ); - // Zero rolling flow average buffer - resetBloodFlowMovingAverage(); + // Zero rolling pump speed average buffer + resetBloodPumpRPMMovingAverage(); // Zero motor hall sensors counts buffer bpMotorSpeedCalcIdx = 0; for ( i = 0; i < BP_SPEED_CALC_BUFFER_LEN; i++ ) { bpLastMotorHallSensorCounts[ i ] = 0; } + resetBloodPumpRotorCount(); // Initialize blood flow PI controller initializePIController( PI_CONTROLLER_ID_BLOOD_FLOW, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, BP_P_COEFFICIENT, BP_I_COEFFICIENT, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); // Initialize persistent alarm for flow sensor - initPersistentAlarm( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, 0, BP_FLOW_VS_SPEED_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_OFF_CHECK, 0, BP_OFF_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, 0, BP_MOTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, 0, BP_ROTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, 0, BP_DIRECTION_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, 0, BP_MAX_ROTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, 0, BP_MAX_CURR_ERROR_DURATION_MS ); - initPersistentAlarm( ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, FLOW_SIG_STRGTH_ALARM_PERSIST, FLOW_SIG_STRGTH_ALARM_PERSIST ); + initPersistentAlarm( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, 0, BP_FLOW_VS_SPEED_PERSIST ); initPersistentAlarm( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, 0, BP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST ); } @@ -283,7 +274,7 @@ if ( flowRate <= MAX_SET_BLOOD_FLOW_RATE ) #endif { - resetBloodFlowMovingAverage(); + resetBloodPumpRPMMovingAverage(); targetBloodFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); bloodPumpDirection = dir; bloodPumpControlMode = mode; @@ -297,13 +288,15 @@ { bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; } - break; + break; + case BLOOD_PUMP_RAMPING_DOWN_STATE: // See if we need to reverse direction of ramp if ( bloodPumpPWMDutyCyclePct > bloodPumpPWMDutyCyclePctSet ) { bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; } - break; + break; + case BLOOD_PUMP_CONTROL_TO_TARGET_STATE: // Start ramp to new target in appropriate direction if ( bloodPumpPWMDutyCyclePctSet > bloodPumpPWMDutyCyclePct ) { @@ -313,7 +306,8 @@ { bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; } - break; + break; + default: // Ok - not all states need to be handled here break; @@ -331,6 +325,32 @@ return result; } +/*********************************************************************//** + * @brief + * The calcBloodFlow function calculates an estimated blood flow rate from + * blood pump speed, arterial pressure and tubing wear (measured from count + * of rotor revolutions since cartridge install). + * @details Inputs: bloodPumpRotorCounter, arterial pressure + * @details Outputs: none + * @return calculated blood flow rate (mL/min) + *************************************************************************/ +static F32 calcBloodFlow( void ) +{ + F32 artPres = getLongFilteredArterialPressure(); + F32 rotSpd = filteredBloodPumpSpeed / BP_GEAR_RATIO; +#ifndef WORN_OUT_CARTRIDGE + U32 r = getBloodPumpRotorCount(); + U32 rotCnt = CAP( r, BP_MAX_ROTOR_COUNT_FOR_WEAR ); +#else + U32 rotCnt = BP_MAX_ROTOR_COUNT_FOR_WEAR; +#endif + F32 wear = BP_FLOW_WEAR_A_TERM * (F32)rotCnt + BP_FLOW_WEAR_B_TERM; + F32 alpha = wear * artPres + BP_FLOW_ALPHA_Y_INTERCEPT; + F32 flow = alpha * BP_ML_PER_ROTOR_REV * rotSpd; + + return flow; +} + /*********************************************************************//** * @brief * The signalBloodPumpHardStop function stops the blood pump immediately. @@ -363,7 +383,7 @@ U32 deltaTime = calcTimeBetween( bpRotorRevStartTime, rotTime ); // Increment rotor counter - bloodPumpRotorCounter++; + bloodPumpRotorCounter.data++; // Calculate rotor speed (in RPM) bloodPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; @@ -421,7 +441,14 @@ *************************************************************************/ U32 getBloodPumpRotorCount( void ) { - return bloodPumpRotorCounter; + U32 result = bloodPumpRotorCounter.data; + + if ( OVERRIDE_KEY == bloodPumpRotorCounter.override ) + { + result = bloodPumpRotorCounter.ovData; + } + + return result; } /*********************************************************************//** @@ -435,6 +462,20 @@ BOOL isBloodPumpRunning( void ) { return isBloodPumpOn; +} + +/*********************************************************************//** + * @brief + * The resetBloodPumpRotorCount function resets the blood pump rotor counter + * that is a proxy for cartridge wear. Call this function after a new cartridge + * has been installed. + * @details Inputs: none + * @details Outputs: bloodPumpRotorCounter + * @return none + *************************************************************************/ +void resetBloodPumpRotorCount( void ) +{ + bloodPumpRotorCounter.data = 0; } /*********************************************************************//** @@ -447,43 +488,15 @@ *************************************************************************/ void execBloodFlowMonitor( void ) { - // Check if a new calibration is available - if ( TRUE == isNewCalibrationRecordAvailable() ) - { - // Get the new calibration data and check its validity - processCalibrationData(); - } - HD_OP_MODE_T opMode = getCurrentOperationMode(); U16 bpRPM = getIntADCReading( INT_ADC_BLOOD_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_BLOOD_PUMP_MOTOR_CURRENT ); - U08 fpReadCtr = getFPGABloodFlowFastPacketReadCounter(); - U08 spReadCtr = getFPGABloodFlowSlowPacketReadCounter(); - U08 flowErrorCtr = getFPGABloodFlowErrorCounter(); - U08 flowStatus = getFPGABloodFlowMeterStatus(); - F32 fpgaBloodFlow = getFPGABloodFlow(); - F32 bpFlow = pow(fpgaBloodFlow, 4) * bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].fourthOrderCoeff + - pow(fpgaBloodFlow, 3) * bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].thirdOrderCoeff + - pow(fpgaBloodFlow, 2) * bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].secondOrderCoeff + - fpgaBloodFlow * bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].gain + - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].offset; - - if ( flowStatus != BFM_SENSOR_CONNECTED_STATUS ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_FLOW_STATUS_SELF_TEST_FAILURE, (U32)flowStatus ); - } - lastBloodFlowCommErrorCount = flowErrorCtr; - - // Record flow read counters for next time around - lastBloodFlowFastPacketReadCtr = fpReadCtr; - lastBloodFlowSlowPacketReadCtr = spReadCtr; - adcBloodPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * BP_SPEED_ADC_TO_RPM_FACTOR; adcBloodPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; - bloodFlowSignalStrength.data = getFPGABloodFlowSignalStrength(); - filterBloodFlowReadings( bpFlow ); + filterBloodPumpRPMReadings( getMeasuredBloodPumpMCSpeed() ); + measuredBloodFlowRate.data = calcBloodFlow(); // Pressure and rotor speed already filtered as inputs to calc, so no need to filter flow any further // Calculate blood pump motor speed/direction from hall sensor count updateBloodPumpSpeedAndDirectionFromHallSensors(); @@ -497,11 +510,9 @@ checkBloodPumpMCCurrent(); // Check pump speeds and flow checkBloodPumpSpeeds(); - checkBloodPumpFlowAgainstSpeed(); + checkBloodPumpFlowRate(); // Check for home position, zero/low speed checkBloodPumpRotor(); - // Check flow sensor signal strength - checkBloodFlowSensorSignalStrength(); } // Publish blood flow data on interval @@ -592,7 +603,7 @@ // Have we reached end of ramp up? else if ( bloodPumpPWMDutyCyclePctSet >= bloodPumpPWMDutyCyclePct ) { - resetBloodFlowMovingAverage(); + resetBloodPumpRPMMovingAverage(); bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); bloodPumpControlModeSet = bloodPumpControlMode; @@ -631,7 +642,7 @@ // Have we reached end of ramp down? else if ( bloodPumpPWMDutyCyclePctSet <= bloodPumpPWMDutyCyclePct ) { - resetBloodFlowMovingAverage(); + resetBloodPumpRPMMovingAverage(); bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); bloodPumpControlModeSet = bloodPumpControlMode; @@ -770,26 +781,6 @@ return result; } -/*********************************************************************//** - * @brief - * The getMeasuredBloodFlowSignalStrength function gets the measured blood flow - * signal strength. - * @details Inputs: bloodFlowSignalStrength - * @details Outputs: none - * @return the current blood flow signal strength (in %). - *************************************************************************/ -F32 getMeasuredBloodFlowSignalStrength( void ) -{ - F32 result = bloodFlowSignalStrength.data; - - if ( OVERRIDE_KEY == bloodFlowSignalStrength.override ) - { - result = bloodFlowSignalStrength.ovData; - } - - return result; -} - /*********************************************************************//** * @brief * The getMeasuredBloodPumpRotorSpeed function gets the measured blood flow @@ -893,55 +884,52 @@ payload.measMCSpd = getMeasuredBloodPumpMCSpeed(); payload.measMCCurr = getMeasuredBloodPumpMCCurrent(); payload.pwmDC = bloodPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; - payload.flowSigStrength = getMeasuredBloodFlowSignalStrength() * FRACTION_TO_PERCENT_FACTOR; - broadcastBloodFlowData( &payload ); + payload.rotorCount = getBloodPumpRotorCount(); + broadcastData( MSG_ID_BLOOD_FLOW_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( BLOOD_PUMP_STATUS_PAYLOAD_T ) ); bloodFlowDataPublicationTimerCounter = 0; } } +/*********************************************************************//** + * @brief + * The resetBloodPumpRPMMovingAverage function re-initializes the pump speed + * moving average sample buffer. + * @details Inputs: none + * @details Outputs: rpmReadingsTotal, rpmReadingsIdx, rpmReadingsCount all set to zero. + * @return none + *************************************************************************/ +static void resetBloodPumpRPMMovingAverage( void ) +{ + rpmReadingsIdx = 0; + rpmReadingsCount = 0; + rpmReadingsTotal = 0.0; + filteredBloodPumpSpeed = 0.0; +} + +/*********************************************************************//** + * @brief + * The filterBloodPumpRPMReadings function adds a new pump speed sample to + * the filter. + * @details Inputs: none + * @details Outputs: rpmReadings[], rpmReadingsIdx, rpmReadingsCount, rpmReadingsTotal + * @param rpm newest blood pump speed (in RPM) sample to add to filter + * @return none + *************************************************************************/ +static void filterBloodPumpRPMReadings( F32 rpm ) +{ + if ( rpmReadingsCount >= SIZE_OF_ROLLING_AVG ) + { + rpmReadingsTotal -= rpmReadings[ rpmReadingsIdx ]; + } + rpmReadings[ rpmReadingsIdx ] = rpm; + rpmReadingsTotal += rpm; + rpmReadingsIdx = INC_WRAP( rpmReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); + rpmReadingsCount = INC_CAP( rpmReadingsCount, SIZE_OF_ROLLING_AVG ); + filteredBloodPumpSpeed = rpmReadingsTotal / (F32)rpmReadingsCount; +} + /*********************************************************************//** * @brief - * The resetBloodFlowMovingAverage function re-initializes the blood flow - * moving average sample buffer. - * @details Inputs: none - * @details Outputs: flowReadingsTotal, flowReadingsIdx, flowReadingsCount all set to zero. - * @return none - *************************************************************************/ -static void resetBloodFlowMovingAverage( void ) -{ - flowReadingsIdx = 0; - flowReadingsCount = 0; - flowReadingsTotal = 0.0; - bpControlTimerCounter = 0; -} - -/*********************************************************************//** - * @brief - * The filterBloodFlowReadings function adds a new flow sample to the filter. - * @details Inputs: none - * @details Outputs: flowReadings[], flowReadingsIdx, flowReadingsCount, flowReadingsTotal - * @param flow newest blood flow sample - * @return none - *************************************************************************/ -static void filterBloodFlowReadings( F32 flow ) -{ -#ifndef RAW_FLOW_SENSOR_DATA - if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) - { - flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; - } - flowReadings[ flowReadingsIdx ] = flow; - flowReadingsTotal += flow; - flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); - flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); - measuredBloodFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; -#else - measuredBloodFlowRate.data = flow; -#endif -} - -/*********************************************************************//** - * @brief * The updateBloodPumpSpeedAndDirectionFromHallSensors function calculates * the blood pump motor speed and direction from hall sensor counter on * a 1 second interval. @@ -975,7 +963,7 @@ // Keep a running 32-bit edge count used for safety check on volume in some functions delta = u16BiDiffWithWrap( last, bpMotorHallSensorCount ); - bloodPumpMotorEdgeCount += (U16)delta; + bloodPumpMotorEdgeCount += ( delta >= 0 ? (U16)delta : 0 ); // Update last count for next time bpLastMotorHallSensorCounts[ nextIdx ] = bpMotorHallSensorCount; @@ -1012,7 +1000,7 @@ } // If pump is stopped or running very slowly, set rotor speed to zero - if ( TRUE == didTimeout( bpRotorRevStartTime, BP_HOME_TIMEOUT_MS ) ) + if ( TRUE == didTimeout( bpRotorRevStartTime, BP_MAX_ROTOR_HALL_INTERVAL_MS ) ) { bloodPumpRotorSpeedRPM.data = 0.0; } @@ -1034,13 +1022,16 @@ BOOL isDirIncorrect; U08 dirErrorCnt = getFPGABloodPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS // Check pump direction error count if ( lastBloodPumpDirectionCount != dirErrorCnt ) { lastBloodPumpDirectionCount = dirErrorCnt; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_BLOOD_PUMP ) +#endif } - +#endif bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); bpDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); @@ -1128,48 +1119,6 @@ /*********************************************************************//** * @brief - * The checkBloodPumpFlowAgainstSpeed function checks the measured blood flow - * against the implied flow of the measured pump speed when in treatment mode - * and controlling to target flow. If a sufficient difference persists, a - * flow vs. motor speed check error is triggered. - * @details Inputs: measuredBloodFlowRate, bloodPumpSpeedRPM - * @details Outputs: alarm may be triggered - * @return none - *************************************************************************/ -static void checkBloodPumpFlowAgainstSpeed( void ) -{ - F32 flow = getMeasuredBloodFlowRate(); - - // Range check on measure BP flow rate. -#ifndef DISABLE_PUMP_FLOW_CHECKS - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, ( flow > BP_MAX_FLOW_RATE ) || ( flow < BP_MIN_FLOW_RATE ) ) ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, flow ); - } -#endif - - // Flow vs. speed check only performed while in treatment mode and while we are in control to target state - if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) - { - F32 speed = getMeasuredBloodPumpSpeed(); - F32 impliedSpeed = ( flow / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; - F32 delta = fabs( speed - impliedSpeed ); - - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) ) - { -#ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); -#endif - } - } - else - { - resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK ); - } -} - -/*********************************************************************//** - * @brief * The checkBloodPumpMCCurrent function checks the measured MC current vs. * the set state of the blood pump (stopped or running). * @details Inputs: @@ -1184,7 +1133,7 @@ // Check blood pump current during running state BOOL const isRunningMCCurrentBad = ( BLOOD_PUMP_OFF_STATE != bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ); - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, isOffMCCurrentBad || isRunningMCCurrentBad ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, isOffMCCurrentBad || isRunningMCCurrentBad ) ) { #ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, bpCurr ); @@ -1194,76 +1143,41 @@ /*********************************************************************//** * @brief - * The checkBloodFlowSensorSignalStrength function checks the measured blood - * flow sensor signal strength is sufficient for accurate flow sensing. - * @details Inputs: - * @details Outputs: + * The checkBloodPumpFlowRate function checks the measured blood flow rate + * is in range. + * @details Inputs: measuredBloodFlowRate + * @details Outputs: alarm may be triggered * @return none *************************************************************************/ -static void checkBloodFlowSensorSignalStrength( void ) +static void checkBloodPumpFlowRate( void ) { #ifndef DISABLE_PUMP_FLOW_CHECKS - HD_OP_MODE_T opMode = getCurrentOperationMode(); + F32 flow = getMeasuredBloodFlowRate(); - // Check flow sensor signal strength when appropriate TODO - in pre-treatment, must be far enough along for fluid to be in tubing - if ( MODE_TREA == opMode || ( MODE_PRET == opMode && FALSE ) ) + // Range check on measure BP flow rate. + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, ( flow > BP_MAX_FLOW_RATE ) || ( flow < BP_MIN_FLOW_RATE ) ) ) { - F32 sigStrength = getMeasuredBloodFlowSignalStrength(); - BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, flow ); + } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, outOfRange ) ) + // Flow vs. speed check only performed while in treatment mode and while we are in control to target state + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) + { + F32 speed = getMeasuredBloodPumpSpeed(); + F32 impliedSpeed = ( (F32)targetBloodFlowRate / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; + F32 delta = fabs( speed - impliedSpeed ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, sigStrength, MIN_FLOW_SIG_STRENGTH ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); } } -#endif -} - -/*********************************************************************//** - * @brief - * The processCalibrationData function gets the calibration data and makes - * sure it is valid by checking the calibration date. The calibration date - * should not be 0. - * @details Inputs: none - * @details Outputs: bloodFlowCalRecord - * @return TRUE if the calibration record is valid, otherwise FALSE - *************************************************************************/ -static BOOL processCalibrationData( void ) -{ - BOOL status = TRUE; - - // Get the calibration record from NVDataMgmt - HD_FLOW_SENSORS_CAL_RECORD_T calData = getHDFlowSensorsCalibrationRecord(); - - // Check if the calibration data that was received from NVDataMgmt is legitimate - // The calibration date item should not be zero. If the calibration date is 0, - // then the blood flow sensors data is not stored in the NV memory or it was corrupted. - if ( 0 == calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].calibrationTime ) + else { -#ifndef SKIP_CAL_CHECK - activateAlarmNoData( ALARM_ID_HD_BLOOD_FLOW_INVALID_CAL_RECORD ); - status = FALSE; -#endif + resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK ); } - - // The calibration data was valid, update the local copy - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].fourthOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].fourthOrderCoeff; - - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].thirdOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].thirdOrderCoeff; - - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].secondOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].secondOrderCoeff; - - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].gain = - calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].gain; - - bloodFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].offset = - calData.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].offset; - - return status; -} +#endif +} /*********************************************************************//** * @brief @@ -1274,28 +1188,10 @@ * @return the current state of the BloodFlow self-test. *************************************************************************/ SELF_TEST_STATUS_T execBloodFlowTest( void ) -{ - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - U08 const bfmStatus = getFPGABloodFlowMeterStatus(); +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - // Retrieve blood flow sensor calibration data and check for sensor connected status - if ( BFM_SENSOR_PARAM_CORRUPT_STATUS != bfmStatus ) - { - BOOL calStatus = processCalibrationData(); - - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } - } - else - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_FLOW_STATUS_SELF_TEST_FAILURE, (U32)bfmStatus ); - } + // TODO - anything to test here? return result; } @@ -1616,44 +1512,44 @@ /*********************************************************************//** * @brief - * The testSetMeasuredBloodFlowSignalStrengthOverride function overrides the measured - * blood flow signal strength. + * The testSetBloodPumpRotorCountOverride function overrides the blood pump + * rotor counter value. * @details Inputs: none - * @details Outputs: bloodFlowSignalStrength - * @param value override measured blood flow signal strength (in %) + * @details Outputs: bloodPumpRotorCounter + * @param value override blood pump rotor counter value * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetMeasuredBloodFlowSignalStrengthOverride( F32 value ) +BOOL testSetBloodPumpRotorCountOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; - bloodFlowSignalStrength.ovData = value / 100.0; - bloodFlowSignalStrength.override = OVERRIDE_KEY; + bloodPumpRotorCounter.ovData = value; + bloodPumpRotorCounter.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief - * The testResetMeasuredBloodFlowSignalStrengthOverride function resets the override - * of the measured blood flow signal strength. + * The testResetBloodPumpRotorCountOverride function resets the override + * of the blood pump rotor counter. * @details Inputs: none - * @details Outputs: bloodFlowSignalStrength + * @details Outputs: bloodPumpRotorCounter * @return TRUE if reset successful, FALSE if not *************************************************************************/ -BOOL testResetMeasuredBloodFlowSignalStrengthOverride( void ) +BOOL testResetBloodPumpRotorCountOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; - bloodFlowSignalStrength.override = OVERRIDE_RESET; - bloodFlowSignalStrength.ovData = bloodFlowSignalStrength.ovInitData; + bloodPumpRotorCounter.override = OVERRIDE_RESET; + bloodPumpRotorCounter.ovData = bloodPumpRotorCounter.ovInitData; } return result; Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -29,7 +29,8 @@ #include "PersistentAlarm.h" #include "PIControllers.h" #include "SafetyShutdown.h" -#include "SystemCommMessages.h" +#include "SystemCommMessages.h" +#include "SystemComm.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" @@ -65,7 +66,7 @@ #define DIP_MAX_FLOW_RATE 1320.0 ///< Maximum measured BP flow rate allowed. #define DIP_MIN_FLOW_RATE -1320.0 ///< Minimum measured BP flow rate allowed. -#define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured motor speed and speed implied by measured flow. +#define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured motor speed and speed implied by measured flow. #define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. @@ -82,6 +83,8 @@ static const U32 DIP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); /// Persist time (task intervals) dialysate flow rate out of range error condition. static const U32 DIP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST = ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Time threshold to trigger an alarm if Dialysate flow data has not arrived within 3 seconds +static const U32 DIP_DIALYSATE_FLOW_DATA_ALARM_THRESHOLD = ((3 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. #define DIP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. @@ -91,13 +94,13 @@ #define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000193 ///< ~52 BP motor RPM = 1% PWM duty cycle #define DIP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for dialIn pump motor. -#define DIP_REV_PER_LITER 150.0 ///< Rotor revolutions per liter. +#define DIP_REV_PER_LITER 146.84 ///< Rotor revolutions per liter. /// Macro converts flow rate to motor RPM. #define DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DIP_REV_PER_LITER / ML_PER_LITER ) #define DIP_GEAR_RATIO 32.0 ///< DialIn pump motor to dialIn pump gear ratio. #define DIP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. -/// Macro converts flow rate to estimate PWM needed to achieve it. -#define DIP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO * DIP_MOTOR_RPM_TO_PWM_DC_FACTOR + DIP_PWM_ZERO_OFFSET ) +/// Macro converts flow rate to estimate PWM needed to achieve it. // TODO - I added 1.2 gain based on empirical data +#define DIP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO * DIP_MOTOR_RPM_TO_PWM_DC_FACTOR * 1.258 + DIP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. #define DIP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - DIP_PWM_ZERO_OFFSET) * 4000.0 ) @@ -107,22 +110,8 @@ #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_IN_PUMP_ADC_ZERO ) /// Measured dialIn flow is filtered w/ moving average. -#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * DIP_CONTROL_INTERVAL_SEC ) +#define SIZE_OF_ROLLING_AVG 10 -/// Dialysate flow sensor signal strength low alarm persistence. -#define FLOW_SIG_STRGTH_ALARM_PERSIST ( 5 * MS_PER_SECOND ) -#define MIN_FLOW_SIG_STRENGTH 0.9 ///< Minimum flow sensor signal strength (90%). - -/// Dialysate flow fast read timeout alarm persistence. -#define DIALYSATE_FLOW_FAST_READ_TO_PERSIST 100 -/// Dialysate flow slow read timeout alarm persistence. -#define DIALYSATE_FLOW_SLOW_READ_TO_PERSIST ( MS_PER_SECOND * 3 ) -/// Blood flow comm error persistence. -#define DIALYSATE_FLOW_COMM_ERROR_PERSIST MS_PER_SECOND - -#define DFM_SENSOR_CONNECTED_STATUS 0x00 ///< Dialysate flow meter connected status. -#define DFM_SENSOR_PARAM_CORRUPT_STATUS 0x07 ///< Dialysate flow meter NVM parameter corrupt status. - #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. /// Enumeration of dialysate inlet pump states. @@ -166,14 +155,16 @@ static PUMP_CONTROL_MODE_T dialInPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP;///< Currently set dialIn pump control mode. /// Interval (in ms) at which to publish dialIn flow data to CAN bus -static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; +static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; +static U32 dialysateFlowDataFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh dialysate flow data is received static S32 targetDialInFlowRate = 0; ///< Requested dialIn flow rate static OVERRIDE_F32_T measuredDialInFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate inlet flow rate static OVERRIDE_F32_T dialInPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate inlet pump rotor speed static OVERRIDE_F32_T dialInPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate inlet pump motor speed static OVERRIDE_F32_T adcDialInPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate inlet pump motor controller speed static OVERRIDE_F32_T adcDialInPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate inlet pump motor controller current -static OVERRIDE_F32_T dialInFlowSignalStrength = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate flow signal strength (%) + +static U08 lastDialInPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. static U32 dipControlTimerCounter = 0; ///< Determines when to perform control on dialIn flow @@ -191,18 +182,12 @@ static U32 errorDialInRotorSpeedPersistTimerCtr = 0; ///< Persistence timer counter for rotor speed error condition. static U32 errorDialInPumpDirectionPersistTimerCtr = 0; ///< Persistence timer counter for pump direction error condition. -static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< Holds flow samples for a rolling average. +static F64 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< Holds flow samples for a rolling average. static U32 flowReadingsIdx = 0; ///< Index for next sample in rolling average array. -static F32 flowReadingsTotal = 0.0; ///< Rolling total - used to calc average. +static F64 flowReadingsTotal = 0.0; ///< Rolling total - used to calc average. static U32 flowReadingsCount = 0; ///< Number of samples in flow rolling average buffer. static U32 dipCurrErrorDurationCtr = 0; ///< Used for tracking persistence of dip current errors. - -static U08 lastDialysateFlowFastPacketReadCtr = 0; ///< Previous read counter for the dialysate flow fast packets. -static U08 lastDialysateFlowSlowPacketReadCtr = 0; ///< Previous read counter for the dialysate flow slow packets. -static U08 lastDialInPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. -static U08 lastDialysateFlowCommErrorCount = 0; ///< Previous DPi flow sensor comm error count. -static HD_FLOW_SENSORS_CAL_RECORD_T dialysateFlowCalRecord; ///< Dialysate flow sensor calibration record. // ********** private function prototypes ********** @@ -215,16 +200,14 @@ static void releaseDialInPumpStop( void ); static void setDialInPumpDirection( MOTOR_DIR_T dir ); static void publishDialInFlowData( void ); -static void resetDialInFlowMovingAverage( void ); -static void filterDialInFlowReadings( F32 flow ); +static void resetDialInFlowMovingAverage( void ); +static void filterDialInFlowReadings( F64 flow ); static void updateDialInPumpSpeedAndDirectionFromHallSensors( void ); static void checkDialInPumpRotor( void ); static void checkDialInPumpDirection( void ); static void checkDialInPumpSpeeds( void ); -static void checkDialInPumpFlowAgainstSpeed( void ); static void checkDialInPumpMCCurrent( void ); -static void checkDialInFlowSensorSignalStrength( void ); -static BOOL processCalibrationData( void ); +static void checkDialInPumpFlowRate( void ); /*********************************************************************//** * @brief @@ -256,7 +239,6 @@ MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ); // Initialize persistent alarm for flow sensor signal strength too low - initPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_SIGNAL_STRENGTH_TOO_LOW, FLOW_SIG_STRGTH_ALARM_PERSIST, FLOW_SIG_STRGTH_ALARM_PERSIST ); initPersistentAlarm( ALARM_ID_HD_DIAL_IN_FLOW_OUT_OF_RANGE, 0, DIP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST ); } @@ -417,46 +399,38 @@ *************************************************************************/ void execDialInFlowMonitor( void ) { - // Check if a new calibration is available - if ( TRUE == isNewCalibrationRecordAvailable() ) - { - // Get the new calibration data and check its validity - processCalibrationData(); - } - HD_OP_MODE_T opMode = getCurrentOperationMode(); U16 dipRPM = getIntADCReading( INT_ADC_DIAL_IN_PUMP_SPEED ); U16 dipmA = getIntADCReading( INT_ADC_DIAL_IN_PUMP_MOTOR_CURRENT ); U08 fpReadCtr = getFPGADialysateFlowFastPacketReadCounter(); U08 spReadCtr = getFPGADialysateFlowSlowPacketReadCounter(); U08 flowErrorCtr = getFPGADialysateFlowErrorCounter(); U08 flowStatus = getFPGADialysateFlowMeterStatus(); + F64 dipFlow; - F32 fpgaDialysateFlow = getFPGADialysateFlow(); - F32 dipFlow = pow(fpgaDialysateFlow, 4) * dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].fourthOrderCoeff + - pow(fpgaDialysateFlow, 3) * dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].thirdOrderCoeff + - pow(fpgaDialysateFlow, 2) * dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].secondOrderCoeff + - fpgaDialysateFlow * dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].gain + - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].offset; - -#ifndef DISABLE_PUMP_FLOW_CHECKS - if ( flowStatus != DFM_SENSOR_CONNECTED_STATUS ) + // Process new dialysate flow readings + if ( TRUE == getDialysateFlowDataFreshFlag() ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DIALYSATE_FLOW_STATUS_SELF_TEST_FAILURE, (U32)flowStatus ); + dipFlow = getDGDialysateFlowRateLMin() * (F64)ML_PER_LITER; // convert rate to mL/min + filterDialInFlowReadings( dipFlow ); // process the fresh dialysate flow data + dialysateFlowDataFreshStatusCounter = 0; // reset counter } - lastDialysateFlowCommErrorCount = flowErrorCtr; -#endif + else + { // Alarm if not receiving new dialysate flow readings in timely manner + if ( ++dialysateFlowDataFreshStatusCounter > DIP_DIALYSATE_FLOW_DATA_ALARM_THRESHOLD ) + { + filterDialInFlowReadings( 0.0 ); + if ( TRUE == isDGCommunicating() ) + { + activateAlarmNoData( ALARM_ID_HD_DIALYSATE_FLOW_DATA_NOT_RECEIVE ); + } + } + } - // Record flow read counters for next time around - lastDialysateFlowFastPacketReadCtr = fpReadCtr; - lastDialysateFlowSlowPacketReadCtr = spReadCtr; - + // Get latest pump speed and current from motor controller adcDialInPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(dipRPM)) * DIP_SPEED_ADC_TO_RPM_FACTOR; adcDialInPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(dipmA)) * DIP_CURRENT_ADC_TO_MA_FACTOR; - dialInFlowSignalStrength.data = getFPGADialysateFlowSignalStrength(); - - filterDialInFlowReadings( dipFlow ); - + // Calculate dialysate inlet pump motor speed/direction from hall sensor count updateDialInPumpSpeedAndDirectionFromHallSensors(); @@ -469,13 +443,11 @@ checkDialInPumpMCCurrent(); // Check pump speeds and flow checkDialInPumpSpeeds(); - checkDialInPumpFlowAgainstSpeed(); + checkDialInPumpFlowRate(); // Check for home position, zero/low speed checkDialInPumpRotor(); - // Check flow sensor signal strength - checkDialInFlowSensorSignalStrength(); - } - + } + // Publish dialIn flow data on interval publishDialInFlowData(); } @@ -724,52 +696,6 @@ /*********************************************************************//** * @brief - * The processCalibrationData function gets the calibration data and makes - * sure it is valid by checking the calibration date. The calibration date - * should not be 0. - * @details Inputs: none - * @details Outputs: dialysateFlowCalRecord - * @return TRUE if the calibration record is valid, otherwise FALSE - *************************************************************************/ -static BOOL processCalibrationData( void ) -{ - BOOL status = TRUE; - - // Get the calibration record from NVDataMgmt - HD_FLOW_SENSORS_CAL_RECORD_T calData = getHDFlowSensorsCalibrationRecord(); - - // Check if the calibration data that was received from NVDataMgmt is legitimate - // The calibration date item should not be zero. If the calibration date is 0, - // then the dialysate flow sensors data is not stored in the NV memory or it was corrupted. - if ( 0 == calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].calibrationTime ) - { -#ifndef SKIP_CAL_CHECK - activateAlarmNoData( ALARM_ID_HD_DIALYSATE_FLOW_INVALID_CAL_RECORD ); - status = FALSE; -#endif - } - - // The calibration data was valid, update the local copy - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].fourthOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].fourthOrderCoeff; - - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].thirdOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].thirdOrderCoeff; - - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].secondOrderCoeff = - calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].secondOrderCoeff; - - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].gain = - calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].gain; - - dialysateFlowCalRecord.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].offset = - calData.hdFlowSensors[ CAL_DATA_HD_DIALYSATE_FLOW_SENSOR ].offset; - - return status; -} - -/*********************************************************************//** - * @brief * The getTargetDialInFlowRate function gets the current target dialIn flow * rate. * @details Inputs: targetDialInFlowRate @@ -801,26 +727,6 @@ return result; } -/*********************************************************************//** - * @brief - * The getMeasuredDialInFlowSignalStrength function gets the measured dialIn flow - * signal strength. - * @details Inputs: dialInFlowSignalStrength - * @details Outputs: none - * @return the current dialIn flow signal strength (in %). - *************************************************************************/ -F32 getMeasuredDialInFlowSignalStrength( void ) -{ - F32 result = dialInFlowSignalStrength.data; - - if ( OVERRIDE_KEY == dialInFlowSignalStrength.override ) - { - result = dialInFlowSignalStrength.ovData; - } - - return result; -} - /*********************************************************************//** * @brief * The getMeasuredDialInPumpRotorSpeed function gets the measured dialIn flow @@ -907,11 +813,19 @@ * PWM duty cycle percentage. * @details Inputs: dialInPumpPWMDutyCyclePctSet * @details Outputs: none + * @param init Flag indicates whether or not initial PWM duty cycle is wanted * @return the current dialIn pump PWM duty cycle percentage (0..1). *************************************************************************/ -F32 getDialInPumpPWMDutyCyclePct( void ) +F32 getDialInPumpPWMDutyCyclePct( BOOL init ) { - return dialInPumpPWMDutyCyclePctSet; + F32 result = dialInPumpPWMDutyCyclePctSet; + + if ( TRUE == init ) + { + result = dialInPumpPWMDutyCyclePct; + } + + return result; } /*********************************************************************//** @@ -937,8 +851,8 @@ payload.measMCSpd = getMeasuredDialInPumpMCSpeed(); payload.measMCCurr = getMeasuredDialInPumpMCCurrent(); payload.pwmDC = dialInPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; - payload.flowSigStrength = getMeasuredDialInFlowSignalStrength() * FRACTION_TO_PERCENT_FACTOR; - broadcastDialInFlowData( &payload ); + payload.flowSigStrength = 0.0; + broadcastData( MSG_ID_DIALYSATE_FLOW_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( DIALIN_PUMP_STATUS_PAYLOAD_T ) ); dialInFlowDataPublicationTimerCounter = 0; } } @@ -966,9 +880,8 @@ * @details Outputs: flowReadings[], flowReadingsIdx, flowReadingsCount, flowReadingsTotal * @return none *************************************************************************/ -static void filterDialInFlowReadings( F32 flow ) +void filterDialInFlowReadings( F64 flow ) { -#ifndef RAW_FLOW_SENSOR_DATA if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) { flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; @@ -977,10 +890,7 @@ flowReadingsTotal += flow; flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); - measuredDialInFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; -#else - measuredDialInFlowRate.data = flow; -#endif + measuredDialInFlowRate.data = (F32)( flowReadingsTotal / (F64)flowReadingsCount ); } /*********************************************************************//** @@ -1064,12 +974,16 @@ MOTOR_DIR_T dipMCDir, dipDir; U08 dirErrorCnt = getFPGADialInPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS // Check pump direction error count if ( lastDialInPumpDirectionCount != dirErrorCnt ) { lastDialInPumpDirectionCount = dirErrorCnt; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_DIALYSATE_INLET_PUMP ) +#endif } +#endif dipMCDir = ( getMeasuredDialInPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); dipDir = ( getMeasuredDialInPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); @@ -1195,15 +1109,13 @@ /*********************************************************************//** * @brief - * The checkDialInPumpFlowAgainstSpeed function checks the measured dialysate flow - * against the implied flow of the measured pump speed when in treatment mode - * and controlling to target flow. If a sufficient difference persists, a - * flow vs. motor speed check error is triggered. - * @details Inputs: measuredDialInFlowRate, dialInPumpSpeedRPM, errorDialInFlowVsMotorSpeedPersistTimerCtr + * The checkDialInPumpFlowRate function checks the measured dialysate flow + * rate is in range. + * @details Inputs: measuredDialInFlowRate * @details Outputs: alarm may be triggered * @return none *************************************************************************/ -static void checkDialInPumpFlowAgainstSpeed( void ) +static void checkDialInPumpFlowRate( void ) { F32 flow = getMeasuredDialInFlowRate(); @@ -1218,7 +1130,7 @@ // Check only performed while in treatment mode and while we are in control to target state if ( ( MODE_TREA == getCurrentOperationMode() ) && ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) ) { - F32 flow = getMeasuredDialInFlowRate(); + F32 flow = (F32)targetDialInFlowRate; F32 speed = getMeasuredDialInPumpSpeed(); F32 impliedSpeed = ( flow / (F32)ML_PER_LITER ) * DIP_REV_PER_LITER * DIP_GEAR_RATIO; F32 delta = fabs( speed - impliedSpeed ); @@ -1240,7 +1152,7 @@ else { errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; - } + } } /*********************************************************************//** @@ -1295,33 +1207,6 @@ } } -/*********************************************************************//** - * @brief - * The checkDialInFlowSensorSignalStrength function checks the measured - * dialysate flow sensor signal strength is sufficient for accurate flow sensing. - * @details Inputs: - * @details Outputs: - * @return none - *************************************************************************/ -static void checkDialInFlowSensorSignalStrength( void ) -{ -#ifndef DISABLE_PUMP_FLOW_CHECKS - HD_OP_MODE_T opMode = getCurrentOperationMode(); - - // Check flow sensor signal strength when appropriate TODO - in pre-treatment, must be far enough along for fluid to be in tubing - if ( MODE_TREA == opMode || ( MODE_PRET == opMode && FALSE ) ) - { - F32 sigStrength = getMeasuredDialInFlowSignalStrength(); - BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); - - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_FLOW_SIGNAL_STRENGTH_TOO_LOW, outOfRange ) ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_FLOW_SIGNAL_STRENGTH_TOO_LOW, sigStrength, MIN_FLOW_SIG_STRENGTH ); - } - } -#endif -} - /*********************************************************************//** * @brief * The execDialInFlowTest function executes the state machine for the @@ -1332,27 +1217,8 @@ *************************************************************************/ SELF_TEST_STATUS_T execDialInFlowTest( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - U08 const dfmStatus = getFPGADialysateFlowMeterStatus(); + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - if ( DFM_SENSOR_PARAM_CORRUPT_STATUS != dfmStatus ) - { - BOOL calStatus = processCalibrationData(); - - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } - } - else - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DIALYSATE_FLOW_STATUS_SELF_TEST_FAILURE, (U32)dfmStatus ); - } - return result; } @@ -1670,49 +1536,4 @@ return result; } -/*********************************************************************//** - * @brief - * The testSetMeasuredDialInFlowSignalStrengthOverride function overrides the measured - * dialysate flow signal strength. - * @details Inputs: none - * @details Outputs: dialInFlowSignalStrength - * @param value override measured dialysate flow signal strength (in %) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetMeasuredDialInFlowSignalStrengthOverride( F32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInFlowSignalStrength.ovData = value / 100.0; - dialInFlowSignalStrength.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetMeasuredDialInFlowSignalStrengthOverride function resets the override - * of the measured dialysate flow signal strength. - * @details Inputs: none - * @details Outputs: dialInFlowSignalStrength - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetMeasuredDialInFlowSignalStrengthOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInFlowSignalStrength.override = OVERRIDE_RESET; - dialInFlowSignalStrength.ovData = dialInFlowSignalStrength.ovInitData; - } - - return result; -} - /**@}*/ Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -15,7 +15,6 @@ * ***************************************************************************/ - #include "etpwm.h" #include "Fans.h" @@ -494,7 +493,7 @@ fansData.fansTargetRPM = fansStatus.targetRPM; fansData.fanInlet1RPM = getMeasuredFanRPM( FAN_INLET_1 ); - broadcastFansData( &fansData ); + broadcastData( MSG_ID_HD_FANS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&fansData, sizeof( FANS_DATA_T ) ); fansPublishCounter = 0; } Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -24,7 +24,8 @@ #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Temperatures.h" -#include "Timers.h" +#include "Timers.h" +#include "Valves.h" /** * @addtogroup PressureOcclusion @@ -77,6 +78,13 @@ static const U32 EMPTY_SALINE_BAG_PERSISTENCE = ( 250 / TASK_GENERAL_INTERVAL ); ///< Time that saline bag looks empty before saying it is empty. #define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. + +/// Measured arterial pressure is filtered w/ 10 second moving average for pressure compensation of flow. +#define SIZE_OF_LONG_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) +/// Measured arterial pressure is filtered w/ 1 second moving average for inline pressure. +#define SIZE_OF_SHORT_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) +/// Measured venous pressure is filtered w/ 1 second moving average for inline pressure and unfiltered for occlusion detection. +#define SIZE_OF_SHORT_VEN_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States @@ -102,27 +110,42 @@ /// Interval (in ms) at which to publish pressure/occlusion data to CAN bus. static OVERRIDE_U32_T presOcclDataPublishInterval = { PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL, 0, 0 }; -static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure. +static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure. +static OVERRIDE_F32_T arterialPressureOffset = {0.0, 0.0, 0.0, 0 }; ///< Calculated arterial pressure offset. static OVERRIDE_F32_T venousPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured venous pressure. static OVERRIDE_U32_T bloodPumpOcclusion = {0, 0, 0, 0 }; ///< Measured blood pump occlusion pressure. -static OVERRIDE_U32_T dialInPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate inlet pump occlusion pressure. -static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate outlet pump occlusion pressure. +static F32 longFilteredArterialPressure; ///< Measured arterial pressure after long (10 s) filter. +static F32 shortFilteredArterialPressure; ///< Measured arterial pressure after short (1 s) filter. +static F32 shortFilteredVenousPressure; ///< Measured venous pressure after short (1 s) filter. +#ifndef DISABLE_PRESSURE_CHECKS static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. -static U32 dialInPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate inlet pump occlusion reading taken after cartridge install. -static U32 dialOutPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate outlet pump occlusion reading taken after cartridge install. +#endif static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. static U08 lastArterialPressureReadCtr; ///< Previous arterial pressure sensor read count. static U08 lastVenousPressureReadCtr; ///< Previous venous pressure sensor read count. +#ifndef DISABLE_PRESSURE_CHECKS static U08 lastBPOcclReadCtr; ///< Previous BP occlusion sensor read count. -static U08 lastDPiOcclReadCtr; ///< Previous DPi occlusion sensor read count. -static U08 lastDPoOcclReadCtr; ///< Previous DPo occlusion sensor read count. static U08 lastBPErrorCtr; ///< Previous BP error count. -static U08 lastDPIErrorCtr; ///< Previous DPi error count. -static U08 lastDPOErrorCtr; ///< Previous DPo error count. +#endif +static F32 artPressureReadingsLong[ SIZE_OF_LONG_ART_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 artPressureReadingsLongIdx = 0; ///< Index for next sample in rolling average array. +static F32 artPressureReadingsLongTotal = 0.0; ///< Rolling total - used to calc average. +static U32 artPressureReadingsLongCount = 0; ///< Number of samples in flow rolling average buffer. + +static F32 artPressureReadingsShort[ SIZE_OF_SHORT_ART_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 artPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. +static F32 artPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. +static U32 artPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. + +static F32 venPressureReadingsShort[ SIZE_OF_SHORT_VEN_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. +static U32 venPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. +static F32 venPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. +static U32 venPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. + // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclContReadState( void ); @@ -132,6 +155,7 @@ static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); +static void filterInlinePressureReadings( F32 artPres, F32 venPres ); /*********************************************************************//** * @brief @@ -143,10 +167,10 @@ void initPresOccl( void ) { // Initialize persistent pressure alarms - initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_LOW, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_LOW, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); - initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_HIGH, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_LOW, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_HIGH, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_SENSOR_TEMP_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); @@ -158,35 +182,34 @@ lastArterialPressureReadCtr = 0; lastVenousPressureReadCtr = 0; +#ifndef DISABLE_PRESSURE_CHECKS lastBPOcclReadCtr = 0; - lastDPiOcclReadCtr = 0; - lastDPoOcclReadCtr = 0; lastBPErrorCtr = 0; - lastDPIErrorCtr = 0; - lastDPOErrorCtr = 0; +#endif + longFilteredArterialPressure = 0.0; + shortFilteredArterialPressure = 0.0; + shortFilteredVenousPressure = 0.0; + +#ifndef DISABLE_PRESSURE_CHECKS bloodPumpOcclusionAfterCartridgeInstall = 0; - dialInPumpOcclusionAfterCartridgeInstall = 0; - dialOutPumpOcclusionAfterCartridgeInstall = 0; +#endif } /*********************************************************************//** * @brief * The isCartridgeLoaded function determines whether a cartridge has been - * properly loaded by looking at the 3 occlusion pressure sensors. - * @details Inputs: occlusion pressures for the pumps + * properly loaded by looking at the BP occlusion pressure sensor. + * @details Inputs: BP occlusion pressure * @details Outputs: none - * @return TRUE if all 3 occlusion sensors read above loaded threshold, FALSE if not. + * @return TRUE if BP occlusion sensor reads above loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeLoaded( void ) { BOOL result = FALSE; U32 bpOccl = getMeasuredBloodPumpOcclusion(); - U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); - if ( ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) && ( diOccl >= CARTRIDGE_LOADED_THRESHOLD ) && - ( doOccl >= CARTRIDGE_LOADED_THRESHOLD ) ) + if ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) { result = TRUE; } @@ -197,18 +220,16 @@ /*********************************************************************//** * @brief * The isCartridgeUnloaded function determines if a cartridge has been - * unloaded by looking at the 3 occlusion pressure sensors. - * @details Inputs: occlusion pressures for the pumps + * unloaded by looking at the BP occlusion pressure sensor. + * @details Inputs: BP occlusion pressure * @details Outputs: none - * @return TRUE if all 3 occlusion sensors read below loaded threshold, FALSE if not. + * @return TRUE if occlusion sensor are below loaded threshold, FALSE if not. *************************************************************************/ BOOL isCartridgeUnloaded( void ) { - BOOL const bpOcclBelowLoadedThreshold = getMeasuredBloodPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; - BOOL const diOcclBelowLoadedThreshold = getMeasuredDialInPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; - BOOL const doOcclBelowLoadedThreshold = getMeasuredDialOutPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD; + BOOL const bpOcclBelowLoadedThreshold = ( getMeasuredBloodPumpOcclusion() <= CARTRIDGE_LOADED_THRESHOLD ? TRUE : FALSE ); - return ( bpOcclBelowLoadedThreshold && diOcclBelowLoadedThreshold && doOcclBelowLoadedThreshold ); + return bpOcclBelowLoadedThreshold; } /*********************************************************************//** @@ -242,18 +263,18 @@ /*********************************************************************//** * @brief - * The setOcclusionInstallLevels function sets the occlusion sensor levels + * The setOcclusionInstallLevel function sets the occlusion sensor level * for an installed cartridge. This function should be called after a new * cartridge is installed. - * @details Inputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion - * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall, dialInPumpOcclusionAfterCartridgeInstall, dialOutPumpOcclusionAfterCartridgeInstall + * @details Inputs: bloodPumpOcclusion + * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall * @return none *************************************************************************/ -void setOcclusionInstallLevels( void ) +void setOcclusionInstallLevel( void ) { +#ifndef DISABLE_PRESSURE_CHECKS bloodPumpOcclusionAfterCartridgeInstall = getMeasuredBloodPumpOcclusion(); - dialInPumpOcclusionAfterCartridgeInstall = getMeasuredDialInPumpOcclusion(); - dialOutPumpOcclusionAfterCartridgeInstall = getMeasuredDialOutPumpOcclusion(); +#endif } /*********************************************************************//** @@ -333,8 +354,6 @@ F32 venTemp = getTemperatureValue( TEMPSENSOR_VENOUS_PRESSURE_SENSOR ); U08 venReadCtr = getFPGAVenousPressureReadCounter(); - // TODO - any filtering required??? - // Convert arterial pressure to mmHg if no fault if ( 0 == artPresAlarm ) { @@ -344,7 +363,15 @@ // Check for stale arterial pressure reading if ( FALSE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr || artErrorCtr > 0 ) ) ) { - arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); +#ifndef PBA_ESTIMATION + arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ) + getF32OverrideValue( &arterialPressureOffset ); +#else + // TODO - temporary test code - remove later + F32 artPres = -0.1146 * getMeasuredBloodPumpMCSpeed(); + artPres = MAX(-200.0,artPres); + artPres = MIN(0,artPres); + arterialPressure.data = artPres; +#endif } else { @@ -388,6 +415,9 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_VENOUS_PRESSURE_SENSOR_FAULT, venTemp ) } + + // Filter inline pressure readings + filterInlinePressureReadings( getMeasuredArterialPressure(), getMeasuredVenousPressure() ); } /*********************************************************************//** @@ -400,54 +430,30 @@ static void convertOcclusionPressures( void ) { U08 bpReadCtr = getFPGABloodPumpOcclusionReadCounter(); - U08 dpiReadCtr = getFPGADialInPumpOcclusionReadCounter(); - U08 dpoReadCtr = getFPGADialOutPumpOcclusionReadCounter(); U08 bpErrorCtr = getFPGABloodPumpOcclusionErrorCounter(); - U08 dpiErrorCtr = getFPGADialInPumpOcclusionErrorCounter(); - U08 dpoErrorCtr = getFPGADialOutPumpOcclusionErrorCounter(); #ifndef DISABLE_PRESSURE_CHECKS // Check for sensor errors if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, ( bpErrorCtr != lastBPErrorCtr ) ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, (U32)bpErrorCtr ) } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, ( dpiErrorCtr != lastDPIErrorCtr ) ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, (U32)dpiErrorCtr ) - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, ( dpoErrorCtr != lastDPOErrorCtr ) ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, (U32)dpoErrorCtr ) - } // Check for stale occlusion reads if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( bpReadCtr == lastBPOcclReadCtr ) ) ) { activateAlarmNoData( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( dpiReadCtr == lastDPiOcclReadCtr ) ) ) - { - activateAlarmNoData( ALARM_ID_HD_DPI_OCCLUSON_READ_TIMEOUT_ERROR ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, ( dpoReadCtr == lastDPoOcclReadCtr ) ) ) - { - activateAlarmNoData( ALARM_ID_HD_DPO_OCCLUSION_READ_TIMEOUT_ERROR ); - } #endif // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); - dialInPumpOcclusion.data = (U32)getFPGADialInPumpOcclusion(); - dialOutPumpOcclusion.data = (U32)getFPGADialOutPumpOcclusion(); +#ifndef DISABLE_PRESSURE_CHECKS // Record occlusion read and error counters for next time around lastBPOcclReadCtr = bpReadCtr; - lastDPiOcclReadCtr = dpiReadCtr; - lastDPoOcclReadCtr = dpoReadCtr; lastBPErrorCtr = bpErrorCtr; - lastDPIErrorCtr = dpiErrorCtr; - lastDPOErrorCtr = dpoErrorCtr; +#endif } /*********************************************************************//** @@ -460,7 +466,7 @@ *************************************************************************/ static void checkArterialPressureInRange( void ) { - F32 artPres = getMeasuredArterialPressure(); + F32 artPres = getFilteredArterialPressure(); #ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is in range @@ -469,37 +475,30 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, artPres ); } -#endif // Check arterial pressure during treatment mode - if ( MODE_TREA == getCurrentOperationMode() ) + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); -#ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is within user set alarm limits if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) - { - clearAlarmCondition( ALARM_ID_ARTERIAL_PRESSURE_LOW ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) - { - clearAlarmCondition( ALARM_ID_ARTERIAL_PRESSURE_HIGH ); - } -#endif } + else + { // Reset persistence if alarm is out of scope + isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, FALSE ); + } +#endif } /*********************************************************************//** @@ -512,7 +511,7 @@ *************************************************************************/ static void checkVenousPressureInRange( void ) { - F32 venPres = getMeasuredVenousPressure(); + F32 venPres = getFilteredVenousPressure(); #ifndef DISABLE_PRESSURE_CHECKS // Check arterial pressure is in range @@ -521,36 +520,37 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); } -#endif // Check arterial pressure during treatment mode - if ( MODE_TREA == getCurrentOperationMode() ) + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( getTreatmentState() <= TREATMENT_DIALYSIS_STATE ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); -#ifndef DISABLE_PRESSURE_CHECKS - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + // Cannot monitor for low venous pressure while venting air trap + if ( getValveAirTrapStatus() != STATE_OPEN ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + } } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) - { - clearAlarmCondition( ALARM_ID_VENOUS_PRESSURE_LOW ); + else + { // clear persistence if air trap valve is open + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); } if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) - { - clearAlarmCondition( ALARM_ID_VENOUS_PRESSURE_HIGH ); - } -#endif } + else + { // Reset persistence if alarm is out of scope + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, FALSE ); + } +#endif } /*********************************************************************//** @@ -564,52 +564,24 @@ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); - U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); #ifndef DISABLE_PRESSURE_CHECKS - // Range check occlusion sensors + // Range check occlusion sensor if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl < MIN_OCCLUSION_COUNTS ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl < MIN_OCCLUSION_COUNTS ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl ); - } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl < MIN_OCCLUSION_COUNTS ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl ); - } - // Check for occlusions + // Check for occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { signalBloodPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + //SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) } else if ( bpOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { - clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); + //clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); } - if ( diOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) - { - signalDialInPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) - } - else if ( diOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) - { - clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_IN_PUMP ); - } - if ( doOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) - { - signalDialOutPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) - } - else if ( doOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) - { - clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP ); - } #endif } @@ -631,6 +603,30 @@ return result; } + +/*********************************************************************//** + * @brief + * The getFilteredArterialPressure function gets the current filtered arterial pressure. + * @details Inputs: shortFilteredArterialPressure + * @details Outputs: none + * @return the current filtered arterial pressure (in mmHg). + *************************************************************************/ +F32 getFilteredArterialPressure( void ) +{ + return shortFilteredArterialPressure; +} + +/*********************************************************************//** + * @brief + * The getLongFilteredArterialPressure function gets the current long filtered arterial pressure. + * @details Inputs: longFilteredArterialPressure + * @details Outputs: none + * @return the current long filtered arterial pressure (in mmHg). + *************************************************************************/ +F32 getLongFilteredArterialPressure( void ) +{ + return longFilteredArterialPressure; +} /*********************************************************************//** * @brief @@ -650,6 +646,18 @@ return result; } + +/*********************************************************************//** + * @brief + * The getFilteredVenousPressure function gets the measured filtered venous pressure. + * @details Inputs: shortFilteredVenousPressure + * @details Outputs: none + * @return the current filtered venous pressure (in mmHg). + *************************************************************************/ +F32 getFilteredVenousPressure( void ) +{ + return shortFilteredVenousPressure; +} /*********************************************************************//** * @brief @@ -671,44 +679,53 @@ return result; } -/*********************************************************************//** - * @brief - * The getMeasuredDialInPumpOcclusion function gets the measured dialysate - * inlet pump occlusion pressure. - * @details Inputs: dialInPumpOcclusion - * @details Outputs: none - * @return the current dialysis inlet pump occlusion pressure (in mmHg). - *************************************************************************/ -U32 getMeasuredDialInPumpOcclusion( void ) +/*********************************************************************//** + * @brief + * The filterInlinePressureReadings function adds a new arterial and venous + * pressure sample to the filters. + * @details Inputs: none + * @details Outputs: artPressureReadingsLong[], artPressureReadingsLongIdx, artPressureReadingsLongTotal, artPressureReadingsLongCount, + * artPressureReadingsShort, artPressureReadingsShortIdx, artPressureReadingsShortTotal, artPressureReadingsShortCount, + * venPressureReadingsShort, venPressureReadingsShortIdx, venPressureReadingsShortTotal, venPressureReadingsShortCount, + * longFilteredArterialPressure, shortFilteredArterialPressure, shortFilteredVenousPressure + * @param artPres newest arterial pressure sample to add to filters + * @param venPres newest venous pressure sample to add to filter + * @return none + *************************************************************************/ +static void filterInlinePressureReadings( F32 artPres, F32 venPres ) { - U32 result = dialInPumpOcclusion.data; - - if ( OVERRIDE_KEY == dialInPumpOcclusion.override ) + // Long filter for arterial pressure. + if ( artPressureReadingsLongCount >= SIZE_OF_LONG_ART_ROLLING_AVG ) { - result = dialInPumpOcclusion.ovData; + artPressureReadingsLongTotal -= artPressureReadingsLong[ artPressureReadingsLongIdx ]; } + artPressureReadingsLong[ artPressureReadingsLongIdx ] = artPres; + artPressureReadingsLongTotal += artPres; + artPressureReadingsLongIdx = INC_WRAP( artPressureReadingsLongIdx, 0, SIZE_OF_LONG_ART_ROLLING_AVG - 1 ); + artPressureReadingsLongCount = INC_CAP( artPressureReadingsLongCount, SIZE_OF_LONG_ART_ROLLING_AVG ); + longFilteredArterialPressure = artPressureReadingsLongTotal / (F32)artPressureReadingsLongCount; - return result; -} - -/*********************************************************************//** - * @brief - * The getMeasuredDialOutPumpOcclusion function gets the measured dialysate - * outlet pump occlusion pressure. - * @details Inputs: dialOutPumpOcclusion - * @details Outputs: none - * @return the current dialysis outlet pump occlusion pressure (in mmHg). - *************************************************************************/ -U32 getMeasuredDialOutPumpOcclusion( void ) -{ - U32 result = dialOutPumpOcclusion.data; - - if ( OVERRIDE_KEY == dialOutPumpOcclusion.override ) + // Short filter for arterial pressure. + if ( artPressureReadingsShortCount >= SIZE_OF_SHORT_ART_ROLLING_AVG ) { - result = dialOutPumpOcclusion.ovData; + artPressureReadingsShortTotal -= artPressureReadingsShort[ artPressureReadingsShortIdx ]; } + artPressureReadingsShort[ artPressureReadingsShortIdx ] = artPres; + artPressureReadingsShortTotal += artPres; + artPressureReadingsShortIdx = INC_WRAP( artPressureReadingsShortIdx, 0, SIZE_OF_SHORT_ART_ROLLING_AVG - 1 ); + artPressureReadingsShortCount = INC_CAP( artPressureReadingsShortCount, SIZE_OF_SHORT_ART_ROLLING_AVG ); + shortFilteredArterialPressure = artPressureReadingsShortTotal / (F32)artPressureReadingsShortCount; - return result; + // Short filter for venous pressure. + if ( venPressureReadingsShortCount >= SIZE_OF_SHORT_VEN_ROLLING_AVG ) + { + venPressureReadingsShortTotal -= venPressureReadingsShort[ venPressureReadingsShortIdx ]; + } + venPressureReadingsShort[ venPressureReadingsShortIdx ] = venPres; + venPressureReadingsShortTotal += venPres; + venPressureReadingsShortIdx = INC_WRAP( venPressureReadingsShortIdx, 0, SIZE_OF_SHORT_VEN_ROLLING_AVG - 1 ); + venPressureReadingsShortCount = INC_CAP( artPressureReadingsShortCount, SIZE_OF_SHORT_VEN_ROLLING_AVG ); + shortFilteredVenousPressure = venPressureReadingsShortTotal / (F32)venPressureReadingsShortCount; } /*********************************************************************//** @@ -726,13 +743,13 @@ { PRESSURE_OCCLUSION_DATA_T data; - data.arterialPressure = getMeasuredArterialPressure(); - data.venousPressure = getMeasuredVenousPressure(); + data.arterialPressure = shortFilteredArterialPressure; + data.venousPressure = shortFilteredVenousPressure; data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); - data.diPumpOcclusion = getMeasuredDialInPumpOcclusion(); - data.doPumpOcclusion = getMeasuredDialOutPumpOcclusion(); + data.diPumpOcclusion = 0; // TODO - remove unused fields + data.doPumpOcclusion = 0; - broadcastPresOcclData( data ); + broadcastData( MSG_ID_PRESSURE_OCCLUSION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); presOcclDataPublicationTimerCounter = 0; } } @@ -748,26 +765,14 @@ { #ifndef DISABLE_PRESSURE_CHECKS U32 const bpPressure = getMeasuredBloodPumpOcclusion(); - U32 const dialysateInPressure = getMeasuredDialInPumpOcclusion(); - U32 const dialysateOutPressure = getMeasuredDialOutPumpOcclusion(); - F32 const arterialPressure = getMeasuredArterialPressure(); - F32 const venousPressure = getMeasuredVenousPressure(); + F32 const arterialPressure = getFilteredArterialPressure(); + F32 const venousPressure = getFilteredVenousPressure(); if ( bpPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SELF_TEST_FAILURE, bpPressure ); } - if ( dialysateInPressure > CARTRIDGE_LOADED_THRESHOLD ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DIP_OCCLUSION_SELF_TEST_FAILURE, dialysateInPressure ); - } - - if ( dialysateOutPressure > CARTRIDGE_LOADED_THRESHOLD ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DOP_OCCLUSION_SELF_TEST_FAILURE, dialysateOutPressure ); - } - if ( ( arterialPressure <= ARTERIAL_PRESSURE_SELF_TEST_MIN ) || ( arterialPressure >= ARTERIAL_PRESSURE_SELF_TEST_MAX ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_SELF_TEST_FAILURE, arterialPressure ); @@ -793,36 +798,12 @@ #ifndef DISABLE_OCCLUSION_SELF_TEST U32 const bpPressure = getMeasuredBloodPumpOcclusion(); - U32 const dialysateInPressure = getMeasuredDialInPumpOcclusion(); - U32 const dialysateOutPressure = getMeasuredDialOutPumpOcclusion(); if ( ( bpPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( bpPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) { + activateAlarmNoData( ALARM_ID_NO_CARTRIDGE_LOADED ); result = SELF_TEST_STATUS_FAILED; } - - if ( ( dialysateInPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( dialysateInPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) - { - result = SELF_TEST_STATUS_FAILED; - } - - if ( ( dialysateOutPressure <= CARTRIDGE_LOADED_THRESHOLD ) || ( dialysateOutPressure >= OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX ) ) - { - result = SELF_TEST_STATUS_FAILED; - } - - if ( SELF_TEST_STATUS_FAILED == result ) - { - if ( ( bpPressure <= CARTRIDGE_LOADED_THRESHOLD ) && ( dialysateInPressure <= CARTRIDGE_LOADED_THRESHOLD ) && - ( dialysateOutPressure <= CARTRIDGE_LOADED_THRESHOLD ) ) - { - activateAlarmNoData( ALARM_ID_NO_CARTRIDGE_LOADED ); - } - else - { - activateAlarmNoData( ALARM_ID_CARTRIDGE_INSTALLED_IMPROPERLY ); - } - } #endif return result; @@ -1013,96 +994,51 @@ } return result; -} +} + +/*********************************************************************//** + * @brief + * The testSetBloodPumpOcclusionOverride function overrides the arterial + * pressure offset. + * @details Inputs: none + * @details Outputs: arterialPressureOffset + * @param value override arterial pressure offset with + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetArterialPressureOffsetOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + arterialPressureOffset.ovData = value; + arterialPressureOffset.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetArterialPressureOffsetOverride function resets the override of the + * arterial pressure offset. + * @details Inputs: none + * @details Outputs: arterialPressureOffset + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetArterialPressureOffsetOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + arterialPressureOffset.override = OVERRIDE_RESET; + arterialPressureOffset.ovData = arterialPressureOffset.ovInitData; + } + + return result; +} -/*********************************************************************//** - * @brief - * The testSetDialInPumpOcclusionOverride function overrides the measured - * dialysate inlet pump occlusion pressure.n - * @details Inputs: none - * @details Outputs: dialInPumpOcclusion - * @param value override measured dialysate inlet pump occlusion pressure - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDialInPumpOcclusionOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInPumpOcclusion.ovData = value; - dialInPumpOcclusion.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetDialInPumpOcclusionOverride function resets the override of the - * measured dialysate inlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialInPumpOcclusion - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDialInPumpOcclusionOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialInPumpOcclusion.override = OVERRIDE_RESET; - dialInPumpOcclusion.ovData = dialInPumpOcclusion.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetDialOutPumpOcclusionOverride function overrides the measured - * dialysate outlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialOutPumpOcclusion - * @param value override measured dialysate outlet pump occlusion pressure - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDialOutPumpOcclusionOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialOutPumpOcclusion.ovData = value; - dialOutPumpOcclusion.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetDialOutPumpOcclusionOverride function resets the override of the - * measured dialysate outlet pump occlusion pressure. - * @details Inputs: none - * @details Outputs: dialOutPumpOcclusion - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDialOutPumpOcclusionOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - dialOutPumpOcclusion.override = OVERRIDE_RESET; - dialOutPumpOcclusion.ovData = dialOutPumpOcclusion.ovInitData; - } - - return result; -} - /**@}*/ Index: firmware/App/Controllers/Temperatures.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2021 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. @@ -15,7 +15,6 @@ * ***************************************************************************/ - #include // For temperature calculations #include "FPGA.h" @@ -419,7 +418,7 @@ sensorsData.pbaADCTempSensor = getTemperatureValue( TEMPSENSOR_PBA_ADC_SENSOR ); // Broadcast the temperatures data - broadcastTemperaturesData( &sensorsData ); + broadcastData( MSG_ID_HD_TEMPERATURES_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&sensorsData, sizeof( TEMPERATURES_DATA_T ) ); // Reset the counter dataPublishCounter = 0; Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -868,8 +868,6 @@ if ( ( TRUE == isAlarmActive( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT ) ) && ( VALVE_POSITION_C_CLOSE == valvesStatus[ valve ].commandedPosition ) ) { activateSafetyShutdown(); - // Set the alarm - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT, (U32)valve ); } } // Check if the valve is close to the temporary target position and if it is, assign the next target position @@ -1150,8 +1148,8 @@ static void getAndMonitorValvesCurrentFPGAPosition( void ) { VALVE_T valve; - S16 currentPostion = 0; - S16 commandedPoistion = 0; + S16 currentPosition = 0; + S16 commandedPosition = 0; VALVE_POSITION_T commandedPositionEnum; // Get the position of the valves and update the structure of each valve @@ -1169,9 +1167,9 @@ { U32 maxDeviation = MAX_DEVIATION_FROM_TARGET_IN_COUNTS; - currentPostion = getValvePositionCounts( valve ); + currentPosition = getValvePositionCounts( valve ); commandedPositionEnum = valvesStatus[ valve ].commandedPosition; - commandedPoistion = valvesStatus[ valve ].positions[ commandedPositionEnum ]; + commandedPosition = valvesStatus[ valve ].positions[ commandedPositionEnum ]; // If the current position is B, current relaxation requires looser range check if ( VALVE_POSITION_B_OPEN == commandedPositionEnum ) @@ -1182,18 +1180,18 @@ // Check if the current position has deviated from the position it is supposed to be in // For more than a certain amount of time. If it has, raise an alarm // Absolute value is used for comparison to cover +/- from the commanded position - if ( abs( currentPostion - commandedPoistion ) > maxDeviation ) + if ( abs( currentPosition - commandedPosition ) > maxDeviation ) { valvesStatus[ valve ].positionOutOfRangeCounter++; } if ( valvesStatus[ valve ].positionOutOfRangeCounter > MAX_POS_DEVIATION_TIME_INTERVAL_COUNTER ) { #ifndef DISABLE_VALVE_ALARMS - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_POSITION_OUT_OF_RANGE, (U32)valve, currentPostion ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_VALVE_POSITION_OUT_OF_RANGE, (U32)valve, currentPosition ); #endif } - else if ( abs( currentPostion - commandedPoistion ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS && + else if ( abs( currentPosition - commandedPosition ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS && valvesStatus[ valve ].positionOutOfRangeCounter > 0 ) { valvesStatus[ valve ].positionOutOfRangeCounter = 0; @@ -1218,6 +1216,7 @@ if ( ++valvesStatus[ valve ].dataPublishCounter >= getU32OverrideValue( &valvesDataPublishInterval ) ) { HD_VALVE_DATA_T valveData; + valveData.valveID = (U32)valve; valveData.state = (U32)valvesStatus[ valve ].execState; valveData.currentPosID = (U32)getValvePosition( valve ); Index: firmware/App/HDCommon.h =================================================================== diff -u -r86ed81916cec970276aa55774936690f2892e4e0 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 86ed81916cec970276aa55774936690f2892e4e0) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -10,8 +10,8 @@ * @author (last) Dara Navaei * @date (last) 14-Oct-2021 * -* @author (original) Sean -* @date (original) 27-Feb-2020 +* @author (original) Sean +* @date (original) 27-Feb-2020 * ***************************************************************************/ @@ -24,9 +24,10 @@ #define HD_VERSION_MAJOR 0 #define HD_VERSION_MINOR 6 -#define HD_VERSION_MICRO 5 -#define HD_VERSION_BUILD 24 +#define HD_VERSION_MICRO 0 +#define HD_VERSION_BUILD 109 + // ********** development build switches ********** // TODO - remove build switches before release @@ -37,29 +38,32 @@ // #define RUN_WITHOUT_DG 1 // Run HD w/o DG // #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 DISABLE_ALARM_AUDIO 1 // Disable alarm audio + #define DISABLE_ALARM_AUDIO 1 // Disable alarm audio // #define SKIP_POST 1 // Skip POST tests - all pass // #define DONT_SKIP_NV_POST 1 // Do not skip NV Data POST -// #define USE_LIBRARY_TIME_FUNCTIONS 1 // Use the C library functions mktime() and gmtime() for epoch<=>date conversions #define DISABLE_AIR_TRAP_LEVELING_ALARM 1 // Disable air trap level control alarms // #define DISABLE_3WAY_VALVES 1 // Disable 3-way valves // #define TST_3WAY_VALVES_ALWAYS_OPEN 1 // After POST and homing, open all 4 valves // #define DISABLE_ACCELS 1 // Disable accelerometer POST and monitoring // #define DISABLE_CRC_ERROR 1 // Do not error on bad CRC for CAN messages -// #define DISABLE_ACK_ERRORS 1 // Do not error on failure of other node(s) to ACK a message + #define DISABLE_ACK_ERRORS 1 // Do not error on failure of other node(s) to ACK a message +// #define USE_FMD_FLOW_SENSOR 1 // Use FMD flow sensor (on HD) instead of FMD on DG +// #define RUN_BP_OPEN_LOOP 1 // Run blood pump in open loop mode +// #define RUN_DPI_OPEN_LOOP 1 // Run dialysate inlet pump in open loop mode + #define WORN_OUT_CARTRIDGE 1 // Running with an old worn out cartridge (max wear) +// #define PBA_ESTIMATION 1 // Estimate arterial pressure rather than look at PBA sensor #define DISABLE_MOTOR_CURRENT_CHECKS 1 // Do not error on HD pump current checks -// #define DISABLE_PUMP_FLOW_CHECKS 1 // Do not error on HD pump flow checks -// #define DISABLE_PUMP_SPEED_CHECKS 1 // Do not error on HD pump speed checks -// #define DISABLE_PUMP_DIRECTION_CHECKS 1 // Do not error on HD pump direction checks + #define DISABLE_PUMP_FLOW_CHECKS 1 // Do not error on HD pump flow checks + #define DISABLE_PUMP_SPEED_CHECKS 1 // Do not error on HD pump speed checks + #define DISABLE_PUMP_DIRECTION_CHECKS 1 // Do not error on HD pump direction checks #define DISABLE_SYRINGE_PUMP 1 // Disable syringe pump functionality #define ALWAYS_ALLOW_SYRINGE_PUMP_CMDS 1 // Allow syringe pump commands at any time except when pump is busy - #define DISABLE_PRESSURE_CHECKS 1 // Do not error on HD pressure checks -// #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks + #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks #define DISABLE_DIALYSATE_TEMP_CHECK 1 // Disable dialysate temperature check -// #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position - #define SKIP_CAL_CHECK 1 + #define DISABLE_PRESSURE_CHECKS 1 // Do not error on HD pressure checks + #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position + #define SKIP_CAL_CHECK 1 // // #define RUN_PUMPS_OPEN_LOOP 1 // BP and DPi pumps will be run open loop (no flow sensor feedback) -// #define RAW_FLOW_SENSOR_DATA 1 // Test build will not filter flow sensor data // #define READ_FPGA_ASYNC_DATA 1 // Test build reads non-priority register page every other time // #define EMC_TEST_BUILD 1 // EMC test build - HD/DG run separately but connected, HD pumps toggle on/off w/ stop button #define ALARMS_DEBUG 1 // Triggered alarms sent to debug UART @@ -71,13 +75,14 @@ // #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters #define DISABLE_VOLTAGE_MONITOR 1 // Disable voltage monitoring/alarms #define ALLOW_1_MIN_TREATMENT_DURATION 1 // Allow user to change treatment duration to as low as 1 minute - #define DISABLE_SYRINGE_PUMP_ALARMS 1 // Disable some syringe pump alarms that are triggering intermittently -// #define NO_PUMP_FLOW_LIMITS 1 // Allow any commanded flow rate for peristaltic pumps +// #define DISABLE_SYRINGE_PUMP_ALARMS 1 // Disable some syringe pump alarms that are triggering intermittently + #define NO_PUMP_FLOW_LIMITS 1 // Allow any commanded flow rate for peristaltic pumps #define DISABLE_BUBBLE_ALARMS 1 // Disable bubble alarms -// #define DISABLE_UI_POST_TEST 1 // Disable the UI POST + #define DISABLE_UI_POST_TEST 1 // Disable the UI POST + #define DISABLE_UI_COMM_TO_ALARM 1 // Disable UI comm timeouts // Skip Pre-Treatment and get to treatment as soon as possible -// #define SKIP_UI_INTERACTION 1 // Skip UI interaction. + #define SKIP_UI_INTERACTION 1 // Skip UI interaction. #define SKIP_SAMPLE_WATER 1 // Skip pre-treatment sample water #define SKIP_CONSUMABLE_TESTS 1 // Skip pre-treatment consumable Self-tests #define SKIP_DRY_SELF_TESTS 1 // Skip pre-treatment dry self-tests Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -131,6 +131,7 @@ { case POST_STATE_START: sendUIVersionRequest(); + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_STARTUP, 0, 0 ) postState = POST_STATE_FW_INTEGRITY; break; @@ -140,8 +141,14 @@ break; case POST_STATE_AC: - testStatus = SELF_TEST_STATUS_PASSED; // TODO add the actual function - postState = handlePOSTStatus( testStatus ); + if ( getMonitoredLineLevel( MONITORED_LINE_24V ) < MIN_24V_MEASURED_FOR_AC ) + { + initiatePowerOff(); + } + else + { + postState = POST_STATE_WATCHDOG; + } break; case POST_STATE_WATCHDOG: Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -57,7 +57,7 @@ #define MSG_NOT_ACKED_TIMEOUT_MS 150 ///< Maximum time for a Denali message that requires ACK to be ACK'd #define MSG_NOT_ACKED_MAX_RETRIES 3 ///< 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 Delanli messages that can be pending ACK at any given time +#define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time #pragma pack(push, 1) @@ -922,8 +922,10 @@ if ( TRUE == uiDidCommunicate ) { if ( TRUE == didTimeout( timeOfLastUICheckIn, UI_COMM_TIMEOUT_IN_MS ) ) - { - activateAlarmNoData( ALARM_ID_UI_COMM_TIMEOUT ); + { +#ifndef DISABLE_UI_COMM_TO_ALARM + activateAlarmNoData( ALARM_ID_UI_COMM_TIMEOUT ); +#endif } if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) @@ -1146,18 +1148,10 @@ handleDGTemperatureData( message ); break; - case MSG_ID_RO_PUMP_DATA: - handleROPumpData( message ); + case MSG_ID_DG_DIALYSATE_FLOW_METER_DATA: + handleDialysateFlowData( message ); break; - case MSG_ID_DG_PRESSURES_DATA: - handleDGPressuresData( message ); - break; - - case MSG_ID_DRAIN_PUMP_DATA: - handleDrainPumpData( message ); - break; - case MSG_ID_DG_OP_MODE: handleDGOpMode( message ); break; @@ -1519,6 +1513,14 @@ handleHDSoftwareResetRequest( message ); break; + case MSG_ID_BLOOD_ROTOR_COUNT_OVERRIDE: + handleHDBloodPumpRotorCountOverrideRequest( message ); + break; + + case MSG_ID_SET_ARTERIAL_PRESSURE_OFFSET: + handleHDSetArterialPressureOffsetRequest( message ); + break; + case MSG_ID_BLOOD_PUMP_HOME_CMD: handleTestBloodPumpHomeRequest( message ); break; @@ -1759,6 +1761,14 @@ handleTestPostTreatmentModeSendIntervalOverrideRequest( message ); break; + case MSG_ID_HD_BLOCK_MESSAGE_TRANSMISSION: + handleTestBlockMessagesRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_FORCE_SENSOR_DAC_CALIBRATE: + handleTestSyringePumpForceSensorCalibrateRequest( message ); + break; + default: // Unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -49,17 +49,26 @@ // ********** private 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. - #ifdef DEBUG_ENABLED #define DEBUG_EVENT_MAX_TEXT_LEN 40 -#endif +#endif + +#define MAX_MSGS_BLOCKED_FOR_XMIT 8 ///< Maximum number of messages to block transmission for. + +#pragma pack(push,1) +/// Payload record structure for block message transmission request. +typedef struct +{ + U16 blockedMessages[ MAX_MSGS_BLOCKED_FOR_XMIT ]; +} BLOCKED_MSGS_DATA_T; +#pragma pack(pop) // ********** private data ********** static BOOL testerLoggedIn = FALSE; ///< Flag indicates whether an external tester (connected PC) has sent a valid login message. -static volatile U16 nextSeqNo = 1; ///< Value of sequence number to use for next transmitted message. +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. +static BLOCKED_MSGS_DATA_T blockedMessagesForXmit = { 0, 0, 0, 0, 0, 0, 0, 0 }; // ********** private function prototypes ********** @@ -74,7 +83,7 @@ * bit of the sequence # is set if ACK is required per parameter. A sync byte * is inserted at the beginning of the message and an 8-bit CRC is appended to * the end of the message. The message is queued for transmission in the given buffer. - * @details Inputs: none + * @details Inputs: blockedMessagesForXmit * @details Outputs: given data array populated with serialized message data and queued for transmit. * @param msg message to serialize * @param buffer outgoing buffer that message should be queued in @@ -84,69 +93,92 @@ U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ) { BOOL result = 0; - BOOL error = FALSE; + BOOL error = FALSE; + BOOL blocked = FALSE; U32 msgSize = 0; U32 sizeMod, sizePad; U32 i; U08 crc; - U08 data[ MAX_ACK_MSG_SIZE ]; // Byte array to populate with message data - - // Prefix data with message sync byte - data[ msgSize++ ] = MESSAGE_SYNC_BYTE; - - // Set sequence # and ACK bit (unless this is an ACK to a received message) - if ( msg.hdr.msgID != MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK ) + U08 data[ MAX_ACK_MSG_SIZE ]; // Byte array to populate with message data + + // Check to see if tester has requested this message not be transmited + if ( TRUE == isTestingActivated() ) + { + U32 i; + + for ( i = 0; i < MAX_MSGS_BLOCKED_FOR_XMIT; i++ ) + { + if ( msg.hdr.msgID == blockedMessagesForXmit.blockedMessages[ i ] ) + { + blocked = TRUE; + break; + } + } + } + // Serialize and queue message for transmission unless this message is blocked + if ( blocked != TRUE ) { - // Thread protect next sequence # access & increment - _disable_IRQ(); - msg.hdr.seqNo = nextSeqNo; - nextSeqNo = INC_WRAP( nextSeqNo, MIN_MSG_SEQ_NO, MAX_MSG_SEQ_NO ); - _enable_IRQ(); - if ( TRUE == ackReq ) + // Prefix data with message sync byte + data[ msgSize++ ] = MESSAGE_SYNC_BYTE; + + // Set sequence # and ACK bit (unless this is an ACK to a received message) + if ( msg.hdr.msgID != MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK ) { - msg.hdr.seqNo *= -1; + // Thread protect next sequence # access & increment + _disable_IRQ(); + msg.hdr.seqNo = nextSeqNo; + nextSeqNo = INC_WRAP( nextSeqNo, MIN_MSG_SEQ_NO, MAX_MSG_SEQ_NO ); + _enable_IRQ(); + if ( TRUE == ackReq ) + { + msg.hdr.seqNo *= -1; + } } - } - // Calculate message CRC - crc = crc8( (U08*)(&msg), sizeof( MESSAGE_HEADER_T ) + msg.hdr.payloadLen ); + // Calculate message CRC + crc = crc8( (U08*)(&msg), sizeof( MESSAGE_HEADER_T ) + msg.hdr.payloadLen ); - // Serialize message header data - memcpy( &data[ msgSize ], &( msg.hdr ), sizeof( MESSAGE_HEADER_T ) ); - msgSize += sizeof( MESSAGE_HEADER_T ); + // Serialize message header data + memcpy( &data[ msgSize ], &( msg.hdr ), sizeof( MESSAGE_HEADER_T ) ); + msgSize += sizeof( MESSAGE_HEADER_T ); - // Serialize message payload (only used bytes per payloadLen field) - memcpy( &data[ msgSize ], &( msg.payload ), msg.hdr.payloadLen ); - msgSize += msg.hdr.payloadLen; + // Serialize message payload (only used bytes per payloadLen field) + memcpy( &data[ msgSize ], &( msg.payload ), msg.hdr.payloadLen ); + msgSize += msg.hdr.payloadLen; - // Add 8-bit CRC - data[ msgSize++ ] = crc; + // Add 8-bit CRC + data[ msgSize++ ] = crc; - // Pad with zero bytes to get length a multiple of CAN_MESSAGE_PAYLOAD_SIZE (8) - sizeMod = msgSize % CAN_MESSAGE_PAYLOAD_SIZE; - sizePad = ( sizeMod == 0 ? 0 : CAN_MESSAGE_PAYLOAD_SIZE - sizeMod ); - for ( i = 0; i < sizePad; i++ ) - { - data[ msgSize++ ] = 0; - } + // Pad with zero bytes to get length a multiple of CAN_MESSAGE_PAYLOAD_SIZE (8) + sizeMod = msgSize % CAN_MESSAGE_PAYLOAD_SIZE; + sizePad = ( sizeMod == 0 ? 0 : CAN_MESSAGE_PAYLOAD_SIZE - sizeMod ); + for ( i = 0; i < sizePad; i++ ) + { + data[ msgSize++ ] = 0; + } -#ifndef DISABLE_ACK_ERRORS - // If ACK required, add to pending ACK list - if ( TRUE == ackReq ) - { - if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) + #ifndef DISABLE_ACK_ERRORS + // If ACK required, add to pending ACK list + if ( TRUE == ackReq ) { - error = TRUE; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) + if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) + { + error = TRUE; + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) + } } - } -#endif + #endif - if ( FALSE == error ) - { - // Add serialized message data to appropriate out-going comm buffer - result = addToCommBuffer( buffer, data, msgSize ); - } + if ( FALSE == error ) + { + // Add serialized message data to appropriate out-going comm buffer + result = addToCommBuffer( buffer, data, msgSize ); + } + } + else + { + result = TRUE; // If message blocked, return successful transmission + } return result; } @@ -320,6 +352,41 @@ return result; } + +/*********************************************************************//** + * @brief + * The sendEvent function constructs an HD event message to the UI and + * queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: HD event msg constructed and queued. + * @param event Enumeration of event type that occurred + * @param dat1 First data associated with event + * @param dat2 Second data associated with event + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendEvent( HD_EVENT_ID_T event, EVENT_DATA_T dat1, EVENT_DATA_T dat2 ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 e = (U32)event; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_EVENT; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( EVENT_DATA_T ) * 2; + + memcpy( payloadPtr, &e, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &dat1, sizeof( EVENT_DATA_T ) ); + payloadPtr += sizeof( EVENT_DATA_T ); + memcpy( payloadPtr, &dat2, sizeof( EVENT_DATA_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_NOT_REQUIRED ); + + return result; +} /*********************************************************************//** * @brief @@ -1024,7 +1091,7 @@ * @param newValue parameter change event new data value * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendTreatmentLogEventData( HD_EVENT_ID_T event, F32 oldValue, F32 newValue ) +BOOL sendTreatmentLogEventData( TX_EVENT_ID_T event, F32 oldValue, F32 newValue ) { MESSAGE_T msg; U08 *payloadPtr = msg.payload; @@ -1704,52 +1771,6 @@ return result; } -/*********************************************************************//** - * @brief - * The broadcastAccelData function constructs an accelerometer data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: accelerometer data broadcast msg constructed and queued. - * @param x X axis vector magnitude (in g) - * @param y Y axis vector magnitude (in g) - * @param z Z axis vector magnitude (in g) - * @param xm max X axis vector magnitude (in g) - * @param ym max Y axis vector magnitude (in g) - * @param zm max Z axis vector magnitude (in g) - * @param xt X axis tilt (in degrees) - * @param yt Y axis tilt (in degrees) - * @param zt Z axis tilt (in degrees) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAccelData( F32 x, F32 y, F32 z, F32 xm, F32 ym, F32 zm, F32 xt, F32 yt, F32 zt ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - ACCEL_DATA_PAYLOAD_T payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_ACCELEROMETER_DATA; - msg.hdr.payloadLen = sizeof( ACCEL_DATA_PAYLOAD_T ); - payload.x = x; - payload.y = y; - payload.z = z; - payload.xMax = xm; - payload.yMax = ym; - payload.zMax = zm; - payload.xTilt = xt; - payload.yTilt = yt; - payload.zTilt = zt; - - memcpy( payloadPtr, &payload, sizeof( ACCEL_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - /*********************************************************************//** * @brief * The broadcastAlarmStatus function constructs an alarm status msg to @@ -1762,15 +1783,8 @@ BOOL broadcastAlarmStatus( COMP_ALARM_STATUS_T almStatus ) { BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; ALARM_COMP_STATUS_PAYLOAD_T payload; - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_STATUS; - msg.hdr.payloadLen = sizeof( ALARM_COMP_STATUS_PAYLOAD_T ); - payload.alarmState = (U32)almStatus.alarmsState; payload.alarmTop = (U32)almStatus.alarmTop; payload.silenceExpiresIn = almStatus.alarmsSilenceExpiresIn; @@ -1789,925 +1803,14 @@ payload.alarmsFlags |= ( almStatus.lampOn ? BIT_BY_POS(ALARM_STATE_FLAG_BIT_POS_LAMP_ON) : 0 ); payload.alarmsFlags |= ( almStatus.noMinimize ? BIT_BY_POS(ALARM_STATE_FLAG_BIT_POS_NO_MINIMIZE) : 0 ); payload.alarmsFlags |= ( almStatus.topAlarmConditionDetected ? BIT_BY_POS(ALARM_STATE_FLAG_BIT_POS_TOP_CONDITION) : 0 ); - - memcpy( payloadPtr, &payload, sizeof( ALARM_COMP_STATUS_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_ALARM, ACK_NOT_REQUIRED ); - - return result; -} -/*********************************************************************//** - * @brief - * The broadcastAlarmInfo function constructs an alarm information msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: alarm information msg constructed and queued. - * @param data alarm information record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmInfo( ALARM_INFO_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_ALARM_INFORMATION; - msg.hdr.payloadLen = sizeof( ALARM_INFO_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( ALARM_INFO_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} + result = broadcastData( MSG_ID_ALARM_STATUS, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&payload, sizeof( ALARM_COMP_STATUS_PAYLOAD_T ) ); -/*********************************************************************//** - * @brief - * The broadcastAlarmTriggered function constructs an alarm triggered msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: alarm triggered msg constructed and queued. - * @param alarm ID of alarm triggered - * @param almData1 1st data associated with alarm - * @param almData2 2nd data associated with alarm - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmTriggered( U32 alarm, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_TRIGGERED; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) * 2 * 2; // 2 alarm data recs w/ 2 32-bit values each - - memcpy( payloadPtr, &alarm, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &almData1.dataType, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &almData1.data, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &almData2.dataType, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &almData2.data, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_ALARM, ACK_REQUIRED ); - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastAlarmCleared function constructs an alarm cleared msg to be - * broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: alarm cleared msg constructed and queued. - * @param alarm ID of alarm cleared - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmCleared( U32 alarm ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_CLEARED; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &alarm, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_ALARM, ACK_REQUIRED ); - - return result; } /*********************************************************************//** * @brief - * The broadcastAlarmConditionCleared function constructs an alarm condition - * cleared msg to be broadcast and queues the msg for transmit on the - * appropriate CAN channel. - * @details Inputs: none - * @details Outputs: alarm condition cleared msg constructed and queued. - * @param alarm ID of alarm that has had its condition cleared - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmConditionCleared( U32 alarm ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_CONDITION_CLEARED; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &alarm, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_ALARM, ACK_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastBloodFlowData function constructs a blood flow data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: blood flow data msg constructed and queued. - * @param bloodData blood pump and flow data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastBloodFlowData( BLOOD_PUMP_STATUS_PAYLOAD_T *bloodData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_BLOOD_FLOW_DATA; - msg.hdr.payloadLen = sizeof( BLOOD_PUMP_STATUS_PAYLOAD_T ); - - memcpy( payloadPtr, bloodData, sizeof( BLOOD_PUMP_STATUS_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastDialInFlowData function constructs a dialysate flow data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: dialysate flow data msg constructed and queued. - * @param dialInData Dialysate inlet pump and flow data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDialInFlowData( DIALIN_PUMP_STATUS_PAYLOAD_T *dialInData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DIALYSATE_FLOW_DATA; - msg.hdr.payloadLen = sizeof( DIALIN_PUMP_STATUS_PAYLOAD_T ); - - memcpy( payloadPtr, dialInData, sizeof( DIALIN_PUMP_STATUS_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastDialInFlowData function constructs a dialysate outlet flow data - * msg to be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: dialysate out flow data msg constructed and queued. - * @param dialOutFlowData Pointer to the dialysate out flow data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DIALYSATE_OUT_FLOW_DATA; - msg.hdr.payloadLen = sizeof( DIAL_OUT_FLOW_DATA_T ); - - memcpy( payloadPtr, dialOutFlowData, sizeof( DIAL_OUT_FLOW_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastSyringePumpData function constructs a syringe pump data - * msg to be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: syringe pump data msg constructed and queued. - * @param data syringe pump data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_SYRINGE_PUMP_DATA; - msg.hdr.payloadLen = sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastHeparinData function constructs a Heparin data message - * to be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: Heparin data msg constructed and queued. - * @param data Heparin data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastHeparinData( F32 volume ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_HEPARIN_DATA_BROADCAST; - msg.hdr.payloadLen = sizeof( F32 ); - - memcpy( payloadPtr, &volume, sizeof( F32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastPresOcclData function constructs a pres/occl data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: pressure/occlusion data msg constructed and queued. - * @param data Latest measured pressures and occlusion values. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_PRESSURE_OCCLUSION_DATA; - msg.hdr.payloadLen = sizeof( PRESSURE_OCCLUSION_DATA_T ); - - memcpy( payloadPtr, &data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastVoltagesData function constructs a monitored voltages data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: monitored voltages data msg constructed and queued. - * @param data Latest monitored voltage values. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_VOLTAGES_DATA; - msg.hdr.payloadLen = sizeof( VOLTAGES_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( VOLTAGES_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastRTCEpoch function constructs an epoch msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: RTC time and date in epoch - * @param epoch Current time and date in epoch - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastRTCEpoch( U32 epoch ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_RTC_EPOCH; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &epoch, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastTreatmentTime function constructs a treatment time msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: treatment time data msg constructed and queued - * @param secsTotTreatment Total treatment time prescribed (in seconds) - * @param secsElapsed Treatment time elapsed (in seconds) - * @param secsRemaining Treatment time remaining (in seconds) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastTreatmentTime( U32 secsTotTreatment, U32 secsElapsed, U32 secsRemaining ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - TREATMENT_TIME_DATA_T payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_TREATMENT_TIME; - msg.hdr.payloadLen = sizeof( TREATMENT_TIME_DATA_T ); - - payload.treatmentTimePrescribedinSec = secsTotTreatment; - payload.treatmentTimeElapsedinSec = secsElapsed; - payload.treatmentTimeRemaininginSec = secsRemaining; - - memcpy( payloadPtr, &payload, sizeof( TREATMENT_TIME_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastTreatmentState function constructs a treatment state msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: treatment state msg constructed and queued - * @param payload Record with treatment state data - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_TREATMENT_STATE; - msg.hdr.payloadLen = sizeof( TREATMENT_STATE_DATA_T ); - - memcpy( payloadPtr, &payload, sizeof( TREATMENT_STATE_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastPostTreatmentState function constructs a post treatment state msg - * to be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: post-treatment state msg constructed and queued - * @param postTreatmentSubMode post-treatment state sub-mode - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPostTreatmentState( U32 postTreatmentSubMode ) -{ - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_POST_TREATMENT_STATE; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &postTreatmentSubMode, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - return serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); -} - -/*********************************************************************//** - * @brief - * The broadcastPreTreatmentState function constructs a pre-treatment state msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: pre-treatment state msg constructed and queued - * @param preTreatmentDataPtr pointer to pre-treatment data record to broadcast - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPreTreatmentState( PRE_TREATMENT_STATE_DATA_T *preTreatmentDataPtr ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_PRE_TREATMENT_STATE; - msg.hdr.payloadLen = sizeof( PRE_TREATMENT_STATE_DATA_T ); - - memcpy( payloadPtr, preTreatmentDataPtr, sizeof( PRE_TREATMENT_STATE_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastPowerOffWarning function constructs a power off warning msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: power off warning msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPowerOffWarning( void ) -{ - BOOL result; - MESSAGE_T msg; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_POWER_OFF_WARNING; - msg.hdr.payloadLen = 0; - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastHDOperationMode function constructs an HD operation mode - * broadcast message and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: HD operation mode msg constructed and queued - * @param mode current HD operation mode - * @param subMode current HD operation sub-mode - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastHDOperationMode( U32 mode, U32 subMode ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_OP_MODE; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &mode, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &subMode, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastHDValves function constructs an HD valves msg to \n - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: HD valves msg constructed and queued - * @param valveData valve data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastHDValves( HD_VALVE_DATA_T *valveData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_VALVES_DATA; - msg.hdr.payloadLen = sizeof( HD_VALVE_DATA_T ); - - memcpy( payloadPtr, valveData, sizeof( HD_VALVE_DATA_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastSalineBolusData function constructs a saline bolus data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: saline bolus data msg constructed and queued - * @param data saline bolus data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_SALINE_BOLUS_DATA; - msg.hdr.payloadLen = sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastTreatmentStopData function constructs a treatment stop data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: treatment stop data msg constructed and queued - * @param timeout treatment stop timeout (in sec) - * @param countdown treatment stop timeout count down (in sec) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_TREATMENT_STOP_TIMER_DATA; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &timeout, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &countdown, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastRinsebackData function constructs a rinseback data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: rinseback data msg constructed and queued - * @param data rinseback data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_RINSEBACK_PROGRESS; - msg.hdr.payloadLen = sizeof( RINSEBACK_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( RINSEBACK_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastRecircData function constructs a treatment re-circ data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: treatment re-circ data msg constructed and queued - * @param timeout re-circulation timeout (in sec) - * @param countdown re-circulation timeout count down (in sec) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastRecircData( U32 timeout, U32 countdown ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_RECIRC_PROGRESS; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &timeout, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &countdown, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastBloodPrimeData function constructs a blood prime data msg to - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: blood prime data msg constructed and queued - * @param data blood prime data record - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_BLOOD_PRIME_PROGRESS; - msg.hdr.payloadLen = sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, &data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastAirTrapData function constructs an HD air trap data msg to \n - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: air trap data msg constructed and queued - * @param lowerLevel air trap lower level data - * @param upperLevel air trap upper level data - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - U32 lower = (U32)lowerLevel; - U32 upper = (U32)upperLevel; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_AIR_TRAP_DATA; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &lower, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &upper, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastNoCartSelfTestTime function sends out the no cartridge self-test - * progress data. - * @details Inputs: none - * @details Outputs: no cartridge self-test time data msg constructed and queued - * @param timeout no cartridge self-test timeout (in sec) - * @param countdown no cartridge self-test timeout count down (in sec) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastNoCartSelfTestTime( U32 timeout, U32 countdown ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &timeout, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &countdown, sizeof( U32 ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastDrySelfTestTime function sends out the dry self-test progress data. - * @details Inputs: none - * @details Outputs: dry self-test time data msg constructed and queued - * @param timeout dry self-test timeout (in sec) - * @param countdown dry self-test timeout count down (in sec) - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDrySelfTestTime( U32 timeout, U32 countdown ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_DRY_SELF_TEST_PROGRESS; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &timeout, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &countdown, sizeof( U32 ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastFluidLeakState function constructs an HD fluid leak state msg to \n - * be broadcasted and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: fluid leak state msg constructed and queued - * @param state fluid leak state - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - U32 leakState = (U32)state; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_FLUID_LEAK_STATE; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &leakState, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastBloodLeakData function constructs an HD blood leak data msg to \n - * be broadcasted and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: blood leak data msg constructed and queued - * @param status blood leak status - * @param state blood leak state - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastBloodLeakData( BLOOD_LEAK_STATUS_T status, U32 state ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - U32 leakStatus = (U32)status; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_BLOOD_LEAK_DATA; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &leakStatus, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &state, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastBubblesData function constructs an HD air bubble data msg to \n - * be broadcasted and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: air bubbles data msg constructed and queued - * @param status air bubbles status - * @param state air bubbles states - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastBubblesData( U32 statusADA, U32 stateADA, U32 statusADV, U32 stateADV ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_BUBBLES_DATA; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ); - - memcpy( payloadPtr, &statusADA, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &stateADA, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &statusADV, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &stateADV, sizeof( U32 ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/***********************************************************************//** - * @brief - * The broadcastPrimeData function constructs a prime data msg to \n - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details Inputs: none - * @details Outputs: prime data msg constructed and queued - * @param primeDataPtr prime data record pointer - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPrimeData( PRIMING_DATA_PAYLOAD_T *primeDataPtr ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_PRIMING_STATUS_DATA; - msg.hdr.payloadLen = sizeof( PRIMING_DATA_PAYLOAD_T ); - - memcpy( payloadPtr, primeDataPtr, sizeof( PRIMING_DATA_PAYLOAD_T ) ); - - // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief * The sendHDCalibrationRecord function sends out the HD calibration * record. * @details Inputs: none @@ -2824,114 +1927,6 @@ return result; } -/*********************************************************************//** - * @brief - * The broadcastDisinfectsData function sends out the disinfects data. - * @details Inputs: none - * @details Outputs: disinfects data msg constructed and queued - * @param disinfectsData which is disinfects msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDisinfectsData( DISINFECTS_DATA_T *disinfectsData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_DISINFECT_STANDBY_DATA; - msg.hdr.payloadLen = sizeof( DISINFECTS_DATA_T ); - - memcpy( payloadPtr, disinfectsData, sizeof( DISINFECTS_DATA_T ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastSwitchesData function sends out switches data. - * @details Inputs: none - * @details Outputs: switches data msg constructed and queued - * @param SWITCHES_DATA_T which is switches msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastSwitchesData( SWITCHES_DATA_T *switchesData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_SWITCHES_DATA; - msg.hdr.payloadLen = sizeof( SWITCHES_DATA_T ); - - memcpy( payloadPtr, switchesData, sizeof( SWITCHES_DATA_T ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastTemperaturesData function sends out the temperatures data. - * @details Inputs: none - * @details Outputs: temperatures data msg constructed and queued - * @param temperaturesData which is the temperatures msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastTemperaturesData( TEMPERATURES_DATA_T *temperaturesData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_TEMPERATURES_DATA; - msg.hdr.payloadLen = sizeof( TEMPERATURES_DATA_T ); - - memcpy( payloadPtr, temperaturesData, sizeof( TEMPERATURES_DATA_T ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/*********************************************************************//** - * @brief - * The broadcastFansData function sends out the fans data. - * @details Inputs: none - * @details Outputs: fans data msg constructed and queued - * @param fansData which is the fans msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastFansData( FANS_DATA_T *fansData ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_FANS_DATA; - msg.hdr.payloadLen = sizeof( FANS_DATA_T ); - - memcpy( payloadPtr, fansData, sizeof( FANS_DATA_T ) ); - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - #ifdef EMC_TEST_BUILD BOOL broadcastCANErrorCount( U32 count ) { @@ -3259,74 +2254,34 @@ TEMPERATURE_SENSORS_DATA_T payload; memcpy( &payload, message->payload, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); - setDialysateTemperatureReadings( payload.inletDialysate, payload.outletRedundant ); + setDialysateTemperatureReadings( payload.TDi, payload.TRo ); } // TODO - what to do if invalid payload length? // TODO - how to know if DG stops sending these? } -/*********************************************************************//** - * @brief - * The handleROPumpData function handles an RO pump data broadcast - * message from the DG. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleROPumpData( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(DG_RO_PUMP_DATA_PAYLOAD_T) ) - { - DG_RO_PUMP_DATA_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(DG_RO_PUMP_DATA_PAYLOAD_T) ); - setDGROPumpData( payload.setPtPSI, payload.measFlowRateMlMin ); - } +/*********************************************************************//** + * @brief + * The handleDialysateFlowData function handles dialysate flow data broadcast + * message from the DG. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDialysateFlowData( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof(DIALYSATE_FLOW_METER_DATA_T) ) + { + DIALYSATE_FLOW_METER_DATA_T payload; + + memcpy( &payload, message->payload, sizeof(DIALYSATE_FLOW_METER_DATA_T) ); + setDialysateFlowData( payload.measuredDialysateFlowRate ); + } } -/*********************************************************************//** - * @brief - * The handleDrainPumpData function handles a drain pump broadcast - * message from the DG. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleDrainPumpData( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(DG_DRAIN_PUMP_DATA_PAYLOAD_T) ) - { - DG_DRAIN_PUMP_DATA_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(DG_DRAIN_PUMP_DATA_PAYLOAD_T) ); - setDGDrainPumpData( payload.setPtRPM ); - } -} - -/*********************************************************************//** - * @brief - * The handleDGPressuresData function handles a DG pressure sensor readings - * broadcast message from the DG. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleDGPressuresData( MESSAGE_T *message ) -{ - if ( message->hdr.payloadLen == sizeof(DG_PRESSURES_DATA_PAYLOAD_T) ) - { - DG_PRESSURES_DATA_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(DG_PRESSURES_DATA_PAYLOAD_T) ); - setDGPressures( payload.roInPSI, payload.roOutPSI, payload.drainInPSI, payload.drainOutPSI ); - } -} - -/*********************************************************************//** - * @brief +/*********************************************************************//** + * @brief * The handleDGReservoirData function handles a reservoir data broadcast * message from the DG. * @details Inputs: none @@ -4563,14 +3518,14 @@ /*********************************************************************//** * @brief - * The handleTestBloodFlowSignalStrengthOverrideRequest function handles a - * request to override the measured blood flow signal strength (%). + * The handleHDBloodPumpRotorCountOverrideRequest function handles a request to + * override the blood pump rotor count. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ -void handleTestBloodFlowSignalStrengthOverrideRequest( MESSAGE_T *message ) +void handleHDBloodPumpRotorCountOverrideRequest( MESSAGE_T *message ) { TEST_OVERRIDE_PAYLOAD_T payload; BOOL result = FALSE; @@ -4581,18 +3536,50 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetMeasuredBloodFlowSignalStrengthOverride( payload.state.f32 ); + result = testSetBloodPumpRotorCountOverride( payload.state.u32 ); } else { - result = testResetMeasuredBloodFlowSignalStrengthOverride(); + result = testResetBloodPumpRotorCountOverride(); } } // Respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } - + +/*********************************************************************//** + * @brief + * The handleHDSetArterialPressureOffsetRequest function handles a request to + * set the arterial pressure offset. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleHDSetArterialPressureOffsetRequest( 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 = testSetArterialPressureOffsetOverride( payload.state.f32 ); + } + else + { + result = testResetArterialPressureOffsetOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /*********************************************************************//** * @brief * The handleTestBloodPumpRotorMeasuredSpeedOverrideRequest function handles a request to @@ -4835,38 +3822,6 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } -/*********************************************************************//** - * @brief - * The handleTestDialInFlowSignalStrengthOverrideRequest function handles a - * request to override the measured dialysate inlet flow signal strength (%). - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleTestDialInFlowSignalStrengthOverrideRequest( 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 = testSetMeasuredDialInFlowSignalStrengthOverride( payload.state.f32 ); - } - else - { - result = testResetMeasuredDialInFlowSignalStrengthOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - /*********************************************************************//** * @brief * The handleTestDialInPumpRotorMeasuredSpeedOverrideRequest function handles a request to @@ -5125,70 +4080,6 @@ /*********************************************************************//** * @brief - * The handleTestDialysateInletPumpOcclusionOverrideRequest function handles a request to - * override the dialysate inlet pump occlusion sensor. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleTestDialysateInletPumpOcclusionOverrideRequest( 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 = testSetDialInPumpOcclusionOverride( payload.state.u32 ); - } - else - { - result = testResetDialInPumpOcclusionOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief - * The handleTestDialysateOutletPumpOcclusionOverrideRequest function handles a request to - * override the dialysate outlet pump occlusion sensor. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleTestDialysateOutletPumpOcclusionOverrideRequest( 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 = testSetDialOutPumpOcclusionOverride( payload.state.u32 ); - } - else - { - result = testResetDialOutPumpOcclusionOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleTestPresOcclBroadcastIntervalOverrideRequest function handles a request to * override the broadcast interval for pressure/occlusion data. * @details Inputs: none @@ -6228,6 +5119,7 @@ if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) { memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) { result = testSetBatteryRemainingPercentOverride( payload.state.u32 ); @@ -6276,38 +5168,6 @@ /*********************************************************************//** * @brief - * The handleBloodPrimeSafetyVolumeOverrideRequest function handles a request to - * override the calculated safety blood prime volume (in mL). - * @details Inputs: none - * @details Outputs: message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleBloodPrimeSafetyVolumeOverrideRequest( 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 = testSetBloodPrimeSafetyVolumeOverride( payload.state.f32 ); - } - else - { - result = testResetBloodPrimeSafetyVolumeOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleRinsebackVolumeOverrideRequest function handles a request to * override the calculated rinseback volume (in mL). * @details Inputs: none @@ -6340,38 +5200,6 @@ /*********************************************************************//** * @brief - * The handleRinsebackSafetyVolumeOverrideRequest function handles a request to - * override the calculated safety rinseback volume (in mL). - * @details Inputs: none - * @details Outputs: message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleRinsebackSafetyVolumeOverrideRequest( 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 = testSetRinsebackSafetyVolumeOverride( payload.state.f32 ); - } - else - { - result = testResetRinsebackSafetyVolumeOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleHDSoftwareResetRequest function handles a request to reset the * HD firmware processor. * @details Inputs: none @@ -7457,6 +6285,63 @@ /*********************************************************************//** * @brief + * The handleTestBlockMessagesRequest function handles a request to + * block transmission of specific message(s). + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestBlockMessagesRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( BLOCKED_MSGS_DATA_T ) == message->hdr.payloadLen ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + memcpy( &blockedMessagesForXmit.blockedMessages[0], message->payload, sizeof( BLOCKED_MSGS_DATA_T ) ); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpForceSensorCalibrateRequest function handles a + * request message to set the syringe pump DAC reference voltage. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpForceSensorCalibrateRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( F32 ) == message->hdr.payloadLen ) + { + if ( TRUE == isTestingActivated() ) + { + F32 dacVRef; + + result = TRUE; + memcpy( &dacVRef, message->payload, sizeof( F32 ) ); + setSyringePumpDACVref( dacVRef ); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief * The handleTestAlarmAudioVolumeOverrideRequest function handles a * request to override the alarm audio volume level. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r5bfaf341319b9fd763d07ad0a68a986028c37587 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5bfaf341319b9fd763d07ad0a68a986028c37587) @@ -31,7 +31,7 @@ #include "Fans.h" #include "FluidLeak.h" #include "HDCommon.h" -#include "Prime.h" +#include "MessageSupport.h" #include "ModeInitPOST.h" #include "ModePostTreat.h" #include "ModePreTreat.h" @@ -40,6 +40,7 @@ #include "MsgQueues.h" #include "NVDataMgmt.h" #include "PresOccl.h" +#include "Prime.h" #include "Rinseback.h" #include "Switches.h" #include "SyringePump.h" @@ -61,8 +62,14 @@ #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_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. + // ********** public function prototypes ********** - + +// Serialize message +U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); + // ACK MSG BOOL sendACKMsg( MESSAGE_T *message ); @@ -99,6 +106,9 @@ // MSG_ID_HD_DG_POST_RESULT_REQUEST BOOL sendDGPOSTResultRequest( void ); +// 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 ); @@ -134,7 +144,10 @@ void handleDGTemperatureData( MESSAGE_T *message ); // MSG_ID_RO_PUMP_DATA: -void handleROPumpData( MESSAGE_T *message ); +void handleROPumpData( MESSAGE_T *message ); + +// MSG_ID_DG_DIALYSATE_FLOW_METER_DATA: +void handleDialysateFlowData( MESSAGE_T *message ); // MSG_ID_DRAIN_PUMP_DATA: void handleDrainPumpData( MESSAGE_T *message ); @@ -332,7 +345,7 @@ BOOL sendTreatmentLogAlarmEventData( ALARM_ID_T alarmID, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ); // MSG_ID_HD_TREATMENT_LOG_EVENT -BOOL sendTreatmentLogEventData( HD_EVENT_ID_T event, F32 oldValue, F32 newValue ); +BOOL sendTreatmentLogEventData( TX_EVENT_ID_T event, F32 oldValue, F32 newValue ); // *********** public DG command functions ********** @@ -378,113 +391,9 @@ // MSG_ID_DG_START_STOP_CHEM_DISINFECT BOOL sendDGStartChemicalDisinfectModeCommand( BOOL start ); -// *********** public data broad cast functions ********** - -// MSG_ID_HD_ACCELEROMETER_DATA -BOOL broadcastAccelData( F32 x, F32 y, F32 z, F32 xm, F32 ym, F32 zm, F32 xt, F32 yt, F32 zt ); - // MSG_ID_ALARM_STATUS BOOL broadcastAlarmStatus( COMP_ALARM_STATUS_T almStatus ); -// MSG_ID_HD_ALARM_INFORMATION -BOOL broadcastAlarmInfo( ALARM_INFO_PAYLOAD_T data ); - -// MSG_ID_ALARM_TRIGGERED -BOOL broadcastAlarmTriggered( U32 alarm, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ); - -// MSG_ID_ALARM_CLEARED -BOOL broadcastAlarmCleared( U32 alarm ); - -// MSG_ID_ALARM_CONDITION_CLEARED -BOOL broadcastAlarmConditionCleared( U32 alarm ); - -// MSG_ID_BLOOD_FLOW_DATA -BOOL broadcastBloodFlowData( BLOOD_PUMP_STATUS_PAYLOAD_T *bloodData ); - -// MSG_ID_DIALYSATE_FLOW_DATA -BOOL broadcastDialInFlowData( DIALIN_PUMP_STATUS_PAYLOAD_T *dialInData ); - -// MSG_ID_DIALYSATE_OUT_FLOW_DATA -BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); - -// MSG_ID_HD_SYRINGE_PUMP_DATA -BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ); - -// MSG_ID_HD_HEPARIN_DATA_BROADCAST -BOOL broadcastHeparinData( F32 volume ); - -// MSG_ID_PRESSURE_OCCLUSION_DATA -BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ); - -// MSG_ID_HD_VOLTAGES_DATA -BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ); - -// MSG_ID_RTC_EPOCH -BOOL broadcastRTCEpoch( U32 epoch ); - -// MSG_ID_TREATMENT_TIME -BOOL broadcastTreatmentTime( U32 secsTotTreatment, U32 secsElapsed, U32 secsRemaining ); - -// MSG_ID_TREATMENT_STATE -BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ); - -// MSG_ID_HD_POST_TREATMENT_STATE -BOOL broadcastPostTreatmentState( U32 postTreatmentSubMode ); - -// MSG_ID_PRE_TREATMENT_STATE -BOOL broadcastPreTreatmentState( PRE_TREATMENT_STATE_DATA_T *preTreatmentDataPtr ); - -// MSG_ID_POWER_OFF_WARNING -BOOL broadcastPowerOffWarning( void ); - -// MSG_ID_HD_OP_MODE -BOOL broadcastHDOperationMode( U32 mode, U32 subMode ); - -// MSG_ID_HD_VALVES_DATA -BOOL broadcastHDValves( HD_VALVE_DATA_T *valveData ); - -// MSG_ID_SALINE_BOLUS_DATA -BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ); - -// MSG_ID_HD_TREATMENT_STOP_TIMER_DATA -BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ); - -// MSG_ID_HD_RINSEBACK_PROGRESS -BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ); - -// MSG_ID_HD_RECIRC_PROGRESS -BOOL broadcastRecircData( U32 timeout, U32 countdown ); - -// MSG_ID_HD_BLOOD_PRIME_PROGRESS -BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ); - -// MSG_ID_HD_AIR_TRAP_DATA -BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel ); - -// MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS -BOOL broadcastNoCartSelfTestTime( U32 timeout, U32 countdown ); - -// MSG_ID_HD_DRY_SELF_TEST_PROGRESS -BOOL broadcastDrySelfTestTime( U32 timeout, U32 countdown ); - -// MSG_ID_HD_FLUID_LEAK_STATE -BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state ); - -// MSG_ID_HD_BLOOD_LEAK_DATA -BOOL broadcastBloodLeakData( BLOOD_LEAK_STATUS_T status, U32 state ); - -// MSG_ID_HD_BUBBLES_DATA -BOOL broadcastBubblesData( U32 statusADA, U32 stateADA, U32 statusADV, U32 stateADV ); - -// MSG_ID_HD_PRIMING_STATUS_DATA -BOOL broadcastPrimeData( PRIMING_DATA_PAYLOAD_T *primeDataPtr ); - -// MSG_ID_HD_DISINFECT_STANDBY_DATA -BOOL broadcastDisinfectsData( DISINFECTS_DATA_T *disinfectsData ); - -// MSG_ID_HD_SWITCHES_DATA -BOOL broadcastSwitchesData( SWITCHES_DATA_T *switchesData ); - // MSG_ID_HD_SEND_CALIBRATION_RECORD BOOL sendHDCalibrationRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* calRcrdAddress ); @@ -494,15 +403,6 @@ // MSG_ID_Hd_SEND_SERVICE_RECORD BOOL sendHDServiceRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* srvcRcrdAddress ); -// MSG_ID_HD_DISINFECT_STANDBY_DATA -BOOL broadcastDisinfectsData( DISINFECTS_DATA_T *disinfectsData ); - -// MSG_ID_HD_TEMPERATURES_DATA -BOOL broadcastTemperaturesData( TEMPERATURES_DATA_T *temperaturesData ); - -// MSG_ID_HD_FANS_DATA -BOOL broadcastFansData( FANS_DATA_T *fansData ); - #ifdef EMC_TEST_BUILD // MSG_ID_CAN_ERROR_COUNT BOOL broadcastCANErrorCount( U32 count ); @@ -546,9 +446,12 @@ // MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE void handleTestBloodFlowMeasuredOverrideRequest( MESSAGE_T *message ); -// MSG_ID_BLOOD_FLOW_SIG_STRENGTH_OVERRIDE -void handleTestBloodFlowSignalStrengthOverrideRequest( MESSAGE_T *message ); +// MSG_ID_BLOOD_ROTOR_COUNT_OVERRIDE +void handleHDBloodPumpRotorCountOverrideRequest( MESSAGE_T *message ); +// MSG_ID_SET_ARTERIAL_PRESSURE_OFFSET +void handleHDSetArterialPressureOffsetRequest( MESSAGE_T *message ); + // MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE void handleTestBloodPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); @@ -573,9 +476,6 @@ // MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE void handleTestDialInFlowMeasuredOverrideRequest( MESSAGE_T *message ); -// MSG_ID_DIAL_IN_FLOW_SIG_STRENGTH_OVERRIDE -void handleTestDialInFlowSignalStrengthOverrideRequest( MESSAGE_T *message ); - // MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE void handleTestDialInPumpMCMeasuredSpeedOverrideRequest( MESSAGE_T *message ); @@ -600,12 +500,6 @@ // MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE void handleTestBloodPumpOcclusionOverrideRequest( MESSAGE_T *message ); -// MSG_ID_OCCLUSION_DIAL_IN_PUMP_OVERRIDE -void handleTestDialysateInletPumpOcclusionOverrideRequest( MESSAGE_T *message ); - -// MSG_ID_OCCLUSION_DIAL_OUT_PUMP_OVERRIDE -void handleTestDialysateOutletPumpOcclusionOverrideRequest( MESSAGE_T *message ); - // MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE void handleTestPresOcclBroadcastIntervalOverrideRequest( MESSAGE_T *message ); @@ -713,15 +607,9 @@ // MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE void handleBloodPrimeVolumeOverrideRequest( MESSAGE_T *message ); -// MSG_ID_HD_BLOOD_PRIME_SAFETY_VOLUME_OVERRIDE -void handleBloodPrimeSafetyVolumeOverrideRequest( MESSAGE_T *message ); - // MSG_ID_HD_RINSEBACK_VOLUME_OVERRIDE void handleRinsebackVolumeOverrideRequest( MESSAGE_T *message ); -// MSG_ID_HD_RINSEBACK_SAFETY_VOLUME_OVERRIDE -void handleRinsebackSafetyVolumeOverrideRequest( MESSAGE_T *message ); - // MSG_ID_HD_SWITCHES_STATUS_OVERRIDE void handleSetSwitchesStatusOverrideRequest( MESSAGE_T *message ); @@ -866,6 +754,12 @@ // MSG_ID_HD_FANS_RPM_OVERRIDE void handleFansRPMOverride( MESSAGE_T *message ); +// MSG_ID_HD_BLOCK_MESSAGE_TRANSMISSION +void handleTestBlockMessagesRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_FORCE_SENSOR_DAC_CALIBRATE +void handleTestSyringePumpForceSensorCalibrateRequest( MESSAGE_T *message ); + // MSG_ID_HD_STOP_RTC_CLOCK void handleStopHDRTCClock( MESSAGE_T *message );