Index: firmware/App/Controllers/AirTrap.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -384,10 +384,12 @@ // Publish air trap data on interval if ( ++airTrapDataPublicationTimerCounter >= getU32OverrideValue( &airTrapDataPublishInterval ) ) { - AIR_TRAP_LEVELS_T lowLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); - AIR_TRAP_LEVELS_T highLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); + AIR_TRAP_PAYLOAD_T data; - broadcastAirTrapData( lowLevel, highLevel ); + data.lowerLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); + data.upperLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); + + broadcastData( MSG_ID_HD_AIR_TRAP_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( AIR_TRAP_PAYLOAD_T ) ); airTrapDataPublicationTimerCounter = 0; } } Index: firmware/App/Controllers/AirTrap.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/AirTrap.h (.../AirTrap.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/AirTrap.h (.../AirTrap.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -48,6 +48,13 @@ NUM_OF_AIR_TRAP_LEVELS ///< Number of air trap level sensor levels } AIR_TRAP_LEVELS_T; +/// Payload record structure for air trap data broadcast message +typedef struct +{ + U32 lowerLevel; ///< Lower air trap level sensor state + U32 upperLevel; ///< Upper air trap level sensor state +} AIR_TRAP_PAYLOAD_T; + // ********** public function prototypes ********** void initAirTrap( void ); @@ -58,7 +65,7 @@ void startAirTrapControl( void ); void endAirTrapControl( void ); -BOOL isAirTrapControlling( void ); +BOOL isAirTrapControlling( void ); AIR_TRAP_LEVELS_T getAirTrapLevel( AIR_TRAP_LEVEL_SENSORS_T sensor ); Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r31785f24396cebed8e10834f56fc2668783558e6 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 31785f24396cebed8e10834f56fc2668783558e6) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -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; @@ -748,6 +759,18 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_DIRECTION, dir ) break; } +} + +/*********************************************************************//** + * @brief + * The getTargetBloodFlowRate function gets the target blood flow rate. + * @details Inputs: targetBloodFlowRate + * @details Outputs: none + * @return the current target blood flow rate (in mL/min). + *************************************************************************/ +S32 getTargetBloodFlowRate( void ) +{ + return targetBloodFlowRate; } /*********************************************************************//** @@ -770,26 +793,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 +896,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 +975,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 +1012,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 +1034,14 @@ 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; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_BLOOD_PUMP ) } - +#endif bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); bpDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); @@ -1128,48 +1129,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 +1143,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 +1153,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 +1198,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 +1522,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/BloodFlow.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/BloodFlow.h (.../BloodFlow.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/BloodFlow.h (.../BloodFlow.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -35,7 +35,7 @@ #define MIN_SET_BLOOD_FLOW_RATE 100 ///< Minimum blood flow rate (in mL/min). #define SALINE_BOLUS_FLOW_RATE 150 ///< Saline bolus flow rate (in mL/min). -#define VOLUME_PER_BP_MOTOR_REV_ML 0.2 ///< Theoretical volume (mL) of blood/saline volume per motor revolution. +#define VOLUME_PER_BP_MOTOR_REV_ML 0.216 ///< Theoretical volume (mL) of blood/saline volume per motor revolution. #define BP_HALL_EDGE_COUNTS_PER_REV 48 ///< Number of hall sensor edge counts per motor revolution. /// Payload record structure for a blood pump data message. @@ -48,7 +48,7 @@ F32 measMCSpd; F32 measMCCurr; F32 pwmDC; - F32 flowSigStrength; + U32 rotorCount; } BLOOD_PUMP_STATUS_PAYLOAD_T; // ********** public function prototypes ********** @@ -63,12 +63,13 @@ BOOL homeBloodPump( void ); U32 getBloodPumpMotorCount( void ); U32 getBloodPumpRotorCount( void ); -BOOL isBloodPumpRunning( void ); +BOOL isBloodPumpRunning( void ); +void resetBloodPumpRotorCount( void ); SELF_TEST_STATUS_T execBloodFlowTest( void ); - + +S32 getTargetBloodFlowRate( void ); F32 getMeasuredBloodFlowRate( void ); -F32 getMeasuredBloodFlowSignalStrength( void); F32 getMeasuredBloodPumpRotorSpeed( void ); F32 getMeasuredBloodPumpSpeed( void ); F32 getMeasuredBloodPumpMCSpeed( void ); @@ -87,8 +88,8 @@ BOOL testResetMeasuredBloodPumpMCSpeedOverride( void ); BOOL testSetMeasuredBloodPumpMCCurrentOverride( F32 value ); BOOL testResetMeasuredBloodPumpMCCurrentOverride( void ); -BOOL testSetMeasuredBloodFlowSignalStrengthOverride( F32 value ); -BOOL testResetMeasuredBloodFlowSignalStrengthOverride( void ); +BOOL testSetBloodPumpRotorCountOverride( U32 value ); +BOOL testResetBloodPumpRotorCountOverride( void ); /**@}*/ Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -327,9 +327,11 @@ // Publish blood leak data on interval if ( ++bloodLeakDataPublicationTimerCounter >= getU32OverrideValue( &bloodLeakDataPublishInterval ) ) { - BLOOD_LEAK_STATUS_T status = getBloodLeakStatus(); + BLOOD_LEAK_DATA_T bloodLeakData; - broadcastBloodLeakData( status, (U32)bloodLeakState ); + bloodLeakData.bloodLeakStatus = (U32)getBloodLeakStatus(); + bloodLeakData.bloodLeakState = (U32)bloodLeakState; + broadcastData( MSG_ID_HD_BLOOD_LEAK_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&bloodLeakData, sizeof( BLOOD_LEAK_DATA_T ) ); bloodLeakDataPublicationTimerCounter = 0; } } Index: firmware/App/Controllers/BloodLeak.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -41,6 +41,13 @@ NUM_OF_BLOOD_LEAK_STATUS ///< Number of blood leak detector status } BLOOD_LEAK_STATUS_T; +/// Blood leak detector data publish +typedef struct +{ + U32 bloodLeakStatus; ///< Blood leak detector status + U32 bloodLeakState; ///< Blood leak detector state +} BLOOD_LEAK_DATA_T; + // ********** public function prototypes ********** void initBloodLeak( void ); Index: firmware/App/Controllers/Bubble.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Bubble.c (.../Bubble.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Bubble.c (.../Bubble.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -339,10 +339,13 @@ // Publish air bubble detectors data on interval if ( ++bubblesDataPublicationTimerCounter >= getU32OverrideValue( &bubblesDataPublishInterval ) ) { - BUBBLE_STATUS_T statusADA = getBubbleStatus( ADA ); - BUBBLE_STATUS_T statusADV = getBubbleStatus( ADV ); + BUBBLES_DATA_T bubbleData; - broadcastBubblesData( (U32)statusADA, (U32)bubblesState[ ADA ], (U32)statusADV, (U32)bubblesState[ ADV ] ); + bubbleData.statusADA = (U32)getBubbleStatus( ADA ); + bubbleData.stateADA = (U32)bubblesState[ ADA ]; + bubbleData.statusADV = (U32)getBubbleStatus( ADV ); + bubbleData.stateADV = (U32)bubblesState[ ADV ]; + broadcastData( MSG_ID_HD_BUBBLES_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&bubbleData, sizeof( BUBBLES_DATA_T ) ); bubblesDataPublicationTimerCounter = 0; } } Index: firmware/App/Controllers/Bubble.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Bubble.h (.../Bubble.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Bubble.h (.../Bubble.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -37,19 +37,28 @@ /// Enumeration of air bubble detectors status. typedef enum BubblesStatus { - BUBBLE_DETECTED = 0, ///< Air bubble detector senses bubble - BUBBLE_NOT_DETECTED, ///< Air bubble detector does not sense any bubble - NUM_OF_BUBBLE_STATUS ///< Number of air bubble detector status + BUBBLE_DETECTED = 0, ///< Air bubble detector senses bubble + BUBBLE_NOT_DETECTED, ///< Air bubble detector does not sense any bubble + NUM_OF_BUBBLE_STATUS ///< Number of air bubble detector status } BUBBLE_STATUS_T; /// Air bubble detectors names typedef enum bubblesNames { - ADA = 0, ///< Arterial air bubble detector - ADV, ///< Venous air bubble detector - NUM_OF_BUBBLES ///< Number of air bubble detectors + ADA = 0, ///< Arterial air bubble detector + ADV, ///< Venous air bubble detector + NUM_OF_BUBBLES ///< Number of air bubble detectors } BUBBLES_T; +/// Bubble detectors data publish +typedef struct +{ + U32 statusADA; ///< Arterial bubble detector status + U32 stateADA; ///< Arterial bubble detector state + U32 statusADV; ///< Venous bubble detector status + U32 stateADV; ///< Venous bubble detector state +} BUBBLES_DATA_T; + // ********** public function prototypes ********** void initBubbles( void ); Index: firmware/App/Controllers/Buttons.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Buttons.c (.../Buttons.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -297,7 +297,7 @@ // If we are in a mode that allows power off, initiate power off sequence if ( TRUE == isCurrentOpModeOkToTurnOff() ) { - broadcastPowerOffWarning(); + broadcastData( MSG_ID_POWER_OFF_WARNING, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)0, 0 ); signalPowerOffWarning(); offButtonPressPending = TRUE; offRequestPulseCount = OFF_REQUEST_PULSE_COUNT; @@ -348,6 +348,24 @@ } return result; +} + +/*********************************************************************//** + * @brief + * The initiatePowerOff function initiates a power off sequence. + * @details Inputs: none + * @details Outputs: offRequestDelayTimer, offRequestPulseTimer, offRequestPulseCount, offButtonPressPending + * @return none + *************************************************************************/ +void initiatePowerOff( void ) +{ + // Warn NV Data Mgr that power will be lost shortly + signalPowerOffWarning(); + // Mimic confirmed power off button state to initiate power off cycle + offRequestDelayTimer = 0; + offRequestPulseTimer = 0; + offRequestPulseCount = OFF_REQUEST_PULSE_COUNT; + offButtonPressPending = TRUE; } /*********************************************************************//** Index: firmware/App/Controllers/Buttons.h =================================================================== diff -u -r1c628bfd5d6414b74b8cbd083f66839888a8236b -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Buttons.h (.../Buttons.h) (revision 1c628bfd5d6414b74b8cbd083f66839888a8236b) +++ firmware/App/Controllers/Buttons.h (.../Buttons.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file Buttons.h +* @file Buttons.h * -* @author (last) Sean Nash -* @date (last) 26-Aug-2020 +* @author (last) Quang Nguyen +* @date (last) 02-Dec-2020 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -79,7 +79,6 @@ static U32 resMgmtTimer = 0; ///< Used for keeping state time. // DG sensor data -static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. @@ -98,11 +97,10 @@ static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. -// DG pumps data -static F32 dgROPumpFlowRateMlMin = 0.0; ///< Latest RO water flow rate reported by the DG. -static U32 dgROPumpPressureSetPtPSI = 0; ///< Latest RO pump target pressure reported by the DG. -static U32 dgDrainPumpSpeedSetPtRPM = 0; ///< Latest Drain pump target speed reported by the DG. - +// DG Dialysate flow rate +static F32 dgDialysateFlowRateMlMin = 0.0; ///< Latest dialysate flow rate reported by the DG. +static BOOL dgDialysateFlowDataFreshFlag = FALSE; ///< Flag to signal the execDialInFlowMonitor() to process fresh flow rate data + // Reservoir data static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. @@ -138,7 +136,7 @@ dgTrimmerTempSet = 0.0; dgActiveReservoirSet = DG_RESERVOIR_2; dgReservoirFillVolumeTargetSet = 0; - dgReservoirDrainVolumeTargetSet = 0; + dgReservoirDrainVolumeTargetSet = 0; // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) @@ -267,7 +265,7 @@ { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, TRUE ); } } else if ( DG_MODE_DRAI == dgOpMode ) @@ -430,76 +428,38 @@ return ( dgActiveReservoir == dgActiveReservoirSet ); } -/*********************************************************************//** - * @brief - * The getDGPressure function gets the latest pressure reported by the DG - * for a given pressure sensor. - * @details Inputs: dgPressures[] - * @details Outputs: none - * @param sensorID pressure sensor we are getting reading for - * @return Latest pressure reading reported by DG for the given sensor. - *************************************************************************/ -F32 getDGPressure( DG_PRESSURE_SENSORS_T sensorID ) -{ - F32 result = 0.0; - - if ( sensorID < NUM_OF_DG_PRESSURE_SENSORS ) - { - result = dgPressures[ sensorID ]; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_PRESSURE_ID, sensorID ) - } - - return result; +/*********************************************************************//** + * @brief + * The getDGDialysateFlowRateLMin function gets the latest dialysate flow + * rate reported by the DG. + * @details Inputs: dgDialysateFlowRateMlMin + * @details Outputs: none + * @return Latest dialysate flow rate (in L/min) reported by DG. + *************************************************************************/ +F32 getDGDialysateFlowRateLMin( void ) +{ + F32 result = dgDialysateFlowRateMlMin; + + return result; } + +/*********************************************************************//** + * @brief + * The getDialysateFlowDataFreshFlag function returns a flag to indicate + * if the dialysate flow rate data reported by the DG is fresh or stale data. + * @details Inputs: dgDialysateFlowDataFreshFlag + * @details Outputs: dgDialysateFlowDataFreshFlag + * @return T/F flag to indicate fresh/stale status of dialysate flow data. + *************************************************************************/ +BOOL getDialysateFlowDataFreshFlag( void ) +{ + BOOL result = dgDialysateFlowDataFreshFlag; + + dgDialysateFlowDataFreshFlag = FALSE; + + return result; +} -/*********************************************************************//** - * @brief - * The getDGROPumpPressureSetPt function gets the latest RO pump - * pressure set point reported by the DG. - * @details Inputs: dgROPumpPressureSetPtPSI - * @details Outputs: none - * @return Latest RO pump pressure set point reported by DG. - *************************************************************************/ -U32 getDGROPumpPressureSetPt( void ) -{ - U32 result = dgROPumpPressureSetPtPSI; - - return result; -} - -/*********************************************************************//** - * @brief - * The getDGROPumpFlowRateMlMin function gets the latest RO pump flow - * rate reported by the DG. - * @details Inputs: dgROPumpFlowRateMlMin - * @details Outputs: none - * @return Latest RO pump flow rate reported by DG. - *************************************************************************/ -F32 getDGROPumpFlowRateMlMin( void ) -{ - F32 result = dgROPumpFlowRateMlMin; - - return result; -} - -/*********************************************************************//** - * @brief - * The getDGDrainPumpRPMSetPt function gets the latest drain pump RPM - * set point reported by the DG. - * @details Inputs: dgDrainPumpSpeedSetPtRPM - * @details Outputs: none - * @return Latest drain pump RPM set point reported by DG. - *************************************************************************/ -U32 getDGDrainPumpRPMSetPt( void ) -{ - U32 result = dgDrainPumpSpeedSetPtRPM; - - return result; -} - /*********************************************************************//** * @brief * The getLoadCellWeight function gets the current load cell weight. @@ -671,56 +631,24 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, resID ); } } - -/*********************************************************************//** - * @brief - * The setDGPressures function sets the latest pressures reported by the DG. - * @details Inputs: none - * @details Outputs: dgPressures[] - * @param roIn latest RO pump inlet pressure reported by DG - * @param roOut latest RO pump outlet pressure reported by DG - * @param drainIn latest drain pump inlet pressure reported by DG - * @param drainOut latest drain pump outlet pressure reported by DG - * @return none - *************************************************************************/ -void setDGPressures( F32 roIn, F32 roOut, F32 drainIn, F32 drainOut ) -{ - dgPressures[ DG_PRESSURE_SENSOR_RO_PUMP_INLET ] = roIn; - dgPressures[ DG_PRESSURE_SENSOR_RO_PUMP_OUTLET ] = roOut; - dgPressures[ DG_PRESSURE_SENSOR_DRAIN_PUMP_INLET ] = drainIn; - dgPressures[ DG_PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] = drainOut; -} - -/*********************************************************************//** - * @brief - * The setDGROPumpData function sets the latest RO pump data reported by the DG. - * @details Inputs: none - * @details Outputs: dgROPumpPressureSetPtPSI, dgROPumpFlowRateMlMin - * @param presSetPt latest RO pump pressure set point reported by DG - * @param flowRate latest RO pump flow rate (LPM) reported by DG - * @return none - *************************************************************************/ -void setDGROPumpData( U32 presSetPt, F32 flowRate ) -{ - dgROPumpPressureSetPtPSI = presSetPt; - dgROPumpFlowRateMlMin = flowRate * ML_PER_LITER; -} - -/*********************************************************************//** - * @brief - * The setDGDrainPumpData function sets the latest drain pump data reported by the DG. - * @details Inputs: none - * @details Outputs: dgDrainPumpSpeedSetPtRPM - * @param rpmSetPt latest drain pump RPM set point reported by DG - * @return none - *************************************************************************/ -void setDGDrainPumpData( U32 rpmSetPt ) -{ - dgDrainPumpSpeedSetPtRPM = rpmSetPt; -} - + /*********************************************************************//** * @brief + * The setDialysateFlowData function sets the latest dialysate flow rate + * and its freshness status. The dialysate flow data is reported by the DG. + * @details Inputs: none + * @details Outputs: dgDialysateFlowRateMlMin + * @param flowRate latest dialysate flow rate (mL/min) reported by DG + * @return none + *************************************************************************/ +void setDialysateFlowData( F32 flowRate ) +{ + dgDialysateFlowRateMlMin = flowRate; + dgDialysateFlowDataFreshFlag = TRUE; +} + +/*********************************************************************//** + * @brief * The setNewLoadCellReadings function sets the latest DG reservoir load cell * readings sent by the DG (in g or mL). New readings are expected once * every 100 ms. @@ -802,7 +730,7 @@ { dgStartCommandSent = TRUE; - sendDGStartStopCommand( START_DG_CMD ); + sendDGStartStopCommand( (BOOL)START_DG_CMD ); } /*********************************************************************//** @@ -817,7 +745,7 @@ { dgStarted = FALSE; - sendDGStartStopCommand( STOP_DG_CMD ); + sendDGStartStopCommand( (BOOL)STOP_DG_CMD ); } /*********************************************************************//** @@ -936,16 +864,19 @@ * @details Inputs: none * @details Outputs: drain command sent to DG. * @param drainToVolMl volume (in mL) to drain inactive reservoir to - * @param tareLoadCell flag to tell DG tare load cell or not + * @param tareLoadCell flag to tell DG tare load cell or not + * @param start flag to tell DG to start or stop the drain mode * @return none *************************************************************************/ -void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell ) +void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell, BOOL rinse, BOOL start ) { DRAIN_RESERVOIR_CMD_PAYLOAD_T payload; dgCmdResp[ DG_CMD_START_DRAIN ].commandID = DG_CMD_NONE; payload.drainToVolumeML = drainToVolMl; - payload.tareLoadCells = tareLoadCell; + payload.tareLoadCells = tareLoadCell; + payload.rinseConcentrateLines = rinse; + payload.cmd = start; dgReservoirDrainVolumeTargetSet = drainToVolMl; sendDGDrainCommand( &payload ); Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -37,40 +37,12 @@ #define FILL_RESERVOIR_TO_VOLUME_LOW_FLOW_ML 1300 ///< Fill reservoir to this volume (in mL) during treatment if dialysate flow is slow. #define SLOW_DIALYSATE_FLOW_ML_MIN 250 ///< Threshold for slow dialysate flow designation. -/// Enumeration of DG pressure sensors. -typedef enum DG_PressureSensors -{ - DG_PRESSURE_SENSOR_RO_PUMP_INLET = 0, ///< RO pump pressure sensor - DG_PRESSURE_SENSOR_RO_PUMP_OUTLET, ///< RO pump pressure sensor - DG_PRESSURE_SENSOR_DRAIN_PUMP_INLET, ///< Drain pump inlet pressure - DG_PRESSURE_SENSOR_DRAIN_PUMP_OUTLET, ///< Drain pump outlet pressure - NUM_OF_DG_PRESSURE_SENSORS ///< Number of pressure sensors -} DG_PRESSURE_SENSORS_T; - -/// Payload record structure for an RO pump data message. +/// Dialysate flow meter data struct. typedef struct { - U32 setPtPSI; ///< RO pump set target pressure - F32 measFlowRateMlMin; ///< RO pump measured flow rate in mL per min - F32 setPWMDutyCyclePct; ///< RO pump set PWM duty cycle percent -} DG_RO_PUMP_DATA_PAYLOAD_T; + F32 measuredDialysateFlowRate; ///< Dialysate flow meter rate average measurement +} DIALYSATE_FLOW_METER_DATA_T; -/// Payload record structure for a drain pump data message. -typedef struct -{ - U32 setPtRPM; ///< Drain pump set RPM value - F32 setDAC; ///< Drain pump set DAC value -} DG_DRAIN_PUMP_DATA_PAYLOAD_T; - -/// Payload record structure for a DG pressures data message. -typedef struct -{ - F32 roInPSI; ///< DG inlet pressure in PSI - F32 roOutPSI; ///< DG outlet pressure in PSI - F32 drainInPSI; ///< DG drain inlet pressure in PSI - F32 drainOutPSI; ///< DG drain outlet pressure in PSI -} DG_PRESSURES_DATA_PAYLOAD_T; - /// Payload record structure for a reservoirs data message. typedef struct { @@ -113,6 +85,8 @@ { U32 drainToVolumeML; ///< Drain to target volume in ml BOOL tareLoadCells; ///< Flag indicates to tare load cells or not + BOOL rinseConcentrateLines; ///< Flag indicates to rinse concentrate lines or not + BOOL cmd; ///< Flag indicates to start or stop the drain mode } DRAIN_RESERVOIR_CMD_PAYLOAD_T; /// DG command response data record structure. @@ -146,10 +120,8 @@ DG_RESERVOIR_ID_T getDGActiveReservoir( void ); DG_RESERVOIR_ID_T getDGInactiveReservoir( void ); BOOL hasDGCompletedReservoirSwitch( void ); -F32 getDGPressure( DG_PRESSURE_SENSORS_T sensorID ); -U32 getDGROPumpPressureSetPt( void ); -F32 getDGROPumpFlowRateMlMin( void ); -U32 getDGDrainPumpRPMSetPt( void ); +BOOL getDialysateFlowDataFreshFlag( void ); +F32 getDGDialysateFlowRateLMin( void ); F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ); F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ); F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ); @@ -160,9 +132,7 @@ void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ); void setDGDialysateTemperatures( F32 primaryHtrTemp, F32 trimmerHtrTemp ); void setDGReservoirsData( DG_RESERVOIR_ID_T resID, U32 fillVol, U32 drainVol ); -void setDGPressures( F32 roIn, F32 roOut, F32 drainIn, F32 drainOut ); -void setDGROPumpData( U32 presSetPt, F32 flowRate ); -void setDGDrainPumpData( U32 rpmSetPt ); +void setDialysateFlowData( F32 flowRate ); void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); void setDGDisinfectsStates( DG_DISINFECT_UI_STATES_T states ); @@ -172,8 +142,8 @@ void cmdSetDGActiveReservoir( DG_RESERVOIR_ID_T resID ); void cmdChangeDGValveSetting( DG_VALVE_SETTING_ID_T valveSettingID ); void cmdStartDGFill( U32 fillToVolMl ); -void cmdStopDGFill( void ); -void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell ); +void cmdStopDGFill( void ); +void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell, BOOL rinse, BOOL start ); void cmdStartDGTrimmerHeater( void ); void cmdStopDGTrimmerHeater( void ); void cmdDGSampleWater( SAMPLE_WATER_CMD_T cmd ); Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -rc653aeb570c11e65ab6859f966c6081c8e3de318 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision c653aeb570c11e65ab6859f966c6081c8e3de318) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -5,13 +5,13 @@ * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file DialInFlow.c +* @file DialInFlow.c * -* @author (last) H. Nguyen -* @date (last) 28-Oct-2021 +* @author (last) Dara Navaei +* @date (last) 06-Nov-2021 * -* @author (original) Sean -* @date (original) 16-Dec-2019 +* @author (original) Sean +* @date (original) 16-Dec-2019 * ***************************************************************************/ Index: firmware/App/Controllers/DialInFlow.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -56,20 +56,19 @@ BOOL setDialInPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir, PUMP_CONTROL_MODE_T mode ); void signalDialInPumpHardStop( void ); -void signalDialInPumpRotorHallSensor( void ); +void signalDialInPumpRotorHallSensor( void ); BOOL homeDialInPump( void ); BOOL isDialInPumpRunning( void ); SELF_TEST_STATUS_T execDialInFlowTest( void ); S32 getTargetDialInFlowRate( void ); -F32 getMeasuredDialInFlowRate( void ); -F32 getMeasuredDialInFlowSignalStrength( void ); +F32 getMeasuredDialInFlowRate( void ); F32 getMeasuredDialInPumpRotorSpeed( void ); F32 getMeasuredDialInPumpSpeed( void ); F32 getMeasuredDialInPumpMCSpeed( void ); F32 getMeasuredDialInPumpMCCurrent( void ); -F32 getDialInPumpPWMDutyCyclePct( void ); +F32 getDialInPumpPWMDutyCyclePct( BOOL init ); BOOL testSetDialInFlowDataPublishIntervalOverride( U32 value ); BOOL testResetDialInFlowDataPublishIntervalOverride( void ); @@ -84,8 +83,6 @@ BOOL testResetMeasuredDialInPumpMCSpeedOverride( void ); BOOL testSetMeasuredDialInPumpMCCurrentOverride( F32 value ); BOOL testResetMeasuredDialInPumpMCCurrentOverride( void ); -BOOL testSetMeasuredDialInFlowSignalStrengthOverride( F32 value ); -BOOL testResetMeasuredDialInFlowSignalStrengthOverride( void ); /**@}*/ Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -85,15 +85,14 @@ #define DOP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for dialysate outlet pump motor. #define DOP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000193 ///< ~52 BP motor RPM = 1% PWM duty cycle -#define UF_PWM_DC_PCT_PER_ML_PER_MIN 0.004 ///< Estimated DPo PWM duty cycle amount per each mL/min of ultrafiltration desired. #define DOP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for dialysate outlet pump motor. #define DOP_ADC_FULL_SCALE_V 3.0 ///< DPo analog signals are 0-3V (while int. ADC ref V may be different). #define DOP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DOP_ADC_ZERO ) ///< Macro converts a 12-bit ADC reading to a signed 16-bit value. /*** setDialOutFlowRxTotalVolumeAndRxTime ***/ -#define DOP_REV_PER_LITER 150.0 ///< Rotor revolutions per liter. +#define DOP_REV_PER_LITER 144.7 ///< Rotor revolutions per liter. #define DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DOP_REV_PER_LITER / ML_PER_LITER ) ///< Conversion factor from mL/min to pump motor RPM. #define DOP_GEAR_RATIO 32.0 ///< Pump motor to pump gear ratio. #define DOP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. @@ -151,6 +150,10 @@ static OVERRIDE_F32_T dialOutPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate outlet pump motor controller current. static OVERRIDE_F32_T dialOutPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate outlet pump rotor speed. static OVERRIDE_F32_T dialOutPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< Measured dialysate outlet pump motor speed. +#if 1 // TODO - remove test code +static F32 ufMeasuredRate = 0.0; +static F32 prevMeasuredVolumes[2] = { 0.0, 0.0 }; +#endif static U32 dopControlTimerCounter = 0; ///< Timer counter to determine when to control dialysate outlet pump. static U32 dopCurrErrorDurationCtr = 0; ///< Timer counter for motor current error persistence. @@ -515,7 +518,7 @@ } else { // Closed loop UF control is only controlling offset from DPi PWM - resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, (F32)( (S32)lastGivenRate - getTargetDialInFlowRate() ) * UF_PWM_DC_PCT_PER_ML_PER_MIN ); + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet - getDialInPumpPWMDutyCyclePct( TRUE ) ); } dialOutPumpControlModeSet = dialOutPumpControlMode; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); @@ -560,7 +563,7 @@ } else { // Closed loop UF control is only controlling offset from DPi PWM - resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, (F32)( (S32)lastGivenRate - getTargetDialInFlowRate() ) * UF_PWM_DC_PCT_PER_ML_PER_MIN ); + resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet - getDialInPumpPWMDutyCyclePct( TRUE ) ); } dialOutPumpControlModeSet = dialOutPumpControlMode; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); @@ -598,10 +601,16 @@ F32 totVol = getTotalMeasuredUFVolumeInMl(); F32 offsetPWMDutyCyclePct; +#if 1 // TODO - remove test code + ufMeasuredRate = ( totVol - prevMeasuredVolumes[1] ) * 6.0; // calculate UF rate based on change in volume over last 10 seconds + prevMeasuredVolumes[1] = prevMeasuredVolumes[0]; // update last 2 volumes for next time + prevMeasuredVolumes[0] = totVol; +#endif + // Get new PWM offset from PI controller offsetPWMDutyCyclePct = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); // Add PWM offset to DPi PWM mirror for our new DPo PWM - dialOutPumpPWMDutyCyclePctSet = getDialInPumpPWMDutyCyclePct() + offsetPWMDutyCyclePct; + dialOutPumpPWMDutyCyclePctSet = getDialInPumpPWMDutyCyclePct( FALSE ) + offsetPWMDutyCyclePct; // Limit PWM range dialOutPumpPWMDutyCyclePctSet = MIN( dialOutPumpPWMDutyCyclePctSet, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); dialOutPumpPWMDutyCyclePctSet = MAX( dialOutPumpPWMDutyCyclePctSet, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); @@ -703,12 +712,16 @@ dialOutBroadCastVariables.refUFVolMl = getTotalTargetDialOutUFVolumeInMl(); dialOutBroadCastVariables.measUFVolMl = getTotalMeasuredUFVolumeInMl(); dialOutBroadCastVariables.measRotSpdRPM = getMeasuredDialOutPumpRotorSpeed(); +#if 1 // TODO - remove test code + dialOutBroadCastVariables.measSpdRPM = ufMeasuredRate; +#else dialOutBroadCastVariables.measSpdRPM = getMeasuredDialOutPumpSpeed(); +#endif dialOutBroadCastVariables.measMCSpdRPM = getMeasuredDialOutPumpMCSpeed(); dialOutBroadCastVariables.measMCCurrmA = getMeasuredDialOutPumpMCCurrent(); dialOutBroadCastVariables.setPWMpct = dialOutPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; - broadcastDialOutFlowData( &dialOutBroadCastVariables); + broadcastData( MSG_ID_DIALYSATE_OUT_FLOW_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&dialOutBroadCastVariables, sizeof( DIAL_OUT_FLOW_DATA_T ) ); dialOutFlowDataPublicationTimerCounter = 0; } } Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r0aa4fbd4180c83d6cf274a361ed0ad3fc6a34965 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 0aa4fbd4180c83d6cf274a361ed0ad3fc6a34965) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -8,7 +8,7 @@ * @file Fans.c * * @author (last) Dara Navaei -* @date (last) 16-Aug-2021 +* @date (last) 15-Sep-2021 * * @author (original) Dara Navaei * @date (original) 04-Aug-2021 @@ -432,14 +432,18 @@ if ( TRUE == isAlarmTriggered ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_FAN_RPM_OUT_OF_RANGE, rpm ) + // Set the alarm flag to TRUE hasAlarmBeenRaised = TRUE; } - + // If the alarm has been raised but the time that the alarm has not been set, set the alarm start timer if ( ( TRUE == hasAlarmBeenRaised ) && ( 0 == rpmAlarmStartTimer ) ) { rpmAlarmStartTimer = getMSTimerCount(); } } + // If the alarm has been raised and the alarm has been silent for at least a day, set the flag to FALSE + // This way, if the fans RPM are out of range the alarm will be raised again. This alarm is supposed to be raised + // and remain silent for a define period of time. else if ( ( TRUE == hasAlarmBeenRaised ) && ( TRUE == didTimeout( rpmAlarmStartTimer, SECONDS_IN_A_DAY ) ) ) { hasAlarmBeenRaised = FALSE; Index: firmware/App/Controllers/FluidLeak.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/FluidLeak.c (.../FluidLeak.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/FluidLeak.c (.../FluidLeak.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -130,9 +130,9 @@ // Publish fluid leak state on interval if ( ++fluidLeakStatePublicationTimerCounter >= getU32OverrideValue( &fluidLeakStatePublishInterval ) ) { - FLUID_LEAK_STATES_T state = getFluidLeakState(); + U32 state = (U32)getFluidLeakState(); - broadcastFluidLeakState( state ); + broadcastData( MSG_ID_HD_FLUID_LEAK_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&state, sizeof( U32 ) ); fluidLeakStatePublicationTimerCounter = 0; } } Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r84e94699ac1a6236a6aba130e45149a9cf3ac5f8 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 84e94699ac1a6236a6aba130e45149a9cf3ac5f8) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file PresOccl.c +* @file PresOccl.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Dara Navaei +* @date (last) 14-Oct-2021 * -* @author (original) Sean -* @date (original) 15-Jan-2020 +* @author (original) Sean +* @date (original) 15-Jan-2020 * ***************************************************************************/ Index: firmware/App/Controllers/PresOccl.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -67,17 +67,18 @@ void execPresOcclTest( void ); SELF_TEST_STATUS_T execPresOcclDryTest( void ); -F32 getMeasuredArterialPressure( void ); -F32 getMeasuredVenousPressure( void ); -U32 getMeasuredBloodPumpOcclusion( void ); -U32 getMeasuredDialInPumpOcclusion( void ); -U32 getMeasuredDialOutPumpOcclusion( void ); +F32 getMeasuredArterialPressure( void ); +F32 getFilteredArterialPressure( void ); +F32 getLongFilteredArterialPressure( void ); +F32 getMeasuredVenousPressure( void ); +F32 getFilteredVenousPressure( void ); +U32 getMeasuredBloodPumpOcclusion( void ); BOOL isCartridgeLoaded( void ); BOOL isCartridgeUnloaded( void ); BOOL isSalineBagEmpty( void ); -void setOcclusionInstallLevels( void ); +void setOcclusionInstallLevel( void ); BOOL testSetPresOcclDataPublishIntervalOverride( U32 value ); BOOL testResetPresOcclDataPublishIntervalOverride( void ); @@ -87,10 +88,8 @@ BOOL testResetVenousPressureOverride( void ); BOOL testSetBloodPumpOcclusionOverride( U32 value ); BOOL testResetBloodPumpOcclusionOverride( void ); -BOOL testSetDialInPumpOcclusionOverride( U32 value ); -BOOL testResetDialInPumpOcclusionOverride( void ); -BOOL testSetDialOutPumpOcclusionOverride( U32 value ); -BOOL testResetDialOutPumpOcclusionOverride( void ); +BOOL testSetArterialPressureOffsetOverride( F32 value ); +BOOL testResetArterialPressureOffsetOverride( void ); /**@}*/ Index: firmware/App/Controllers/Switches.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Switches.c (.../Switches.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Switches.c (.../Switches.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -180,7 +180,7 @@ switchesDataPublicationCounter = 0; - broadcastSwitchesData( &data ); + broadcastData( MSG_ID_HD_SWITCHES_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SWITCHES_DATA_T ) ); } } Index: firmware/App/Controllers/Switches.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Switches.h (.../Switches.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Switches.h (.../Switches.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -15,7 +15,6 @@ * ***************************************************************************/ - #ifndef APP_CONTROLLERS_SWITCHES_H_ #define APP_CONTROLLERS_SWITCHES_H_ Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -196,8 +196,10 @@ static S32 syringePumpLastPositions[ SYRINGE_PUMP_SPEED_CALC_BUFFER_LEN ]; ///< Last encoder positions for the syringe pump. static U32 syringePumpMotorSpeedCalcIdx; ///< Index into 1 second buffer of syringe pump encoder positions. static U32 syringePumpSpeedCalcTimerCounter; ///< Used to calculate measured rate from change in position over time. +#ifndef DISABLE_SYRINGE_PUMP_ALARMS static MOTOR_DIR_T syringePumpControllerMeasuredDirection; ///< Measured direction of syringe pump per controller. static MOTOR_DIR_T syringePumpEncoderMeasuredDirection; ///< Measured direction of syringe pump per encoder position relative to previous. +#endif static BOOL syringePumpRetractRequested; ///< Flag indicates a retract operation is requested. static BOOL syringePumpSeekRequested; ///< Flag indicates a plunger seek operation is requested. @@ -275,8 +277,10 @@ syringePumpVolumeStartPosition = 0; syringePumpHomePositionOffset = 0; syringePumpLastPosition = 0; +#ifndef DISABLE_SYRINGE_PUMP_ALARMS syringePumpControllerMeasuredDirection = MOTOR_DIR_FORWARD; syringePumpEncoderMeasuredDirection = MOTOR_DIR_FORWARD; +#endif syringePumpDataPublicationTimerCounter = 0; syringePumpSpeedCalcTimerCounter = 0; @@ -519,17 +523,29 @@ { syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; - // Reset volume and start pos before starting prime operation - syringePumpVolumeDelivered.data = 0.0; - syringePumpSafetyVolumeDelivered = 0.0; - syringePumpVolumeStartPosition = getSyringePumpPosition(); + resetHeparinVolumeDelivered(); } return syringePumpPrimeRequested; } /*********************************************************************//** * @brief + * The resetHeparinVolumeDelivered function resets the Heparin volume delivered. + * @details Inputs: none + * @details Outputs: syringePumpVolumeDelivered, syringePumpSafetyVolumeDelivered, + * syringePumpVolumeStartPosition + * @return none + *************************************************************************/ +void resetHeparinVolumeDelivered( void ) +{ + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); +} + +/*********************************************************************//** + * @brief * The startHeparinBolus function requests Heparin bolus delivery. * @details Inputs: syringePumpState * @details Outputs: syringePumpSetRate, syringePumpBolusRequested @@ -550,10 +566,6 @@ { syringePumpSetRate = tgtRate; syringePumpBolusRequested = TRUE; - // Reset volume and start pos before starting bolus operation - syringePumpVolumeDelivered.data = 0.0; - syringePumpSafetyVolumeDelivered = 0.0; - syringePumpVolumeStartPosition = getSyringePumpPosition(); } } else @@ -930,6 +942,7 @@ static void execSyringePumpMonitor( void ) { F32 forceSensorBeforCal = 0.0; + BOOL prevSyringeDetected = isSyringeDetected(); // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) @@ -949,6 +962,11 @@ // Get latest ADC data and convert to V syringePumpMeasHome.data = ( (F32)getFPGASyringePumpADCChannel2() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; + // On transition from not detected to detected - clear syringe removed alarm condition + if ( ( prevSyringeDetected != TRUE ) && ( TRUE == isSyringeDetected() ) ) + { + clearAlarmCondition( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_REMOVED ); + } forceSensorBeforCal = ( (F32)getFPGASyringePumpADCChannel0() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasForce.data = pow(forceSensorBeforCal, 4) * forceSensorCalRecord.hdHeparinForceSensor.fourthOrderCoeff + @@ -965,10 +983,12 @@ calcSafetyVolumeDelivered(); // Calculate measured rate (mL/hr) calcMeasRate(); +#ifndef DISABLE_SYRINGE_PUMP_ALARMS // Get measured direction syringePumpControllerMeasuredDirection = ( ( getSyringePumpEncoderStatus() & SYRINGE_PUMP_ENCODER_DIRECTION_BIT ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); // Calculate direction from encoder position relative to last syringePumpEncoderMeasuredDirection = ( getSyringePumpPosition() - syringePumpLastPosition >= 0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); +#endif // Check if syringe pump is on while BP is off { @@ -1091,8 +1111,8 @@ * @brief * The handleSyringePumpInitState function handles the initialize state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: none + * @details Outputs: pump speed set to zero, ADC enabled, direction set to reverse * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpInitState( void ) @@ -1113,8 +1133,10 @@ * @brief * The handleSyringePumpOffState function handles the off state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpRetractRequested, syringePumpSeekRequested, + * syringePumpPrimeRequested, syringePumpBolusRequested, syringePumpContinuousRequested, + * syringePumpDACVrefSetRequested + * @details Outputs: Pump speed and direction set if pump command initiated * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ) @@ -1306,6 +1328,7 @@ if ( TRUE == stopPump ) { stopSyringePump(); + retractSyringePump(); result = SYRINGE_PUMP_OFF_STATE; } @@ -1619,13 +1642,13 @@ static BOOL checkMeasRate( BOOL stopPump, F32 pctMargin ) { BOOL result = stopPump; +#ifndef DISABLE_SYRINGE_PUMP_ALARMS F32 rate = getSyringePumpMeasRate(); F32 max = MAX( rate, syringePumpSetRate ); F32 min = MIN( rate, syringePumpSetRate ); - F32 delta = max - min; F32 error = ( max > 0.0 ? ( 1.0 - fabs( min / max ) ) : 0.0 ); + F32 delta = max - min; -#ifndef DISABLE_SYRINGE_PUMP_ALARMS // Alarm on rate if off by more than 5% or 0.1 mL/hr, whichever is greater if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) ) ) { @@ -1835,8 +1858,8 @@ ( (U32)getSyringePumpADCandDACStatus() << SHIFT_8_BITS_FOR_BYTE_SHIFT ) | ( (U32)getSyringePumpADCReadCounter() ); - broadcastSyringePumpData( data ); - broadcastHeparinData( data.syringePumpVolumeDelivered ); + broadcastData( MSG_ID_HD_SYRINGE_PUMP_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ) ); + broadcastData( MSG_ID_HD_HEPARIN_DATA_BROADCAST, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data.syringePumpVolumeDelivered, sizeof( F32 ) ); syringePumpDataPublicationTimerCounter = 0; } } @@ -1936,7 +1959,7 @@ * The testSyringePumpOperationRequest function requests a given syringe pump * operation. * @details Inputs: none - * @details Outputs: TBD + * @details Outputs: pump operation request is handled * @param opParams record containing the requested operation and its parameters * @return TRUE if override successful, FALSE if not *************************************************************************/ Index: firmware/App/Controllers/SyringePump.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -84,6 +84,7 @@ BOOL retractSyringePump( void ); BOOL seekSyringePlunger( void ); BOOL primeSyringePump( void ); +void resetHeparinVolumeDelivered( void ); BOOL startHeparinBolus( void ); BOOL startHeparinContinuous( void ); BOOL setSyringePumpDACVref( F32 vRef ); Index: firmware/App/Controllers/Temperatures.c =================================================================== diff -u -r9b831d8407ad2ac737a58f369455074306d5097a -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 9b831d8407ad2ac737a58f369455074306d5097a) +++ firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2021-2021 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file Temperatures.c +* @file Temperatures.c * -* @author (last) Dara Navaei -* @date (last) 01-Oct-2021 +* @author (last) Dara Navaei +* @date (last) 14-Oct-2021 * -* @author (original) Dara Navaei -* @date (original) 01-Oct-2021 +* @author (original) Dara Navaei +* @date (original) 01-Aug-2021 * ***************************************************************************/ @@ -43,7 +43,7 @@ #define ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_1 272.5 ///< ADC board temperature sensor conversion constant 1. #define ADC_BOARD_TEMP_SENSOR_CONVERSION_CONST_2 0x800000 ///< ADC board temperature sensor conversion constant 2. #define MIN_ALLOWED_TEMPERATURE 0.0 ///< Thermistors/sensors minimum allowed temperature reading. -#define MAX_ALLOWED_TEMPERATURE 120.0 ///< Thermistors/sensors maximum allowed temperature reading. +#define MAX_ALLOWED_TEMPERATURE 80.0 ///< Thermistors/sensors maximum allowed temperature reading. #define MAX_ALLOWED_TEMP_OUT_OF_RANGE_PERIOD ( 5 * MS_PER_SECOND ) ///< Thermistors/sensors maximum allowed temperature out of range period. /// Temperatures exec states @@ -265,21 +265,25 @@ static void monitorTemperatures( void ) { TEMPERATURES_T sensor; - BOOL isAlarmTriggered; - F32 temperature = 0.0; BOOL isTempOutOfRange = FALSE; + F32 temperature = 0.0; + U32 lastFaultSensor = 0; + F32 faultSensorTemp = 0.0; for ( sensor = THERMISTOR_ONBOARD_NTC; sensor < NUM_OF_TEMPERATURES; sensor++ ) { temperature = getTemperatureValue( sensor ); - isTempOutOfRange |= ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ); + if ( ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ) ) + { + isTempOutOfRange = TRUE; + lastFaultSensor = sensor; + faultSensorTemp = temperature; + } } - isAlarmTriggered = isPersistentAlarmTriggered( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, isTempOutOfRange ); - - if ( TRUE == isAlarmTriggered ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, isTempOutOfRange ) ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, temperature ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, lastFaultSensor, faultSensorTemp ); } } Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -re4cc37257141c5227186ac6d8ca3d6c87d009042 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision e4cc37257141c5227186ac6d8ca3d6c87d009042) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file Valves.c +* @file Valves.c * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 10-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 07-Aug-2020 +* @author (original) Dara Navaei +* @date (original) 07-Aug-2020 * ***************************************************************************/ @@ -20,6 +20,7 @@ #include "gio.h" #include "FPGA.h" +#include "MessageSupport.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskPriority.h" @@ -131,7 +132,7 @@ typedef enum valve_modes { VALVE_CONTROL_MODE_ENABLE_PID = 0, ///< Valve control mode enable PID - VALVE_CONTORL_MODE_ENABLE_BYPASS, ///< Valve control mode enable bypass + VALVE_CONTROL_MODE_ENABLE_BYPASS, ///< Valve control mode enable bypass VALVE_CONTROL_MODE_DISABLE_ALL, ///< Valve control mode disable all modes NUM_OF_VALVE_CONTROL_MODES, ///< Number of valve control modes } VALVE_MODE_T; @@ -169,7 +170,8 @@ { VALVE_POSITION_T commandedPosition; ///< Valve commanded position enum VALVE_POSITION_T currentPosition; ///< Valve current position enum - OVERRIDE_S32_T currentPositionInCounts; ///< Valve current position in counts + VALVE_POSITION_T pendingCommandedPosition; ///< Valve pending position enum + OVERRIDE_S32_T currentPositionInCounts; ///< Valve current position in counts S16 targetPositionInCounts; ///< Valve target position in counts BOOL hasTransitionBeenRequested; ///< Valve transition request flag VALVE_STATE_T execState; ///< Valve execution state @@ -257,8 +259,7 @@ /*********************************************************************//** * @brief * The initValves function initializes the valves driver. - * @details Inputs: valveSelfTestState, valvesSelfTestResult, valvesStatus, - * valvesControlSetBits + * @details Inputs: none * @details Outputs: valveSelfTestState, valvesSelfTestResult, valvesStatus * @return none *************************************************************************/ @@ -293,7 +294,7 @@ /*********************************************************************//** * @brief * The homeValve function sets the homing request flag of a valve to TRUE. - * @details Inputs: valvesStatus + * @details Inputs: none * @details Outputs: valvesStatus (The flag that sets the homing request) * @param valve that is set to be homed * @return none @@ -318,7 +319,7 @@ /*********************************************************************//** * @brief * The setValvePosition function sets the requested position of a valve. - * @details Inputs: valvesStatus + * @details Inputs: none * @details Outputs: valvesStatus * @param valve that its position is set * @param position that the valve is set @@ -330,11 +331,10 @@ // Valve not in position cannot be requested // All the other positions are valid - if ( ( position < NUM_OF_VALVE_POSITIONS ) && ( position != VALVE_POSITION_NOT_IN_POSITION ) && ( valve < NUM_OF_VALVES ) ) + if ( ( position != VALVE_POSITION_NOT_IN_POSITION ) && ( valve < NUM_OF_VALVES ) ) { - valvesStatus[ valve ].commandedPosition = position; + valvesStatus[ valve ].pendingCommandedPosition = position; valvesStatus[ valve ].hasTransitionBeenRequested = TRUE; - result = TRUE; } else @@ -372,7 +372,7 @@ /*********************************************************************//** * @brief * The getValveCurrent function returns the current of a valve. - * @details Inputs: none + * @details Inputs: valvesStatus * @details Outputs: valvesStatus * @param valve that the current is requested * @return returns the current of the valve in float @@ -393,7 +393,7 @@ * @brief * The setValveBloodTrap function set the blood trap valve to open or close * position. - * @details Inputs: valveAirTrapStatus + * @details Inputs: none * @details Outputs: valveAirTrapStatus * @param state enumeration of open or close for valve * @return: none @@ -532,8 +532,8 @@ /*********************************************************************//** * @brief * The handleValveSelfTestEnableValves function starts the valves self test. - * @details Inputs: valvesSelfTestResult, valvesSelfTestResult - * @details Outputs: valvesSelfTestResult, valvesSelfTestResult + * @details Inputs: none + * @details Outputs: valvesStatus, valvesSelfTestResult * @return next state of the self test state machine *************************************************************************/ static VALVE_SELF_TEST_STATE_T handleValveSelfTestEnableValves( void ) @@ -559,7 +559,7 @@ * @brief * The handleValveSelfTestConfirmEnable function checks to make sure the * valves are enabled properly. - * @details Inputs: valvesSelfTestResult + * @details Inputs: none * @details Outputs: valvesSelfTestResult * @return next state of the self test state machine *************************************************************************/ @@ -720,7 +720,7 @@ // Set the current position to Position C and the commanded position to Position A valvesStatus[ valve ].hasValveBeenHomed = TRUE; valvesStatus[ valve ].currentPosition = VALVE_POSITION_C_CLOSE; - valvesStatus[ valve ].commandedPosition = VALVE_POSITION_A_INSERT_EJECT; + valvesStatus[ valve ].pendingCommandedPosition = VALVE_POSITION_A_INSERT_EJECT; valvesStatus[ valve ].hasTransitionBeenRequested = TRUE; valvesStatus[ valve ].hasHomingBeenRequested = FALSE; valvesStatus[ valve ].numberOfFailedHomings = 0; @@ -783,34 +783,31 @@ } #endif - if ( valvesStatus[ valve ].hasHomingBeenRequested ) + if ( TRUE == valvesStatus[ valve ].hasHomingBeenRequested ) { state = VALVE_STATE_HOMING_NOT_STARTED; } - else if ( valvesStatus[ valve ].hasValveBeenHomed && valvesStatus[ valve ].hasTransitionBeenRequested ) + else if ( ( TRUE == valvesStatus[ valve ].hasValveBeenHomed ) && ( TRUE == valvesStatus[ valve ].hasTransitionBeenRequested ) ) { - if ( valvesStatus[ valve ].currentPosition != valvesStatus[ valve ].commandedPosition ) + if ( valvesStatus[ valve ].currentPosition != valvesStatus[ valve ].pendingCommandedPosition ) { // Just set the valves to transition so it will not be in a known position for a while - valvesStatus[ valve ].transitionStartTime = getMSTimerCount(); + valvesStatus[ valve ].commandedPosition = valvesStatus[ valve ].pendingCommandedPosition; + valvesStatus[ valve ].transitionStartTime = getMSTimerCount(); + valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; setValveNextStep( valve, TRANSITION_STEP_CHANGE_IN_COUNTS ); state = VALVE_STATE_IN_TRANSITION; } - else - { - valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; - } } // This option is only available in a debug build #ifdef DEBUG_ENABLED // Check if the valves have been homed and a bypass mode has been requested - else if ( valvesStatus[ valve ].hasValveBeenHomed && - valvesStatus[ valve ].bypassModeStatus.hasBypassModeBeenRequeseted ) + else if ( ( TRUE == valvesStatus[ valve ].hasValveBeenHomed ) && ( TRUE == valvesStatus[ valve ].bypassModeStatus.hasBypassModeBeenRequeseted ) ) { // Set the valve control mode to bypass and set the PWM - setValveControlMode( valve, VALVE_CONTORL_MODE_ENABLE_BYPASS ); - valvesStatus[ valve ].controlMode = VALVE_CONTORL_MODE_ENABLE_BYPASS; + setValveControlMode( valve, VALVE_CONTROL_MODE_ENABLE_BYPASS ); + valvesStatus[ valve ].controlMode = VALVE_CONTROL_MODE_ENABLE_BYPASS; valvesStatus[ valve ].bypassModeStatus.hasChangeBeenRequested = FALSE; setFPGAValvePWM( valve ); @@ -847,15 +844,12 @@ { // The valve is in range. Set the current position to the commanded position valvesStatus[ valve ].currentPosition = commandedPositionEnum; - // Set the transition request to false as it has been serviced - valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; // If we are in Pos B, enable current relaxation if ( commandedPositionEnum == VALVE_POSITION_B_OPEN ) { // Enable current relaxation setFPGAValveSetPoint( valve, currentPosition, TRUE ); - valvesStatus[ valve ].hasTransitionBeenRequested = TRUE; } // Go back to Idle state @@ -864,14 +858,14 @@ // Check if the valve's transition time has timed out else if ( didTimeout( valvesStatus[ valve ].transitionStartTime, VALVE_TRANSITION_TIMEOUT_MS ) ) { - valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; + //valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; TODO remove // Go back to Idle state state = VALVE_STATE_IDLE; #ifndef DISABLE_VALVE_ALARMS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT, (U32)valve ); #endif // If the valve transition timeout is active and the valve's commanded positions is position C, activate safety shutdown - if ( isAlarmActive( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT ) && valvesStatus[ valve ].commandedPosition == VALVE_POSITION_C_CLOSE ) + if ( ( TRUE == isAlarmActive( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT ) ) && ( VALVE_POSITION_C_CLOSE == valvesStatus[ valve ].commandedPosition ) ) { activateSafetyShutdown(); } @@ -924,8 +918,7 @@ /*********************************************************************//** * @brief * The setValveControlMode function sets the valves control mode. - * @details Inputs: valvesControlSetBits, valvesControlModesSetBits, - * valvesControlModesResetBits + * @details Inputs: none * @details Outputs: valvesControlSetBits * @param valve that its control mode is set * @param mode the control mode that the valve will be set to @@ -982,7 +975,7 @@ * The areValvesEnabled function checks the current valves status from FPGA * to the enable bit mask of each valve. If any of the valves is not enabled * the function raises an alarm. - * @details Inputs: valvesStatus, valvesControlStatusBits + * @details Inputs: valvesStatus * @details Outputs: none * @return Returns TRUE if all the valves are enabled properly *************************************************************************/ @@ -1015,7 +1008,7 @@ result = FALSE; } } - else if ( mode == VALVE_CONTORL_MODE_ENABLE_BYPASS ) + else if ( mode == VALVE_CONTROL_MODE_ENABLE_BYPASS ) { if ( ! ( status & VALVE_CONTROL_STATUS_BITS[ valve ][ VALVE_CONTROL_STATUS_BYPASS_ENABLED ] ) ) { @@ -1046,7 +1039,7 @@ /*********************************************************************//** * @brief - * The setFPGAValue function sets the position of a valve to FPGA. + * The setFPGAValveSetPoint function sets the position of a valve to FPGA. * @details Inputs: none * @details Outputs: none * @param valve that its FPGA set point is updated @@ -1385,7 +1378,7 @@ * @brief * The getValvesCurrentPWM function gets the PWM counts from the FPGA module * and converts them in to duty cycle in percent. - * @details Inputs: valvesStatus + * @details Inputs: none * @details Outputs: valvesStatus * @return none *************************************************************************/ @@ -1455,7 +1448,7 @@ * @brief * The testResetValvesDataPublishInterval function resets the override * of the valves publish interval. - * @details Inputs: valvesDataPublishInterval + * @details Inputs: none * @details Outputs: valvesDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ @@ -1476,7 +1469,7 @@ /*********************************************************************//** * @brief * The testSetValvesPositionOverride function overrides the valves position. - * @details Inputs: valvesPositionOverride, valvesStatus + * @details Inputs: none * @details Outputs: valvesPositionOverride * @param valve to override its position * @param position of the valve that will be overridden @@ -1566,7 +1559,7 @@ * @brief * The testResetValvePWMOverride function resets the override PWM in bypass * control mode. - * @details Inputs: valvesStatus + * @details Inputs: none * @details Outputs: valvesStatus * @param valve that its PWM override will be reset * @return TRUE if override reset successful, FALSE if not @@ -1639,8 +1632,8 @@ * @brief * The testSetValvesPositionCountOverride function overrides the valves * position in counts. - * @details Inputs: valvesPositionOverride, valvesStatus - * @details Outputs: valvesPositionOverride + * @details Inputs: valvesStatus + * @details Outputs: none * @param valve to override its position * @param position of the valve that will be overridden * @return TRUE if override successful, FALSE if not @@ -1665,7 +1658,7 @@ * @brief * The testResetValvesPositionCountOverride function resets the override * of the valves' position in counts. - * @details Inputs: valvesStatus + * @details Inputs: none * @details Outputs: valvesStatus * @param valve that its position count override will be reset * @return TRUE if override reset successful, FALSE if not Index: firmware/App/Controllers/Voltages.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Voltages.c (.../Voltages.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Controllers/Voltages.c (.../Voltages.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -52,9 +52,9 @@ 28.25, // MONITORED_LINE_24V_REGEN 1.3125, // MONITORED_LINE_FPGA_REF_V 3.3, // MONITORED_LINE_PBA_REF_V - 3.3, // MONITORED_LINE_FPGA_VCC_V - 3.3, // MONITORED_LINE_FPGA_AUX_V - 1.1 // MONITORED_LINE_FPGA_PVN_V + 1.1, // MONITORED_LINE_FPGA_VCC_V + 1.98, // MONITORED_LINE_FPGA_AUX_V + 0.1 // MONITORED_LINE_FPGA_PVN_V }; /// Minimum voltage/current level for each monitored signal. static const F32 MIN_VOLTAGES[ NUM_OF_MONITORED_LINES ] = @@ -67,9 +67,9 @@ 22.0, // MONITORED_LINE_24V_REGEN 1.1875, // MONITORED_LINE_FPGA_REF_V 2.7, // MONITORED_LINE_PBA_REF_V - 2.7, // MONITORED_LINE_FPGA_VCC_V - 2.7, // MONITORED_LINE_FPGA_AUX_V - 0.9 // MONITORED_LINE_FPGA_PVN_V + 0.9, // MONITORED_LINE_FPGA_VCC_V + 1.62, // MONITORED_LINE_FPGA_AUX_V + -0.1 // MONITORED_LINE_FPGA_PVN_V }; // ********** private data ********** @@ -147,8 +147,8 @@ * @brief * The handleVoltagesInitState function handles the initialize state * of the voltages monitor state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: none + * @details Outputs: none * @return next state *************************************************************************/ static VOLTAGES_STATE_T handleVoltagesInitState( void ) @@ -288,7 +288,7 @@ data.fpgaVaux = getMonitoredLineLevel( MONITORED_LINE_FPGA_AUX_V ); data.fpgaVpvn = getMonitoredLineLevel( MONITORED_LINE_FPGA_PVN_V ); - broadcastVoltagesData( data ); + broadcastData( MSG_ID_HD_VOLTAGES_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( VOLTAGES_DATA_PAYLOAD_T ) ); voltagesDataPublicationTimerCounter = 0; } } Index: firmware/App/Controllers/Voltages.h =================================================================== diff -u -r8f217e3f4f171dba78c9ac69a3470af442941a89 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision 8f217e3f4f171dba78c9ac69a3470af442941a89) +++ firmware/App/Controllers/Voltages.h (.../Voltages.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file Voltages.h +* @file Voltages.h * -* @author (last) Sean Nash -* @date (last) 15-Apr-2021 +* @author (last) Sean Nash +* @date (last) 30-Jul-2021 * -* @author (original) Sean -* @date (original) 15-Apr-2021 +* @author (original) Sean Nash +* @date (original) 15-Apr-2021 * ***************************************************************************/ Index: firmware/App/HDCommon.h =================================================================== diff -u -rb10be90b122eece9f2a300ede726bff6ced43ff0 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision b10be90b122eece9f2a300ede726bff6ced43ff0) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file HDCommon.h +* @file HDCommon.h * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @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 * ***************************************************************************/ @@ -25,7 +25,7 @@ #define HD_VERSION_MAJOR 0 #define HD_VERSION_MINOR 6 #define HD_VERSION_MICRO 0 -#define HD_VERSION_BUILD 0 +#define HD_VERSION_BUILD 24 // ********** development build switches ********** @@ -58,8 +58,9 @@ #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_VALVE_ALARMS 1 // Do not error on HD valve position - #define SKIP_CAL_CHECK 1 // + #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 RUN_PUMPS_OPEN_LOOP 1 // BP and DPi pumps will be run open loop (no flow sensor feedback) // #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 @@ -70,7 +71,7 @@ #define DISABLE_OCCLUSION_SELF_TEST 1 // Skip occlusion sensor self-test. // #define SKIP_CARTRIDGE_REMOVAL 1 // Skip cartridge removal check // #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters -// #define DISABLE_VOLTAGE_MONITOR 1 // Disable voltage monitoring/alarms + #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 Index: firmware/App/Modes/BloodPrime.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -36,22 +36,15 @@ // ********** private definitiions *********** -// TODO - get from Systems when available #define TARGET_BLOOD_PRIME_VOLUME_ML 300.0 ///< Target blood prime volume to prime the blood side circuit (in mL). -#define MIN_RAMP_TIME_SEC 60 ///< Minimum ramp time for blood prime (in seconds). +#define MAX_BLOOD_PRIME_VOLUME_ERROR_ML 60.0 ///< Maximum error in total additional blood prime volume (20% of total). +#define MIN_RAMP_TIME_SEC 60 ///< Minimum ramp time for blood prime (in seconds). -#ifndef DISABLE_PUMP_FLOW_CHECKS -/// Maximum blood prime volume measured by independent means (as % of target). -static const F32 MAX_BLOOD_PRIME_SAFETY_VOLUME_ML = ( TARGET_BLOOD_PRIME_VOLUME_ML * 1.2 ); -/// Minimum blood prime volume measured by independent means (as % of target). -static const F32 MIN_BLOOD_PRIME_SAFETY_VOLUME_ML = ( TARGET_BLOOD_PRIME_VOLUME_ML * 0.8 ); -#endif - /// Initial flow rate for blood pump when starting blood prime operation. #define BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN 100 /// Interval at which blood prime ramping is controlled. -static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +static const U32 BLOOD_PRIME_RAMPING_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Interval at which blood prime progress is to be published to UI. #define BLOOD_PRIME_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) @@ -71,16 +64,13 @@ /// Interval (in task intervals) at which to publish blood prime data to CAN bus. static OVERRIDE_U32_T bloodPrimePublishInterval = { BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, BLOOD_PRIME_DATA_PUBLISH_INTERVAL, 0 }; -static OVERRIDE_F32_T cumulativeBloodPrimeVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative blood prime volume (in mL). -static OVERRIDE_F32_T bloodPrimeVolumeDelivered_Safety = { 0.0, 0.0, 0.0, 0 }; ///< The cumulative independent blood prime volume (in mL) calculated so far. -static S32 bloodPrimeMotorCount; ///< The cumulative sum of BP motor encoder counts used for independent blood prime volume check. -static U32 bloodPrimeLastMotorCount; ///< The last BP motor encoder count read for independent blood prime volume check. +static OVERRIDE_F32_T cumulativeBloodPrimeVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative blood prime volume (in mL) from measured blood flow rate. +static F32 expectedBloodPrimeVolume_mL = 0.0; ///< Total cumulative blood prime volume (in mL) expected based on target blood flow rate. // ********** private function prototypes ********** static void resetBloodPrimeFlags( void ); static F32 getBloodPrimeVolume( void ); -static F32 getBloodPrimeSafetyVolume( void ); static BLOOD_PRIME_STATE_T handleBloodPrimeRampState( void ); static void publishBloodPrimeData( void ); @@ -98,11 +88,9 @@ bloodPrimeState = BLOOD_PRIME_RAMP_STATE; bloodPrimeRampControlTimerCtr = 0; - bloodPrimePublishTimerCtr = 0; + bloodPrimePublishTimerCtr = BLOOD_PRIME_DATA_PUBLISH_INTERVAL; cumulativeBloodPrimeVolume_mL.data = 0.0; - bloodPrimeVolumeDelivered_Safety.data = 0.0; - bloodPrimeMotorCount = 0; - bloodPrimeLastMotorCount = getBloodPumpMotorCount(); + expectedBloodPrimeVolume_mL = 0.0; resetBloodPrimeFlags(); bloodPrimeRampFlowRate_mL_min = (F32)BLOOD_PRIME_INIT_BP_FLOW_RATE_ML_MIN; @@ -194,26 +182,6 @@ /*********************************************************************//** * @brief - * The getBloodPrimeSafetyVolume function gets the calculated independent - * blood prime volume delivered. - * @details Inputs: bloodPrimeVolumeDelivered_Safety - * @details Outputs: none - * @return the current blood prime safety volume delivered (in mL). - *************************************************************************/ -static F32 getBloodPrimeSafetyVolume( void ) -{ - F32 result = bloodPrimeVolumeDelivered_Safety.data; - - if ( OVERRIDE_KEY == bloodPrimeVolumeDelivered_Safety.override ) - { - result = bloodPrimeVolumeDelivered_Safety.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The execBloodPrime function executes the Blood Prime sub-mode state machine. * @details Inputs: bloodPrimeState * @details Outputs: bloodPrimeState @@ -253,32 +221,21 @@ // Update blood prime volume delivered so far cumulativeBloodPrimeVolume_mL.data += ( getMeasuredBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); - // Update independent calculated safety volume delivered so far - bloodPrimeMotorCount = u32BiDiffWithWrap( bloodPrimeLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - bloodPrimeVolumeDelivered_Safety.data = ( (F32)bloodPrimeMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc + expectedBloodPrimeVolume_mL += ( (F32)getTargetBloodFlowRate() * BLOOD_PRIME_FLOW_INTEGRATOR ); // Has blood prime completed? if ( getBloodPrimeVolume() >= TARGET_BLOOD_PRIME_VOLUME_ML ) { -#ifndef DISABLE_PUMP_FLOW_CHECKS - // check for under-delivery - if ( getBloodPrimeSafetyVolume() < MIN_BLOOD_PRIME_SAFETY_VOLUME_ML ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE, TARGET_BLOOD_PRIME_VOLUME_ML, getBloodPrimeSafetyVolume() ); - } - else -#endif - { - setBloodIsPrimed( TRUE ); - signalDialInPumpHardStop(); - signalBloodPrimeToDialysis(); - } + setBloodIsPrimed( TRUE ); + signalDialInPumpHardStop(); + signalBloodPrimeToDialysis(); + cmdStopDGTrimmerHeater(); } #ifndef DISABLE_PUMP_FLOW_CHECKS - // Has independent safety volume exceeded safety limit? - else if ( getBloodPrimeSafetyVolume() > MAX_BLOOD_PRIME_SAFETY_VOLUME_ML ) + // Is blood prime taking too long based on set BP rate? + else if ( fabs( expectedBloodPrimeVolume_mL - getBloodPrimeVolume() ) > MAX_BLOOD_PRIME_VOLUME_ERROR_ML ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE, TARGET_BLOOD_PRIME_VOLUME_ML, getBloodPrimeSafetyVolume() ); + activateAlarmNoData( ALARM_ID_BLOOD_PRIME_VOLUME_CHECK_FAILURE ); } #endif else @@ -330,8 +287,8 @@ bloodPrimePublishTimerCtr = 0; data.targetBloodPrimeVolumeMl = TARGET_BLOOD_PRIME_VOLUME_ML; data.deliveredBloodPrimeVolumeMl = getBloodPrimeVolume(); - data.indDeliveredBloodPrimeVolumeMl = getBloodPrimeSafetyVolume(); - broadcastBloodPrimeData( data ); + data.unused = 0.0; // TODO - remove later when UI no longer looking for this field. + broadcastData( MSG_ID_HD_BLOOD_PRIME_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); } } @@ -388,51 +345,6 @@ /*********************************************************************//** * @brief - * The testSetBloodPrimeSafetyVolumeOverride function overrides the calculated - * blood prime volume. - * @details Inputs: none - * @details Outputs: bloodPrimeVolumeDelivered_Safety - * @param vol override calculated blood prime safety volume (in mL) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetBloodPrimeSafetyVolumeOverride( F32 vol ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - bloodPrimeVolumeDelivered_Safety.ovData = vol; - bloodPrimeVolumeDelivered_Safety.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetBloodPrimeSafetyVolumeOverride function resets the override of the - * calculated blood prime safety volume. - * @details Inputs: none - * @details Outputs: bloodPrimeVolumeDelivered_Safety - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetBloodPrimeSafetyVolumeOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - bloodPrimeVolumeDelivered_Safety.override = OVERRIDE_RESET; - bloodPrimeVolumeDelivered_Safety.ovData = bloodPrimeVolumeDelivered_Safety.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The testSetBloodPrimePublishIntervalOverride function sets the override of the * blood prime data publication interval. * @details Inputs: none Index: firmware/App/Modes/BloodPrime.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/BloodPrime.h (.../BloodPrime.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/BloodPrime.h (.../BloodPrime.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -41,7 +41,7 @@ { F32 targetBloodPrimeVolumeMl; F32 deliveredBloodPrimeVolumeMl; - F32 indDeliveredBloodPrimeVolumeMl; + F32 unused; } BLOOD_PRIME_DATA_PAYLOAD_T; // ********** public function prototypes ********** @@ -54,8 +54,6 @@ BOOL testSetBloodPrimeVolumeOverride( F32 vol ); BOOL testResetBloodPrimeVolumeOverride( void ); -BOOL testSetBloodPrimeSafetyVolumeOverride( F32 vol ); -BOOL testResetBloodPrimeSafetyVolumeOverride( void ); BOOL testSetBloodPrimePublishIntervalOverride( U32 ms ); BOOL testResetBloodPrimePublishIntervalOverride( void ); Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -47,8 +47,7 @@ #define MAX_SALINE_VOLUME_DELIVERED 800 ///< Maximum saline volume delivered for a treatment. #define SALINE_BOLUS_RATE_ML_MIN 150 ///< Fixed rate for saline bolus delivery. -#define MIN_SALINE_BOLUS_VOLUME_PCT 0.8 ///< Minimum saline bolus volume measured by independent means (as % of target). -#define MAX_SALINE_BOLUS_VOLUME_PCT 1.2 ///< Maximum saline bolus volume measured by independent means (as % of target). +#define MAX_BOLUS_ERROR_PCT 0.2 ///< Maximum error in saline bolus volume delivered (as a percentage of target). #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0 ///< Maximum delta between new and previous measured UF volume. @@ -78,11 +77,9 @@ static BOOL salineBolusStartRequested; ///< Flag indicates a saline bolus start has been requested by user. static BOOL salineBolusAbortRequested; ///< Flag indicates a salien bolus abort has been requested by user. static BOOL salineBolusAutoResumeUF = FALSE; ///< Flag indicates UF should be auto-resumed after saline bolus completes. -static F32 totalSalineVolumeDelivered; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). -static F32 bolusSalineVolumeDelivered; ///< Volume (mL) of current bolus delivered so far. -static F32 bolusSalineVolumeDelivered_Safety; ///< Volume (mL) of current bolus delivered so far according to safety monitor. -static S32 bolusSalineMotorCount; ///< Blood pump motor rev count during saline bolus to calculate saline bolus volume independently for safety. -static U32 bolusSalineLastMotorCount; ///< Last blood pump count from last saline bolus volume update. +static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). +static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). +static F32 expectedSalineBolusVolume_mL; ///< Volume (mL) of current bolus delivered so far (calculated from target blood flow rate). static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. static U32 uFAccuracyCheckTimerCtr; ///< Timer counter to determine when next to check ultrafiltration accuracy. @@ -139,7 +136,7 @@ setUFRate = 0.0; salineBolusBroadcastTimerCtr = 0; - totalSalineVolumeDelivered = 0.0; + totalSalineVolumeDelivered_mL = 0.0; uFAccuracyCheckTimerCtr = 0; lastUFVolumeChecked = 0.0; @@ -160,9 +157,8 @@ { salineBolusStartRequested = FALSE; salineBolusAbortRequested = FALSE; - bolusSalineVolumeDelivered = 0.0; - bolusSalineVolumeDelivered_Safety = 0.0; - bolusSalineMotorCount = 0; + bolusSalineVolumeDelivered_mL = 0.0; + expectedSalineBolusVolume_mL = 0.0; if ( currentSalineBolusState != SALINE_BOLUS_STATE_MAX_DELIVERED ) { currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; @@ -202,9 +198,17 @@ setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // Restart pumps #ifndef RUN_PUMPS_OPEN_LOOP +#ifndef RUN_BP_OPEN_LOOP setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); +#else + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); +#endif +#ifndef RUN_DPI_OPEN_LOOP setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); #else + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); +#endif +#else setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); #endif @@ -244,7 +248,7 @@ // If not done with bolus, start/resume bolus if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) { - startHeparinBolus(); // TODO - check return status + startHeparinBolus(); // TODO - check return status or have function trigger alarm if not successful } // Otherwise, start/resume continuous delivery else @@ -289,9 +293,17 @@ if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) { #ifndef RUN_PUMPS_OPEN_LOOP +#ifndef RUN_BP_OPEN_LOOP setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); +#else + setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); +#endif +#ifndef RUN_DPI_OPEN_LOOP setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); #else + setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); +#endif +#else setBloodPumpTargetFlowRate( setBloodFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); #endif @@ -323,8 +335,8 @@ * @brief * The signalStartSalineBolus function handles user request to initiate a * saline bolus. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusStartRequested, response sent * @return none *************************************************************************/ void signalStartSalineBolus( void ) @@ -345,7 +357,7 @@ { rejReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } - else if ( totalSalineVolumeDelivered >= (F32)MAX_SALINE_VOLUME_DELIVERED ) + else if ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) { rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; } @@ -367,8 +379,8 @@ * @brief * The signalAbortSalineBolus function handles user request to abort a * saline bolus. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: set bolus volume, current mode/sub-mode, bolus state + * @details Outputs: salineBolusAbortRequested, response sent * @return none *************************************************************************/ void signalAbortSalineBolus( void ) @@ -475,7 +487,7 @@ *************************************************************************/ F32 getTotalSalineBolusVolumeDelivered( void ) { - return totalSalineVolumeDelivered; + return totalSalineVolumeDelivered_mL; } /*********************************************************************//** @@ -857,10 +869,7 @@ if ( ( FALSE == isBloodPumpRunning() ) && ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) { // Reset bolus data before we start - bolusSalineVolumeDelivered = 0.0; - bolusSalineVolumeDelivered_Safety = 0.0; - bolusSalineMotorCount = 0; - bolusSalineLastMotorCount = getBloodPumpMotorCount(); + bolusSalineVolumeDelivered_mL = 0.0; bolusSalineLastVolumeTimeStamp = getMSTimerCount(); // Bypass dialyzer @@ -902,15 +911,16 @@ BOOL errorFound = FALSE; F32 timeSinceLastVolumeUpdateMin = (F32)calcTimeSince( bolusSalineLastVolumeTimeStamp ) / (F32)( MS_PER_SECOND * SEC_PER_MIN ); F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + F32 maxBolusErrorMl = bolusTargetVolume * MAX_BOLUS_ERROR_PCT; F32 bldFlowRate = getMeasuredBloodFlowRate(); // TODO - should I use raw flow instead of filtered here??? F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; + F32 expVolSinceLastUpdateMl = (F32)getTargetBloodFlowRate() * timeSinceLastVolumeUpdateMin; // Update saline bolus volumes bolusSalineLastVolumeTimeStamp = getMSTimerCount(); - bolusSalineVolumeDelivered += volSinceLastUpdateMl; - totalSalineVolumeDelivered += volSinceLastUpdateMl; - bolusSalineMotorCount = u32BiDiffWithWrap( bolusSalineLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - bolusSalineVolumeDelivered_Safety = ( (F32)bolusSalineMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc (from PBA). + bolusSalineVolumeDelivered_mL += volSinceLastUpdateMl; + totalSalineVolumeDelivered_mL += volSinceLastUpdateMl; + expectedSalineBolusVolume_mL += expVolSinceLastUpdateMl; // Check for empty saline bag per arterial line pressure if ( TRUE == isSalineBagEmpty() ) @@ -921,23 +931,15 @@ } // Determine if we have reached maximum saline delivery volume - if ( ( totalSalineVolumeDelivered >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) + if ( ( totalSalineVolumeDelivered_mL >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) { result = SALINE_BOLUS_STATE_MAX_DELIVERED; } else { // Determine if bolus is complete - if ( bolusSalineVolumeDelivered >= bolusTargetVolume ) + if ( bolusSalineVolumeDelivered_mL >= bolusTargetVolume ) { - // If safety thinks we have under-delivered the bolus, throw a fault - if ( bolusSalineVolumeDelivered_Safety < ( bolusTargetVolume * MIN_SALINE_BOLUS_VOLUME_PCT ) ) - { -#ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); - errorFound = TRUE; -#endif - } result = SALINE_BOLUS_STATE_IDLE; } // User is aborting saline bolus @@ -946,15 +948,15 @@ salineBolusAbortRequested = FALSE; result = SALINE_BOLUS_STATE_IDLE; } - // Determine if safety thinks we have over-delivered the bolus - else if ( bolusSalineVolumeDelivered_Safety > ( bolusTargetVolume * MAX_SALINE_BOLUS_VOLUME_PCT ) ) - { #ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); + // Determine if saline bolus is under/over delivering + else if ( fabs( expectedSalineBolusVolume_mL - bolusSalineVolumeDelivered_mL ) > maxBolusErrorMl ) + { + activateAlarmNoData( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE ); errorFound = TRUE; result = SALINE_BOLUS_STATE_IDLE; -#endif } +#endif } // Are we stopping the bolus? @@ -966,8 +968,8 @@ // Send last saline bolus data salineBolusBroadcastTimerCtr = SALINE_BOLUS_DATA_PUB_INTERVAL; publishSalineBolusData(); - sendTreatmentLogEventData( SALINE_BOLUSES_CHANGE_EVENT, bolusSalineVolumeDelivered, totalSalineVolumeDelivered ); - bolusSalineVolumeDelivered = 0.0; + sendTreatmentLogEventData( SALINE_BOLUSES_CHANGE_EVENT, bolusSalineVolumeDelivered_mL, totalSalineVolumeDelivered_mL ); + bolusSalineVolumeDelivered_mL = 0.0; // Dialysis back to UF state *dialysisState = DIALYSIS_UF_STATE; // End dialyzer bypass and resume dialysis if no alarms triggered @@ -1023,9 +1025,9 @@ SALINE_BOLUS_DATA_PAYLOAD_T data; data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - data.cumSalineVolumeMl = totalSalineVolumeDelivered; - data.bolSalineVolumeMl = bolusSalineVolumeDelivered; - broadcastSalineBolusData( data ); + data.cumSalineVolumeMl = totalSalineVolumeDelivered_mL; + data.bolSalineVolumeMl = bolusSalineVolumeDelivered_mL; + broadcastData( MSG_ID_SALINE_BOLUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SALINE_BOLUS_DATA_PAYLOAD_T ) ); salineBolusBroadcastTimerCtr = 0; } } Index: firmware/App/Modes/ModeFault.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -96,6 +96,8 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); stopSyringePump(); + // Request trimmer heater turned off + cmdStopDGTrimmerHeater(); // Ensure all valves are in safe position setValveAirTrap( STATE_CLOSED ); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r50fc6ca962c381ac98c9f032115973a5fff2a761 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 50fc6ca962c381ac98c9f032115973a5fff2a761) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file ModeInitPOST.c +* @file ModeInitPOST.c * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 10-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -305,13 +305,13 @@ * The signalDGPOSTFinalResult function records the final POST result for * the DG. * @details Inputs: none - * @details Outputs: dgPOSTPassed + * @details Outputs: dgPOSTPassed, dgPOSTResultReceived * @param passed TRUE if DG POST tests all passed, FALSE if any DG POST test failed * @return none *************************************************************************/ void signalDGPOSTFinalResult( BOOL passed ) { - dgPOSTPassed = passed; + dgPOSTPassed = passed; dgPOSTResultReceived = TRUE; } @@ -372,8 +372,8 @@ * @brief * The handlePOSTStatus function handles a status result returned by a * POST function. - * @details Inputs: postPassed - * @details Outputs: none + * @details Inputs: testStatus + * @details Outputs: tempPOSTPassed * @param testStatus status reported by last test * @return recommended next POST state *************************************************************************/ Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -63,7 +63,8 @@ static BOOL disposableRemovalConfirmed = FALSE; ///< Flag indicates user confirms disposable removal. static BOOL isDrainStarted = FALSE; ///< Flag indicates a drain operation has been started. -static BOOL isDrainCompleted = FALSE; +static BOOL isDrainCompleted = FALSE; ///< Flag indicates drain has completed. +static BOOL rinseConcentrateLines = FALSE; ///< FLag indicates to rinse concentrate lines. static HD_POST_TREATMENT_STATE_T currentPostTreatmentState; ///< Current state of post-treatment mode state machine. static DRAIN_STATE_T currentDrainReservoirState; ///< Current drain reservoir state. @@ -75,8 +76,9 @@ // ********** private function prototypes ********** -static HD_POST_TREATMENT_STATE_T handlePostTreatmentPatientDisconnectionState( void ); static HD_POST_TREATMENT_STATE_T handlePostTreatmentDrainReservoirsState( void ); +static HD_POST_TREATMENT_STATE_T handlePostTreatmentPatientDisconnectionState( void ); +static HD_POST_TREATMENT_STATE_T handlePostTreatmentDisposableRemovalState( void ); static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ); static void execDrainReservoirs( void ); @@ -99,7 +101,8 @@ disposableRemovalConfirmed = FALSE; isDrainStarted = FALSE; isDrainCompleted = FALSE; - currentPostTreatmentState = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; + rinseConcentrateLines = FALSE; + currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; currentDrainReservoirState = DRAIN_FIRST_RESERVOIR_START_STATE; postTreatmentPublishTimerCounter = 0; @@ -156,12 +159,16 @@ switch ( currentPostTreatmentState ) { + case HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE: + currentPostTreatmentState = handlePostTreatmentDrainReservoirsState(); + break; + case HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE: currentPostTreatmentState = handlePostTreatmentPatientDisconnectionState(); break; - case HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE: - currentPostTreatmentState = handlePostTreatmentDrainReservoirsState(); + case HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE: + currentPostTreatmentState = handlePostTreatmentDisposableRemovalState(); break; case HD_POST_TREATMENT_VERIFY_STATE: @@ -175,7 +182,9 @@ if ( ++postTreatmentPublishTimerCounter >= getU32OverrideValue( &postTreatmentModePublishInterval ) ) { - broadcastPostTreatmentState( currentPostTreatmentState ); + U32 state = (U32)currentPostTreatmentState; + + broadcastData( MSG_ID_HD_POST_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&state, sizeof( U32 ) ); postTreatmentPublishTimerCounter = 0; } @@ -312,6 +321,28 @@ /*********************************************************************//** * @brief + * The handlePostTreatmentDrainReservoirsState function executes drain reservoirs + * operation state machine and transition to next state once completed. + * @details Inputs: currentDrainReservoirState + * @details Outputs: executed drain reservoirs operation state machine. + * @return current state (sub-mode) + *************************************************************************/ +static HD_POST_TREATMENT_STATE_T handlePostTreatmentDrainReservoirsState( void ) +{ + HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; + + execDrainReservoirs(); + + if ( DRAIN_COMPLETE_STATE == currentDrainReservoirState ) + { + state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handlePostTreatmentPatientConnectionState function waits for user * confirms patient disconnection. * @details Inputs: none @@ -333,11 +364,11 @@ if ( TRUE == patientDisconnectionConfirmed ) { patientDisconnectionConfirmed = FALSE; - state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; + state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; - for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) { - homeValve( valve ); + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); } homeBloodPump(); @@ -360,28 +391,24 @@ /*********************************************************************//** * @brief - * The handlePostTreatmentDrainReservoirsState function executes drain reservoirs - * operation state machine and transition to next state once completed. - * @details Inputs: currentDrainReservoirState - * @details Outputs: executed drain reservoirs operation state machine. + * The handlePostTreatmentDisposableRemovalState function waits for user + * to confirm disposable removal. + * @details Inputs: disposableRemovalConfirmed + * @details Outputs: processed disposable removal confirmation * @return current state (sub-mode) *************************************************************************/ -static HD_POST_TREATMENT_STATE_T handlePostTreatmentDrainReservoirsState( void ) +static HD_POST_TREATMENT_STATE_T handlePostTreatmentDisposableRemovalState( void ) { - HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; + HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; - execDrainReservoirs(); - - if ( DRAIN_COMPLETE_STATE == currentDrainReservoirState ) - { #ifdef SKIP_UI_INTERACTION - disposableRemovalConfirmed = TRUE; + disposableRemovalConfirmed = TRUE; #endif - if ( TRUE == disposableRemovalConfirmed ) - { - disposableRemovalConfirmed = FALSE; - state = HD_POST_TREATMENT_VERIFY_STATE; - } + + if ( TRUE == disposableRemovalConfirmed ) + { + disposableRemovalConfirmed = FALSE; + state = HD_POST_TREATMENT_VERIFY_STATE; } return state; @@ -414,7 +441,7 @@ { activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); } - + // Wait for cartridge and syringe to be removed and for DG to finish any drains/fills. if ( ( TRUE == isCartridgeRemoved ) && ( FALSE == isSyringeDetected() ) ) { cmdStopDG(); @@ -486,7 +513,7 @@ } else { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); } } @@ -507,8 +534,14 @@ if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { - state = DRAIN_FIRST_RESERVOIR_STATE; - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + state = DRAIN_FIRST_RESERVOIR_STATE; + rinseConcentrateLines = TRUE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); + } } return state; @@ -566,7 +599,8 @@ if ( TRUE == hasDGCompletedReservoirSwitch() ) { state = DRAIN_SECOND_RESERVOIR_STATE; - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + rinseConcentrateLines = FALSE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); } return state; @@ -589,7 +623,7 @@ isDrainStarted = TRUE; } - // Drain has started and DG goes to re-circ mode flush lines state means drain completed + // Drain has started and DG goes to generation idle mode flush lines state means drain completed if ( ( TRUE == isDrainStarted ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_LINES == getDGSubMode() ) ) { isDrainCompleted = TRUE; @@ -601,6 +635,7 @@ { isDrainStarted = FALSE; isDrainCompleted = FALSE; + rinseConcentrateLines = FALSE; state = DRAIN_COMPLETE_STATE; } } Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -45,9 +45,15 @@ #define DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN 100 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. +#ifndef SKIP_PRIMING #define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume (in mL) to flush filter and lines. #define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. #define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 700 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. +#else +#define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML FILL_RESERVOIR_TO_VOLUME_ML +#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML FILL_RESERVOIR_TO_VOLUME_ML +#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML FILL_RESERVOIR_TO_VOLUME_ML +#endif #define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 ///< Primary heater target temperature offset from trimmer heater temperature. @@ -247,7 +253,13 @@ *************************************************************************/ void signalUserConfirmInstallation( void ) { - if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) ) + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + + // Accept installation confirmation if we are in install state of pre-treatment mode and syringe is detected or Heparin not being used in this treatment. + if ( ( MODE_PRET == getCurrentOperationMode() ) && + ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) && + ( ( TRUE == isSyringeDetected() ) || ( ( bolusVol < NEARLY_ZERO ) && ( hepRate < NEARLY_ZERO ) ) ) ) { confirmInstallRequested = TRUE; } @@ -436,7 +448,7 @@ preTreatmentData.recircState = getPreTreatmentRecircState(); preTreatmentData.patientConnectionState = 0; - broadcastPreTreatmentState( &preTreatmentData ); + broadcastData( MSG_ID_PRE_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&preTreatmentData, sizeof( PRE_TREATMENT_STATE_DATA_T ) ); preTreatmentPublishTimerCounter = 0; } } @@ -666,7 +678,7 @@ { if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) { - setOcclusionInstallLevels(); // Record occlusion pressure levels after a new cartridge is installed. + setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed. submodeCompleteTransitionTimeCounter = 0; state = HD_PRE_TREATMENT_PRIME_STATE; transitionToPrime(); @@ -767,7 +779,9 @@ if ( TRUE == treatmentStartRequested ) { DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); + setStartReservoirVolume( activeRes ); + resetHeparinVolumeDelivered(); // get clean starting volume/position before we start treatment requestNewOperationMode( MODE_TREA ); } @@ -872,7 +886,7 @@ if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) { state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, TRUE ); } } Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -113,6 +113,13 @@ setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + + // Set valves to default positions + setValveAirTrap( STATE_CLOSED ); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); } /*********************************************************************//** @@ -664,7 +671,7 @@ data.disinfectSubModeHDState = (U32)dgDisinfectState; - broadcastDisinfectsData( &data ); + broadcastData( MSG_ID_HD_DISINFECT_STANDBY_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( DISINFECTS_DATA_T ) ); dataPublishCounter = 0; } Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -80,9 +80,7 @@ static BOOL rinsebackDone; ///< Flag indicates whether a rinseback has been completed. Set FALSE at start of blood prime. Set TRUE at init and end of rinseback. static BOOL treatmentCompleted; ///< Flag indicates whether the treatment has completed. -static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in minutes). -static U32 presBloodFlowRate; ///< Prescribed blood flow rate (in mL/min). -static U32 presDialysateFlowRate; ///< Prescribed dialysate flow rate (in mL/min). +static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in seconds). static F32 presMaxUFVolumeML; ///< Prescribed ultrafiltration volume (in mL). static F32 presUFRate; ///< Prescribed ultrafiltration rate (in mL/min). @@ -166,8 +164,6 @@ treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode presTreatmentTimeSecs = 0; - presBloodFlowRate = 0; - presDialysateFlowRate = 0; presMaxUFVolumeML = 0.0; presUFRate = 0.0; @@ -685,8 +681,6 @@ lastTreatmentTimeStamp = getMSTimerCount(); presTreatmentTimeSecs = SEC_PER_MIN * getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - presBloodFlowRate = getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ); - presDialysateFlowRate = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); presMaxUFVolumeML = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; presUFRate = presMaxUFVolumeML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); @@ -724,7 +718,8 @@ { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } @@ -846,10 +841,10 @@ { TREATMENT_STATE_T result = TREATMENT_RINSEBACK_STATE; - // Execute treatment re-circ sub-mode + // Execute treatment rinseback sub-mode execRinseback(); - // Handle signals from treatment end sub-mode + // Handle signals from rinseback sub-mode if ( TRUE == rinsebackToRecircRequest ) { transitionToTreatmentRecirc(); @@ -883,7 +878,7 @@ // Execute treatment re-circ sub-mode execTreatmentRecirc(); - // Handle signals from treatment end sub-mode + // Handle signals from treatment re-circ sub-mode if ( TRUE == rinsebackToStoppedRequest ) { transitionToTreatmentStop(); @@ -919,6 +914,11 @@ { signalTreatmentEndAlarmEndTxUserAction(); } + // Handle alarm response from user to resume slow blood flow while waiting for rinseback request + else if ( TRUE == resumeTreatmentAlarmResponseRequest ) + { + signalTreatmentEndAlarmResumeUserAction(); + } // Execute treatment end sub-mode execTreatmentEnd(); @@ -958,7 +958,7 @@ ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= MIN_TREATMENT_TIME_MINUTES ) ) { F32 uFVolume; - U32 dialVolume = presDialysateFlowRate * treatmentTime; // In mL + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL // Always adjust UF volume to accommodate treatment time change (not UF rate) uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); @@ -970,7 +970,7 @@ sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), treatmentTime ); presMaxUFVolumeML = uFVolume; presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); } else { @@ -1048,9 +1048,9 @@ { DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); - F32 uFRate = uFVolume / ((F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN); // What UF rate would be if user selected to adjust it - U32 trtTime = (S32)( uFVolume / presUFRate ) + 1; // What the treatment duration would be if user selected to adjust it - U32 dialVolume = presDialysateFlowRate * trtTime; // What dialysate volume would be if user selected to adjust time + F32 uFRate = uFVolume / ((F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN); // What UF rate would be if user selected to adjust it + U32 trtTime = (S32)( uFVolume / presUFRate ) + 1; // What the treatment duration would be if user selected to adjust it + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * trtTime; // What dialysate volume would be if user selected to adjust time // UF should already be paused but let's make sure. if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && @@ -1098,7 +1098,7 @@ { if ( MODE_TREA != currMode ) { - rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || ( currentTreatmentState >= TREATMENT_END_STATE ) ) @@ -1155,7 +1155,8 @@ { presUFRate = pendingUFRateChange; } - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); // If UF paused, resume with new settings if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && @@ -1213,12 +1214,13 @@ ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; - sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, presBloodFlowRate, bloodRate ); - sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, presDialysateFlowRate, dialRate ); + sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); + sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); // Set to new rates - presBloodFlowRate = bloodRate; - presDialysateFlowRate = dialRate; - setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); + setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); + setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presMaxUFVolumeML, presUFRate ); } else { @@ -1240,7 +1242,8 @@ { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } - sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, presBloodFlowRate, presDialysateFlowRate ); + sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), + getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ); // Send new ranges for settings broadcastTreatmentSettingsRanges(); @@ -1374,16 +1377,15 @@ // Broadcast treatment time data at interval if ( ++treatmentTimeBroadcastTimerCtr >= getU32OverrideValue( &treatmentTimePublishInterval ) ) { + TREATMENT_TIME_DATA_T data = { 0, 0, 0 }; + if ( isTreatmentCompleted() != TRUE ) { - U32 timeRemaining = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; - - broadcastTreatmentTime( presTreatmentTimeSecs, elapsedTreatmentTimeInSecs, timeRemaining ); + data.treatmentTimePrescribedinSec = presTreatmentTimeSecs; + data.treatmentTimeElapsedinSec = elapsedTreatmentTimeInSecs; + data.treatmentTimeRemaininginSec = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; } - else // If treatment is completed, send zeroes to UI - { - broadcastTreatmentTime( 0, 0, 0 ); - } + broadcastData( MSG_ID_TREATMENT_TIME, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_TIME_DATA_T ) ); treatmentTimeBroadcastTimerCtr = 0; } // Broadcast treatment state data at interval @@ -1402,7 +1404,7 @@ payload.heparinState = getHeparinState(); payload.dialysisState = getDialysisState(); - broadcastTreatmentState( payload ); + broadcastData( MSG_ID_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TREATMENT_STATE_DATA_T ) ); treatmentStateBroadcastTimerCtr = 0; } } @@ -1428,7 +1430,7 @@ // Compute maximum treatment duration (from both UF and dialysate volume perspectives) U32 maxTimeRem = ( MAX_UF_VOLUME_ML - (U32)getUltrafiltrationReferenceVolume() ) / ( presUFRate > 0.0 ? (U32)presUFRate : 1 ); U32 maxTime1 = minTime + maxTimeRem; - U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / presDialysateFlowRate; + U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); U32 maxTime = MAX( maxTime1, maxTime2 ); // Compute minimum UF volume F32 minUFVol = getUltrafiltrationReferenceVolume() + presUFRate; @@ -1466,8 +1468,8 @@ if ( timeElapsedSinceLastCollect_ms >= TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) { - F32 const arterialPres = getMeasuredArterialPressure(); - F32 const venousPres = getMeasuredArterialPressure(); + F32 const arterialPres = getFilteredArterialPressure(); + F32 const venousPres = getFilteredVenousPressure(); lastTreatmentPeriodicDataCollectTimeStamp = treatmentTimeMS; bloodFlowRateSum_mL_min += getMeasuredBloodFlowRate(); Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -64,10 +64,10 @@ { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=4}, {.uInt=0} }, // TREATMENT_PARAM_DIALYZER_TYPE { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=60}, {.uInt=30} }, // TREATMENT_PARAM_BP_MEAS_INTERVAL { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=150}, {.uInt=75} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATE - { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=0}, {.sInt=-300} }, // TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=0}, {.sInt=0} }, // TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=600}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=600}, {.sInt=400} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=-30}, {.sInt=-300} }, // TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=-270}, {.sInt=100}, {.sInt=100} }, // TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=570}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=50}, {.sInt=600}, {.sInt=400} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=1.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_DISPENSE_RATE { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=2.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME { CRITICAL_DATA_TYPE_F32, {.sFlt=35.0}, {.sFlt=38.0}, {.sFlt=37.0} }, // TREATMENT_PARAM_DIALYSATE_TEMPERATURE Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -111,6 +111,7 @@ void execOperationModes( void ) { HD_OP_MODE_T newMode; + U32 priorSubMode = currentSubMode; // Any new mode requests? newMode = arbitrateModeRequest(); // Will return current mode if no pending requests @@ -127,6 +128,7 @@ if ( currentMode != newMode ) { // Handle transition to new mode + priorSubMode = 0; lastMode = currentMode; transitionToNewOperationMode( newMode ); currentMode = newMode; @@ -174,6 +176,13 @@ break; } // End switch + // Send sub-mode change event when appropriate + if ( priorSubMode != currentSubMode ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_MODE_CHANGE, priorSubMode, currentSubMode ) + } + priorSubMode = currentSubMode; + // Broadcast current operation mode on interval broadcastOperationMode(); } @@ -317,6 +326,8 @@ *************************************************************************/ static void transitionToNewOperationMode( HD_OP_MODE_T newMode ) { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_OP_MODE_CHANGE, lastMode, newMode ) + // Setup for new operating mode switch ( newMode ) { @@ -362,8 +373,12 @@ { if ( ++broadcastModeIntervalCtr >= getU32OverrideValue( &opModePublishInterval ) ) { + OP_MODE_PAYLOAD_T data; + broadcastModeIntervalCtr = 0; - broadcastHDOperationMode( (U32)currentMode, currentSubMode ); + data.opMode = (U32)currentMode; + data.subMode = currentSubMode; + broadcastData( MSG_ID_HD_OP_MODE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( OP_MODE_PAYLOAD_T ) ); } } Index: firmware/App/Modes/OperationModes.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/OperationModes.h (.../OperationModes.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/OperationModes.h (.../OperationModes.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -31,6 +31,13 @@ // ********** public definitions ********** +/// Payload record structure for op mode broadcast message +typedef struct +{ + U32 opMode; ///< Current operating mode + U32 subMode; ///< Current sub-mode of current operating mode +} OP_MODE_PAYLOAD_T; + // ********** public function prototypes ********** void initOperationModes( void ); // Initialize this module Index: firmware/App/Modes/Prime.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -319,7 +319,7 @@ primeData.totalTime = MAX_PRIME_TIME; primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; - broadcastPrimeData( &primeData ); + broadcastData( MSG_ID_HD_PRIMING_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&primeData, sizeof( PRIMING_DATA_PAYLOAD_T ) ); primeStatusBroadcastTimerCounter = 0; } } @@ -707,7 +707,7 @@ if ( TRUE == primeResumeRequested ) { primeResumeRequested = FALSE; - primeStartTime += calcTimeSince( primePauseStartTime ); + primeStartTime += calcTimeSince( primePauseStartTime ); // Adjust prime start time so we don't count pause time in prime duration calculation. switch ( previousPrimeState ) { Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -37,24 +37,22 @@ // ********** private definitions ********** -#define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). TODO - get from Systems when available -#define MAX_TOTAL_RINSEBACK_VOLUME_ML 400.0 ///< Maximum total rinseback volume allowed : main + all additionals (in mL). TODO - get from Systems when known -#define TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML 10.0 ///< Target rinseback volume for an additional volume request (in mL). -#define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. -#define MIN_RINSEBACK_FLOW_RATE_ML_MIN 50 ///< Minimum rinseback flow rate (in mL/min). -#define MAX_RINSEBACK_FLOW_RATE_ML_MIN 150 ///< Maximum rinseback flow rate (in mL/min). +#define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). TODO - get from Systems when available +#define MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML 300.0 ///< Maximum total additional rinseback volume allowed : all additionals (in mL). +#define MAX_RINSEBACK_VOLUME_ERROR_ML 60.0 ///< Maximum error in total additional rinseback volume (20% of total). +#define TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML 10.0 ///< Target rinseback volume for an additional volume request (in mL). +#define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. +#define MIN_RINSEBACK_FLOW_RATE_ML_MIN 50 ///< Minimum rinseback flow rate (in mL/min). +#define MAX_RINSEBACK_FLOW_RATE_ML_MIN 150 ///< Maximum rinseback flow rate (in mL/min). -#ifndef DISABLE_PUMP_FLOW_CHECKS -/// Maximum rinseback volume measured by independent means (as % of target). -static const F32 MAX_RINSEBACK_SAFETY_VOLUME_ML = ( TARGET_RINSEBACK_VOLUME_ML * 1.2 ); -/// Minimum rinseback volume measured by independent means (as % of target). -static const F32 MIN_RINSEBACK_SAFETY_VOLUME_ML = ( TARGET_RINSEBACK_VOLUME_ML * 0.8 ); -#endif - /// Interval at which rinseback progress is to be published to UI. #define RINSEBACK_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Maximum time allowed for rinseback operation until full volume is delivered. Timer is reset whenever BP is running. static const U32 MAX_RINSEBACK_TIME = ( 5 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); +/// Maximum time allowed after rinseback operation completed. Timer is reset whenever BP is running (additional). +static const U32 MAX_RINSEBACK_DONE_TIME = ( 15 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); +/// Warning time after rinseback operation completed. Timer is reset whenever BP is running (additional). +static const U32 RINSEBACK_DONE_WARNING_TIME = ( 13 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); /// Maximum time allowed for each additional rinseback volume delivery. static const U32 MAX_RINSEBACK_ADDITIONAL_TIME = ( 20 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. @@ -66,12 +64,11 @@ static U32 rinsebackRate_mL_min; ///< Rinseback rate to use/adjust for this current rinseback only. static U32 rinsebackTimerCtr; ///< Timer counter for time spent in rinseback sub-mode. -static OVERRIDE_F32_T cumulativeRinsebackVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative rinseback volume (in mL). -static OVERRIDE_F32_T rinsebackVolumeDelivered_Safety = { 0.0, 0.0, 0.0, 0 }; ///< The cumulative independent rinseback volume (in mL) calculated so far. +static OVERRIDE_F32_T cumulativeRinsebackVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative rinseback volume (in mL) from measured blood flow rate. +static F32 expectedRinsebackVolume_mL = 0.0; ///< Total cumulative rinseback volume (in mL) expected based on target blood flow rate. static F32 targetRinsebackVolumePlusAdditional_mL; ///< Target rinseback volume w/ additional volume(s) added (in mL). static F32 additionalRinsebackVolume_mL; ///< Total volume (in mL) delivered so far for additional volume request. -static S32 rinsebackMotorCount; ///< The cumulative sum of BP motor encoder counts used for independent rinseback volume check. -static U32 rinsebackLastMotorCount; ///< The last BP motor encoder count read for independent rinseback volume check. +static F32 totalAdditionalRinsebackVolume_mL; ///< Total accumulated volume (in mL) delivered so far for all additional volumes combined. static U32 rinsebackAdditionalTimerCtr; ///< Timer counter for duration of an additional rinseback delivery. static U32 rinsebackPublishTimerCtr; ///< Timer counter for determining interval for rinseback status to be published. /// Interval (in task intervals) at which to publish rinseback data to CAN bus. @@ -96,7 +93,6 @@ static void setupForRinsebackStopOrPause( void ); static F32 getRinsebackVolume( void ); -static F32 getRinsebackSafetyVolume( void ); static RINSEBACK_STATE_T handleRinsebackStopInitState( void ); static RINSEBACK_STATE_T handleRinsebackRunState( void ); @@ -132,10 +128,9 @@ targetRinsebackVolumePlusAdditional_mL = TARGET_RINSEBACK_VOLUME_ML; rinsebackTimerCtr = 0; cumulativeRinsebackVolume_mL.data = 0.0; - rinsebackVolumeDelivered_Safety.data = 0.0; + expectedRinsebackVolume_mL = 0.0; additionalRinsebackVolume_mL = 0.0; - rinsebackMotorCount = 0; - rinsebackLastMotorCount = getBloodPumpMotorCount(); + totalAdditionalRinsebackVolume_mL = 0.0; rinsebackAdditionalTimerCtr = 0; rinsebackPublishTimerCtr = 0; resetRinsebackFlags(); @@ -209,8 +204,8 @@ static void setupForRinsebackDelivery( U32 rate ) { // Open VBA and VBV valves to allow flow from saline bag and to patient venous line - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); // draw from saline back instead of patient + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); // return to patient // Start blood pump at rinseback flow rate setBloodPumpTargetFlowRate( rate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); // Start air trap leveling control @@ -259,26 +254,6 @@ /*********************************************************************//** * @brief - * The getRinsebackSafetyVolume function gets the calculated independent - * blood prime volume delivered. - * @details Inputs: rinsebackVolumeDelivered_Safety - * @details Outputs: none - * @return the current rinseback safety volume delivered (in mL). - *************************************************************************/ -static F32 getRinsebackSafetyVolume( void ) -{ - F32 result = rinsebackVolumeDelivered_Safety.data; - - if ( OVERRIDE_KEY == rinsebackVolumeDelivered_Safety.override ) - { - result = rinsebackVolumeDelivered_Safety.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The getCurrentRinsebackState function returns the current state of the * rinseback sub-mode. * @details Inputs: rinsebackState @@ -350,7 +325,6 @@ // Has user requested rinseback start? if ( TRUE == startRinsebackRequested ) { - rinsebackLastMotorCount = getBloodPumpMotorCount(); setupForRinsebackDelivery( rinsebackRate_mL_min ); // From moment we start rinseback, we consider blood side of dialyzer no longer fully primed setBloodIsPrimed( FALSE ); @@ -382,7 +356,7 @@ * The handleRinsebackRunState function handles the rinseback run state * operations. * @details Inputs: flags - * @details Outputs: cumulativeRinsebackVolume_mL, rinsebackVolumeDelivered_Safety, flags handled + * @details Outputs: cumulativeRinsebackVolume_mL, flags handled * @return next rinseback state *************************************************************************/ static RINSEBACK_STATE_T handleRinsebackRunState( void ) @@ -394,29 +368,22 @@ // Update rinseback volume delivered so far cumulativeRinsebackVolume_mL.data += ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); - // update independent calculated safety volume delivered so far - rinsebackMotorCount = u32BiDiffWithWrap( rinsebackLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - rinsebackVolumeDelivered_Safety.data = ( (F32)rinsebackMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc + expectedRinsebackVolume_mL += ( (F32)getTargetBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); // Has user requested to end rinseback? if ( TRUE == endRinsebackRequested ) { setupForRinsebackStopOrPause(); + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; } // Has rinseback completed? else if ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; -#ifndef DISABLE_PUMP_FLOW_CHECKS - // Check for under-delivery - if ( getRinsebackSafetyVolume() < MIN_RINSEBACK_SAFETY_VOLUME_ML ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, getRinsebackSafetyVolume() ); - } -#endif } // Check for empty saline bag if ( TRUE == isSalineBagEmpty() ) @@ -432,12 +399,12 @@ result = RINSEBACK_PAUSED_STATE; } #ifndef DISABLE_PUMP_FLOW_CHECKS - // Has independent safety volume exceeded safety limit? - else if ( getRinsebackSafetyVolume() > MAX_RINSEBACK_SAFETY_VOLUME_ML ) + // Is rinseback taking too long? + else if ( fabs( expectedRinsebackVolume_mL - getRinsebackVolume() ) > MAX_RINSEBACK_VOLUME_ERROR_ML ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, getRinsebackSafetyVolume() ); + activateAlarmNoData( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE ); result = RINSEBACK_STOP_STATE; } #endif @@ -495,6 +462,7 @@ // Has user requested to end rinseback? else if ( TRUE == endRinsebackRequested ) { + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; } @@ -513,23 +481,33 @@ { RINSEBACK_STATE_T result = RINSEBACK_STOP_STATE; - // If user confirms ready to start re-circulate sub-mode, go there - if ( TRUE == recircRequested ) + // Have we been in this stopped state for too long w/o having delivered full blood volume back to patient? + if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) ) { - signalRinsebackToRecirc(); + signalGoToTreatmentStopped(); + activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); } - // Has rinseback operation exceeded max time w/o delivering full volume? - if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) ) + // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? + else if ( ( rinsebackTimerCtr > MAX_RINSEBACK_DONE_TIME ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) { signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); + clearAlarm( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); } + // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? + else if ( ( RINSEBACK_DONE_WARNING_TIME == rinsebackTimerCtr ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + { + activateAlarmNoData( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); + } + else if ( TRUE == recircRequested ) + { + signalRinsebackToRecirc(); + } else if ( TRUE == additionalRinsebackRequested ) { additionalRinsebackRequested = FALSE; // deliver additional rinseback volume only if max volume not reached and max time not reached - if ( ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) && - ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) ) + if ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) { rinsebackAdditionalTimerCtr = 0; additionalRinsebackVolume_mL = 0.0; @@ -568,31 +546,46 @@ // update additional rinseback volume delivered so far additionalRinsebackVolume_mL += rinsebackVolumeSinceLast; + totalAdditionalRinsebackVolume_mL += rinsebackVolumeSinceLast; cumulativeRinsebackVolume_mL.data += rinsebackVolumeSinceLast; rinsebackAdditionalTimerCtr++; - // Has additional rinseback completed or timed out? - if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || - ( getRinsebackVolume() >= MAX_TOTAL_RINSEBACK_VOLUME_ML ) || - ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) - { - setupForRinsebackStopOrPause(); - result = RINSEBACK_STOP_STATE; - } // Check for empty saline bag if ( TRUE == isSalineBagEmpty() ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_EMPTY_SALINE_BAG, getMeasuredArterialPressure() ); - setupForRinsebackStopOrPause(); + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; } + // Has additional rinseback completed + else if ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) + { + result = RINSEBACK_STOP_STATE; + } + // Has additional rinseback timed out? + else if ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) + { + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); + result = RINSEBACK_STOP_STATE; + } // Has alarm requested stop? else if ( TRUE == doesAlarmStatusIndicateStop() ) { - setupForRinsebackStopOrPause(); + targetRinsebackVolumePlusAdditional_mL = getRinsebackVolume(); result = RINSEBACK_STOP_STATE; } + // Setup for rinseback stop state if additional rinseback completed or ending. + if ( RINSEBACK_STOP_STATE == result ) + { + setupForRinsebackStopOrPause(); + // If this additional rinseback volume has brought us to "full" rinseback volume, set flag + if ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) + { + setRinsebackIsCompleted( TRUE ); + } + } + return result; } @@ -716,6 +709,7 @@ { result = TRUE; incrRinsebackFlowRateRequested = TRUE; + rinsebackPublishTimerCtr = getPublishRinsebackInterval(); } else { @@ -750,6 +744,7 @@ { result = TRUE; decrRinsebackFlowRateRequested = TRUE; + rinsebackPublishTimerCtr = getPublishRinsebackInterval(); } else { @@ -861,7 +856,7 @@ if ( RINSEBACK_STOP_STATE == rinsebackState ) { - if ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) + if ( ( totalAdditionalRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML ) { result = TRUE; additionalRinsebackRequested = TRUE; @@ -901,6 +896,10 @@ { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } + else if ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) + { + *rejReason = REQUEST_REJECT_REASON_RINSEBACK_NOT_COMPLETED; + } else { result = TRUE; @@ -983,26 +982,35 @@ { RINSEBACK_DATA_PAYLOAD_T data; U32 timeout = MAX_RINSEBACK_TIME / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - U32 countdown = ( rinsebackTimerCtr >= MAX_RINSEBACK_TIME ? 0 : ( MAX_RINSEBACK_TIME - rinsebackTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + U32 countdown = ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ? MAX_RINSEBACK_DONE_TIME : MAX_RINSEBACK_TIME ); + countdown -= rinsebackTimerCtr; + // Handle countdown past zero + if ( countdown > MAX_RINSEBACK_DONE_TIME ) + { + countdown = 0; + } + // Scale to seconds + countdown /= ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + data.targetRinsebackVolumeMl = TARGET_RINSEBACK_VOLUME_ML; rinsebackPublishTimerCtr = 0; // If we have completed rinseback, timeout is no longer in force - indicate by zeroing timeout. Also include any additionals to target. if ( ( rinsebackState > RINSEBACK_PAUSED_STATE ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) { data.targetRinsebackVolumeMl = targetRinsebackVolumePlusAdditional_mL; - timeout = 0; + timeout = MAX_RINSEBACK_DONE_TIME / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); } data.deliveredRinsebackVolumeMl = getRinsebackVolume(); - data.safetyRinsebackVolumeMl = getRinsebackSafetyVolume(); data.rinsebackFlowRateMlMin = rinsebackRate_mL_min; if ( RINSEBACK_RUN_ADDITIONAL_STATE == rinsebackState ) { data.rinsebackFlowRateMlMin = MIN_RINSEBACK_FLOW_RATE_ML_MIN; } data.timeout = timeout; data.countdown = countdown; - broadcastRinsebackData( data ); + data.unused = 0.0; // TODO - remove when UI no longer looks for this field + broadcastData( MSG_ID_HD_RINSEBACK_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( RINSEBACK_DATA_PAYLOAD_T ) ); } } @@ -1079,51 +1087,6 @@ /*********************************************************************//** * @brief - * The testSetRinsebackSafetyVolumeOverride function overrides the calculated - * rinseback safety volume. - * @details Inputs: none - * @details Outputs: rinsebackVolumeDelivered_Safety - * @param vol override calculated rinseback safety volume (in mL) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetRinsebackSafetyVolumeOverride( F32 vol ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - rinsebackVolumeDelivered_Safety.ovData = vol; - rinsebackVolumeDelivered_Safety.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetRinsebackSafetyVolumeOverride function resets the override of the - * calculated rinseback safety volume. - * @details Inputs: none - * @details Outputs: rinsebackVolumeDelivered_Safety - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetRinsebackSafetyVolumeOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - rinsebackVolumeDelivered_Safety.override = OVERRIDE_RESET; - rinsebackVolumeDelivered_Safety.ovData = rinsebackVolumeDelivered_Safety.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The testSetRinsebackPublishIntervalOverride function sets the override of the * rinseback data publication interval. * @details Inputs: none Index: firmware/App/Modes/Rinseback.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/Rinseback.h (.../Rinseback.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/Rinseback.h (.../Rinseback.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -44,7 +44,7 @@ U32 rinsebackFlowRateMlMin; U32 timeout; U32 countdown; - F32 safetyRinsebackVolumeMl; + F32 unused; } RINSEBACK_DATA_PAYLOAD_T; #pragma pack(pop) @@ -60,8 +60,6 @@ BOOL testSetRinsebackVolumeOverride( F32 vol ); BOOL testResetRinsebackVolumeOverride( void ); -BOOL testSetRinsebackSafetyVolumeOverride( F32 vol ); -BOOL testResetRinsebackSafetyVolumeOverride( void ); BOOL testSetRinsebackPublishIntervalOverride( U32 ms ); BOOL testResetRinsebackPublishIntervalOverride( void ); Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -202,6 +202,10 @@ signalDialInPumpHardStop(); signalDialOutPumpHardStop(); stopSyringePump(); + setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); } /*********************************************************************//** @@ -312,7 +316,11 @@ if ( elapsedSelfTestTimeInSecs <= MAX_NO_CARTRIDGE_SELF_TEST_TIME ) { - broadcastNoCartSelfTestTime( MAX_NO_CARTRIDGE_SELF_TEST_TIME, ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); + SELF_TEST_NO_CARTRIDGE_PAYLOAD_T data; + + data.timeout = MAX_NO_CARTRIDGE_SELF_TEST_TIME; + data.countdown = ( MAX_NO_CARTRIDGE_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); + broadcastData( MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_NO_CARTRIDGE_PAYLOAD_T ) ); } else { @@ -443,7 +451,11 @@ if ( elapsedSelfTestTimeInSecs <= MAX_DRY_SELF_TEST_TIME ) { - broadcastDrySelfTestTime( MAX_DRY_SELF_TEST_TIME, ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ) ); + SELF_TEST_DRY_PAYLOAD_T data; + + data.timeout = MAX_DRY_SELF_TEST_TIME; + data.countdown = ( MAX_DRY_SELF_TEST_TIME - elapsedSelfTestTimeInSecs ); + broadcastData( MSG_ID_HD_DRY_SELF_TEST_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SELF_TEST_DRY_PAYLOAD_T ) ); } else { @@ -783,6 +795,10 @@ if ( STATE_CLOSED == getFPGADoorState() ) { state = DRY_SELF_TESTS_USED_CARTRIDGE_CHECK_STATE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); } if ( TRUE == doesAlarmStatusIndicateStop() ) @@ -848,8 +864,8 @@ } else { - previousNormalArterialPressure = getMeasuredArterialPressure(); - previousNormalVenousPressure = getMeasuredVenousPressure(); + previousNormalArterialPressure = getFilteredArterialPressure(); + previousNormalVenousPressure = getFilteredVenousPressure(); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); @@ -875,8 +891,8 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ) { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_STATE; - F32 const arterialPressure = getMeasuredArterialPressure(); - F32 const venousPressure = getMeasuredVenousPressure(); + F32 const arterialPressure = getFilteredArterialPressure(); + F32 const venousPressure = getFilteredVenousPressure(); // End the test when reaching target pressure or time out if ( ( TRUE == didTimeout( pressureSelfTestBloodPumpRunStartTime, BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ) ) || @@ -919,8 +935,8 @@ { DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_STATE; - F32 const arterialPressureDiff = fabs( getMeasuredArterialPressure() - previousNormalArterialPressure ); - F32 const venousPressureDiff = fabs( getMeasuredVenousPressure() - previousNormalVenousPressure ); + F32 const arterialPressureDiff = fabs( getFilteredArterialPressure() - previousNormalArterialPressure ); + F32 const venousPressureDiff = fabs( getFilteredVenousPressure() - previousNormalVenousPressure ); if ( TRUE == didTimeout( pressureSelfTestNormalizedStartTime, NORMALIZED_PRESSURE_SELF_TEST_TIME ) ) { Index: firmware/App/Modes/SelfTests.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/SelfTests.h (.../SelfTests.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/SelfTests.h (.../SelfTests.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -31,6 +31,20 @@ // ********** public definitions ********** +/// Payload record structure for no cartridge self-test data broadcast message +typedef struct +{ + U32 timeout; ///< No cartridge self-test timeout (in seconds) + U32 countdown; ///< No cartridge self-test timeout countdown (in seconds) +} SELF_TEST_NO_CARTRIDGE_PAYLOAD_T; + +/// Payload record structure for dry self-test data broadcast message +typedef struct +{ + U32 timeout; ///< Dry self-test timeout (in seconds) + U32 countdown; ///< Dry self-test timeout countdown (in seconds) +} SELF_TEST_DRY_PAYLOAD_T; + // ********** public function prototypes ********** void initSelfTests( void ); Index: firmware/App/Modes/TreatmentEnd.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/TreatmentEnd.c (.../TreatmentEnd.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -125,12 +125,13 @@ signalDialOutPumpHardStop(); stopSyringePump(); setBloodPumpTargetFlowRate( TX_END_BP_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + cmdStopDGTrimmerHeater(); // Continue air trap control startAirTrapControl(); // Set user alarm recovery actions allowed in this sub-mode - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); // Resume in this sub-mode indicates resume wait for user rinseback request (not resume treatment) setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); } @@ -146,6 +147,8 @@ *************************************************************************/ static void setupForTxEndWait4RinsebackState( void ) { + // No resume alarm action allowed + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, FALSE ); // Open VBA and VBV valves to allow flow from saline bag and to patient venous line setValvePosition( VBA, VALVE_POSITION_B_OPEN ); setValvePosition( VBV, VALVE_POSITION_B_OPEN ); @@ -167,6 +170,8 @@ *************************************************************************/ static void setupForTxEndPausedState( void ) { + // Resume alarm action will take us back to TxEndWait4RinsebackState + setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); // Stop blood pump signalBloodPumpHardStop(); // Close arterial and venous lines @@ -219,6 +224,19 @@ { TREATMENT_END_STATE_T result = TREATMENT_END_WAIT_FOR_RINSEBACK_STATE; + // Set reservoir 2 as active so we can drain reservoir 1 ASAP // TODO - I think this should be handled by treatment reservoir mgmt state machine + if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) + { + if ( getDGInactiveReservoir() != DG_RESERVOIR_1 ) + { + cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + } + else + { + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, FALSE, TRUE ); + } + } + // Is alarm stop or user reconnect requested? if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -279,12 +297,12 @@ // Ensure we do not sit in stopped state for too long if ( bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) { - activateAlarmNoData( ALARM_ID_BLOOD_SITTING_WARNING ); + activateAlarmNoData( ALARM_ID_END_OF_TREATMENT_ALARM ); } if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) { // Raise the alarm - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_NO_RINSEBACK ); + activateAlarmNoData( ALARM_ID_END_OF_TREATMENT_HIGH ); } } Index: firmware/App/Modes/TreatmentRecirc.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -34,8 +34,10 @@ // ********** private definitions ********** -/// Alarm if re-circulation is running for this much time. TODO - finalize these times w/ Systems +/// Maximum time allowed to be in recirculation sub-mode. static const U32 RECIRC_TIMEOUT = ( ( 15 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); +/// Warn user they need to reconnect to system and resume their treatment soon. +static const U32 RECIRC_WARNING_TIMEOUT = ( ( 13 * SEC_PER_MIN * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ); /// Re-circulation status broadcast interval. static const U32 RECIRC_DATA_PUBLISH_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Target flow rate for re-circulation of saline on blood-side circuit. @@ -47,6 +49,7 @@ static U32 recircTimerCtr; ///< Timer counter (in GP task intervals) counts time spent in re-circulation sub-mode. static U32 recircPublishTimerCtr; ///< Timer counter (in GP task intervals) counts time to next status broadcast. +static BOOL recircTimeoutWarningGiven; ///< Flag indicates 10 minute warning has been given to user. static BOOL recircReconnectRequested; ///< Flag indicates user requesting re-circulate stop so they can re-connect. static BOOL recircBackToTreatmenRequested; ///< Flag indicates user requesting to go back to treatment (confirming re-connected). @@ -84,6 +87,7 @@ recircTimerCtr = 0; recircPublishTimerCtr = 0; resetTreatmentRecircFlags(); + recircTimeoutWarningGiven = FALSE; } /*********************************************************************//** @@ -236,8 +240,14 @@ else if ( recircTimerCtr > RECIRC_TIMEOUT ) { signalGoToTreatmentStopped(); + clearAlarm( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); } + else if ( ( recircTimeoutWarningGiven != TRUE ) && ( RECIRC_WARNING_TIMEOUT == recircTimerCtr ) ) + { + recircTimeoutWarningGiven = TRUE; + activateAlarmNoData( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); + } return result; } @@ -276,6 +286,11 @@ signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); } + else if ( ( recircTimeoutWarningGiven != TRUE ) && ( recircTimerCtr > RECIRC_WARNING_TIMEOUT ) ) + { + recircTimeoutWarningGiven = TRUE; + activateAlarmNoData( ALARM_ID_HD_TREATMENT_RECIRC_TIMEOUT_WARNING ); + } return result; } @@ -462,11 +477,13 @@ { if ( ++recircPublishTimerCtr >= RECIRC_DATA_PUBLISH_INTERVAL ) { - U32 timeout = RECIRC_TIMEOUT / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - U32 countdown = ( recircTimerCtr >= RECIRC_TIMEOUT ? 0 : ( RECIRC_TIMEOUT - recircTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + TREATMENT_RECIRC_PAYLOAD_T data; + data.timeout = RECIRC_TIMEOUT / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + data.countdown = ( recircTimerCtr >= RECIRC_TIMEOUT ? 0 : ( RECIRC_TIMEOUT - recircTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + recircPublishTimerCtr = 0; - broadcastRecircData( timeout, countdown ); + broadcastData( MSG_ID_HD_RECIRC_PROGRESS, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_RECIRC_PAYLOAD_T ) ); } } Index: firmware/App/Modes/TreatmentRecirc.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/TreatmentRecirc.h (.../TreatmentRecirc.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/TreatmentRecirc.h (.../TreatmentRecirc.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -31,6 +31,15 @@ * @{ */ +// ********** public definitions ********** + +/// Payload record structure for treatment recirculate mode data broadcast message +typedef struct +{ + U32 timeout; ///< Recirculation timeout time (in seconds) + U32 countdown; ///< Recirculation timeout countdown (in seconds) +} TREATMENT_RECIRC_PAYLOAD_T; + // ********** public function prototypes ********** void initTreatmentRecirc( void ); Index: firmware/App/Modes/TreatmentStop.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/TreatmentStop.c (.../TreatmentStop.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -68,7 +68,7 @@ { currentTxStopState = TREATMENT_STOP_RECIRC_STATE; bloodSittingTimerCtr = 0; - stopPublishTimerCtr = 0; + stopPublishTimerCtr = TREATMENT_STOP_DATA_PUBLISH_INTERVAL; } /*********************************************************************//** @@ -140,16 +140,19 @@ *************************************************************************/ void execTreatmentStop( void ) { - // Ensure we do not sit in stopped state for too long - if ( ++bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) + // Ensure we do not sit in stopped state for too long (if blood in line) + if ( getRinsebackCompleted() != TRUE ) { - activateAlarmNoData( ALARM_ID_BLOOD_SITTING_WARNING ); + if ( ++bloodSittingTimerCtr > WARN_TIME_BLOOD_SITTING ) + { + activateAlarmNoData( ALARM_ID_BLOOD_SITTING_WARNING ); + } + if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) + { + // Activate the alarm + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_NO_RINSEBACK ); + } } - if ( bloodSittingTimerCtr > MAX_TIME_BLOOD_SITTING ) - { - // Activate the alarm - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_NO_RINSEBACK ); - } // Execute treatment stop sub-mode state machine switch ( currentTxStopState ) @@ -236,11 +239,19 @@ { if ( ++stopPublishTimerCtr >= getU32OverrideValue( &treatmentStopPublishInterval ) ) { - U32 timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - U32 countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + TREATMENT_STOP_PAYLOAD_T data; + data.timeout = MAX_TIME_BLOOD_SITTING / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + if ( getRinsebackCompleted() != TRUE ) + { + data.countdown = ( bloodSittingTimerCtr >= MAX_TIME_BLOOD_SITTING ? 0 : ( MAX_TIME_BLOOD_SITTING - bloodSittingTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + } + else + { + data.countdown = 0; + } stopPublishTimerCtr = 0; - broadcastTreatmentStopData( timeout, countdown ); + broadcastData( MSG_ID_HD_TREATMENT_STOP_TIMER_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_STOP_PAYLOAD_T ) ); } } Index: firmware/App/Modes/TreatmentStop.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Modes/TreatmentStop.h (.../TreatmentStop.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Modes/TreatmentStop.h (.../TreatmentStop.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -34,6 +34,13 @@ // ********** public definitions ****************** +/// Payload record for treatment stop mode broadcast message +typedef struct +{ + U32 timeout; ///< Blood sitting timeout (in seconds) + U32 countdown; ///< Blood sitting timeout countdown (in seconds) +} TREATMENT_STOP_PAYLOAD_T; + // ********** public function prototypes ********** void initTreatmentStop( void ); Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -336,8 +336,13 @@ { // Broadcast alarm and data if alarm not already active if ( FALSE == alarmIsActive[ alarm ] ) - { - broadcastAlarmTriggered( alarm, alarmData1, alarmData2 ); + { + ALARM_TRIGGERED_PAYLOAD_T data; + + data.alarm = (U32)alarm; + data.almData1 = alarmData1; + data.almData2 = alarmData2; + broadcastData( MSG_ID_ALARM_TRIGGERED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_TRIGGERED_PAYLOAD_T ) ); // Send information for UI to log to treatment log if ( ( TRUE == ALARM_TABLE[ alarm ].alarmTreatmentLog ) && ( MODE_TREA == getCurrentOperationMode() ) ) { @@ -364,8 +369,10 @@ // Clear alarm condition and broadcast alarm condition clear if not already cleared if ( TRUE == alarmIsDetected[ alarm ] ) { + U32 a = (U32)alarm; + alarmIsDetected[ alarm ] = FALSE; - broadcastAlarmConditionCleared( alarm ); + broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&a, sizeof( U32 ) ); } } } @@ -390,8 +397,10 @@ { // Clear alarm and broadcast alarm clear if not already cleared if ( TRUE == alarmIsActive[ alarm ] ) - { - broadcastAlarmCleared( alarm ); + { + U32 a = (U32)alarm; + + broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&a, sizeof( U32 ) ); alarmIsActive[ alarm ] = FALSE; clearAlarmCondition( alarm ); @@ -1175,7 +1184,7 @@ data.backupAudioCurr = getAlarmAudioBackupCurrent(); data.safetyShutdown = isSafetyShutdownActivated(); - broadcastAlarmInfo( data ); + broadcastData( MSG_ID_HD_ALARM_INFORMATION, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( ALARM_INFO_PAYLOAD_T ) ); alarmInfoPublicationTimerCounter = 0; } } @@ -1262,8 +1271,7 @@ /*********************************************************************//** * @brief * The execAlarmAudioSelfTest function outputs a test audio tone and - * measures the audio current level. The test passes if the audio current - * exceeds TBD mA. + * measures the audio current level. * @details Inputs: alarmAudioSelfTestState * @details Outputs: none * @return the current backup alarm audio current (in mA). @@ -1472,7 +1480,9 @@ { if ( TRUE == alarmIsActive[ a ] ) { - broadcastAlarmCleared( a ); + U32 al = (U32)a; + + broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&al, sizeof( U32 ) ); alarmIsActive[ a ] = FALSE; alarmStartedAt[ a ].data = 0; // Clear FIFO if this alarm was in it Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -121,13 +121,21 @@ /// Payload record structure for the alarm info message. typedef struct { - U32 audioVolume; ///< Audio volume level (1..5) - F32 audioCurrHG; ///< Primary alarm audio current - high gain (mA) - F32 audioCurrLG; ///< Primary alarm audio current - low gain (mA) - F32 backupAudioCurr; ///< Backup alarm audio current (mA) - BOOL safetyShutdown; ///< Safety shutdown activated? (T/F) + U32 audioVolume; ///< Audio volume level (1..5) + F32 audioCurrHG; ///< Primary alarm audio current - high gain (mA) + F32 audioCurrLG; ///< Primary alarm audio current - low gain (mA) + F32 backupAudioCurr; ///< Backup alarm audio current (mA) + BOOL safetyShutdown; ///< Safety shutdown activated? (T/F) } ALARM_INFO_PAYLOAD_T; +/// Payload record structure for the alarm triggered message. +typedef struct +{ + U32 alarm; ///< ID of alarm that was triggered + ALARM_DATA_T almData1; ///< Supporting data #1 + ALARM_DATA_T almData2; ///< Supporting data #2 +} ALARM_TRIGGERED_PAYLOAD_T; + #pragma pack(pop) #pragma pack(push, 2) Index: firmware/App/Services/CommBuffers.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Services/CommBuffers.c (.../CommBuffers.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -214,7 +214,7 @@ if ( ( len <= ( COMM_BUFFER_LENGTH * DOUBLE_BUFFERS ) ) && ( len <= numberOfBytesInCommBuffer( buffer ) ) ) { U32 activeBuffer = activeDoubleBuffer[ buffer ]; - U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 inactiveBuffer = GET_TOGGLE( activeBuffer, 0, 1 ); U32 bytesInInactiveBuffer = commBufferByteCount[ buffer ][ inactiveBuffer ]; U32 sizeOfFirstConsumption = MIN( len, bytesInInactiveBuffer ); @@ -223,7 +223,7 @@ // Will return # of bytes consumed result = sizeOfFirstConsumption; // Do we need more from active buffer? - if ( len > bytesInInactiveBuffer ) + if ( len > sizeOfFirstConsumption ) { U32 remNumOfBytes = len - sizeOfFirstConsumption; U08 *remPtr = data + sizeOfFirstConsumption; @@ -272,7 +272,7 @@ if ( ( len <= ( COMM_BUFFER_LENGTH * DOUBLE_BUFFERS ) ) && ( len <= numberOfBytesInCommBuffer( buffer ) ) ) { U32 activeBuffer = activeDoubleBuffer[ buffer ]; - U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 inactiveBuffer = GET_TOGGLE( activeBuffer, 0, 1 ); U32 bytesInInactiveBuffer = commBufferByteCount[ buffer ][ inactiveBuffer ]; if ( len <= bytesInInactiveBuffer ) @@ -345,7 +345,7 @@ static U32 switchDoubleBuffer( COMM_BUFFER_T buffer ) { U32 activeBuffer = activeDoubleBuffer[ buffer ]; - U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 inactiveBuffer = GET_TOGGLE( activeBuffer, 0, 1 ); // Ensure inactive buffer is reset before making active commBufferByteCount[ buffer ][ inactiveBuffer ] = 0; @@ -371,7 +371,7 @@ static void getDataFromInactiveBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ) { U32 activeBuffer = activeDoubleBuffer[ buffer ]; - U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 inactiveBuffer = GET_TOGGLE( activeBuffer, 0, 1 ); U32 bytesInInactiveBuffer = commBufferByteCount[ buffer ][ inactiveBuffer ]; // Get the requested data from inactive buffer Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -151,12 +151,12 @@ U16 bloodOcclusionData; ///< Reg 276. Blood pump occlusion sensor data. U08 bloodOcclusionReadCount; ///< Reg 278. Blood pump occlusion sensor read count. U08 bloodOcclusionErrorCount; ///< Reg 279. Blood pump occlusion sensor error count. - U16 dialysateInOcclusionData; ///< Reg 280. Dialysate inlet pump occlusion sensor data. - U08 dialysateInOcclusionReadCount; ///< Reg 282. Dialysate inlet pump occlusion sensor read count. - U08 dialysateInOcclusionErrorCount; ///< Reg 283. Dialysate inlet pump occlusion sensor error count. - U16 dialysateOutOcclusionData; ///< Reg 284. Dialysate outlet pump occlusion sensor data. - U08 dialysateOutOcclusionReadCount; ///< Reg 286. Dialysate outlet pump occlusion sensor read count. - U08 dialysateOutOcclusionErrorCount; ///< Reg 287. Dialysate outlet pump occlusion sensor error count. + U16 obsolete1; ///< Reg 280. Unused. + U08 obsolete2; ///< Reg 282. Unused. + U08 obsolete3; ///< Reg 283. Unused. + U16 obsolete4; ///< Reg 284. Unused. + U08 obsolete5; ///< Reg 286. Unused. + U08 obsolete6; ///< Reg 287. Unused. U16 bloodPumpHallSensorCount; ///< Reg 288. Blood pump hall sensor count. U08 bloodPumpHallSensorStatus; ///< Reg 290. Blood pump hall sensor status. U08 dialInPumpHallSensorStatus; ///< Reg 291. Dialysate inlet pump hall sensor status. @@ -1280,82 +1280,6 @@ /*********************************************************************//** * @brief - * The getFPGABloodFlow function gets the latest blood flow reading. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last blood flow reading - *************************************************************************/ -F32 getFPGABloodFlow( void ) -{ - return fpgaSensorReadings.bloodFlowLast; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodFlowMeterStatus function gets the blood flow meter status. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return current blood flow meter status - *************************************************************************/ -U08 getFPGABloodFlowMeterStatus( void ) -{ - return fpgaSensorReadings.bloodFlowMeterDeviceStatus; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodFlowFastPacketReadCounter function gets the blood - * flow meter fast packet read counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return current blood flow meter fast packet read counter - *************************************************************************/ -U08 getFPGABloodFlowFastPacketReadCounter( void ) -{ - return fpgaSensorReadings.bloodFlowMeterDataPktCount; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodFlowSlowPacketReadCounter function gets the blood - * flow meter slow packet read counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return current blood flow meter slow packet read counter - *************************************************************************/ -U08 getFPGABloodFlowSlowPacketReadCounter( void ) -{ - return ( fpgaSensorReadings.bloodFlowMeterSlowPktCounts & MASK_OFF_NIBBLE_LSB ) >> SHIFT_BITS_BY_4; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodFlowStatusPacketReadCounter function gets the blood - * flow meter status packet read counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return current blood flow meter status packet read counter - *************************************************************************/ -U08 getFPGABloodFlowStatusPacketReadCounter( void ) -{ - return ( fpgaSensorReadings.bloodFlowMeterSlowPktCounts & MASK_OFF_NIBBLE_MSB ); -} - -/*********************************************************************//** - * @brief - * The getFPGABloodFlowErrorCounter function gets the blood flow meter - * error counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return current blood flow meter error counter - *************************************************************************/ -U08 getFPGABloodFlowErrorCounter( void ) -{ - return fpgaSensorReadings.bloodFlowMeterErrorCount; -} - -/*********************************************************************//** - * @brief * The getFPGADialysateFlow function gets the latest dialysate flow reading. * @details Inputs: fpgaSensorReadings * @details Outputs: none @@ -1540,32 +1464,6 @@ /*********************************************************************//** * @brief - * The getFPGADialInPumpOcclusion function gets the latest dialysate - * inlet occlusion reading. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate inlet occlusion reading - *************************************************************************/ -U16 getFPGADialInPumpOcclusion( void ) -{ - return fpgaSensorReadings.dialysateInOcclusionData; -} - -/*********************************************************************//** - * @brief - * The getFPGADialOutPumpOcclusion function gets the latest dialysate - * outlet occlusion reading. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate outlet occlusion reading - *************************************************************************/ -U16 getFPGADialOutPumpOcclusion( void ) -{ - return fpgaSensorReadings.dialysateOutOcclusionData; -} - -/*********************************************************************//** - * @brief * The getFPGABloodPumpOcclusionReadCounter function gets the latest blood * pump occlusion read counter. * @details Inputs: fpgaSensorReadings @@ -1579,32 +1477,6 @@ /*********************************************************************//** * @brief - * The getFPGADialInPumpOcclusionReadCounter function gets the latest dialysate - * inlet pump occlusion read counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate inlet pump occlusion read counter - *************************************************************************/ -U08 getFPGADialInPumpOcclusionReadCounter( void ) -{ - return fpgaSensorReadings.dialysateInOcclusionReadCount; -} - -/*********************************************************************//** - * @brief - * The getFPGADialOutPumpOcclusionReadCounter function gets the latest dialysate - * outlet pump occlusion read counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate outlet pump occlusion read counter - *************************************************************************/ -U08 getFPGADialOutPumpOcclusionReadCounter( void ) -{ - return fpgaSensorReadings.dialysateOutOcclusionReadCount; -} - -/*********************************************************************//** - * @brief * The getFPGABloodPumpOcclusionErrorCounter function gets the latest blood * pump occlusion error counter. * @details Inputs: fpgaSensorReadings @@ -1618,32 +1490,6 @@ /*********************************************************************//** * @brief - * The getFPGADialInPumpOcclusionErrorCounter function gets the latest dialysate - * inlet pump occlusion error counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate inlet pump occlusion error counter - *************************************************************************/ -U08 getFPGADialInPumpOcclusionErrorCounter( void ) -{ - return fpgaSensorReadings.dialysateInOcclusionErrorCount; -} - -/*********************************************************************//** - * @brief - * The getFPGADialOutPumpOcclusionErrorCounter function gets the latest dialysate - * outlet pump occlusion error counter. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return last dialysate outlet pump occlusion error counter - *************************************************************************/ -U08 getFPGADialOutPumpOcclusionErrorCounter( void ) -{ - return fpgaSensorReadings.dialysateOutOcclusionErrorCount; -} - -/*********************************************************************//** - * @brief * The getFPGAArterialPressure function gets the latest arterial pressure reading. * High byte indicates alarm status for ADC channel. * Low 24-bits are channel reading. Subtract 2^23 from low 24 bits to get Index: firmware/App/Services/FPGA.h =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -62,13 +62,6 @@ F32 getFPGABloodFlowSignalStrength( void ); F32 getFPGADialysateFlowSignalStrength( void ); -F32 getFPGABloodFlow( void ); -U08 getFPGABloodFlowMeterStatus( void ); -U08 getFPGABloodFlowFastPacketReadCounter( void ); -U08 getFPGABloodFlowSlowPacketReadCounter( void ); -U08 getFPGABloodFlowStatusPacketReadCounter( void ); -U08 getFPGABloodFlowErrorCounter( void ); - F32 getFPGADialysateFlow( void ); U08 getFPGADialysateFlowMeterStatus( void ); U08 getFPGADialysateFlowFastPacketReadCounter( void ); @@ -90,14 +83,8 @@ U16 getFPGAVenousPressureTemperature( void ); U08 getFPGAVenousPressureReadCounter( void ); U16 getFPGABloodPumpOcclusion( void ); -U16 getFPGADialInPumpOcclusion( void ); -U16 getFPGADialOutPumpOcclusion( void ); U08 getFPGABloodPumpOcclusionReadCounter( void ); -U08 getFPGADialInPumpOcclusionReadCounter( void ); -U08 getFPGADialOutPumpOcclusionReadCounter( void ); U08 getFPGABloodPumpOcclusionErrorCounter( void ); -U08 getFPGADialInPumpOcclusionErrorCounter( void ); -U08 getFPGADialOutPumpOcclusionErrorCounter( void ); void setFPGASyringePumpControlFlags( U08 bitFlags ); void setFPGASyringePumpADCandDACControlFlags( U08 bitFlags ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r7de1ffc01a8b979c8e9c1bb9020a768ab62f0320 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 7de1ffc01a8b979c8e9c1bb9020a768ab62f0320) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file SystemComm.c +* @file SystemComm.c * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 09-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -195,7 +195,7 @@ if ( TRUE == isAlarmActive( ALARM_ID_DG_COMM_TIMEOUT ) ) { - clearAlarm( ALARM_ID_DG_COMM_TIMEOUT ); + clearAlarmCondition( ALARM_ID_DG_COMM_TIMEOUT ); } } @@ -1300,6 +1300,10 @@ handleHDUsageInfoRequest( message ); break; + case MSG_ID_HD_STOP_RTC_CLOCK: + handleStopHDRTCClock( message ); + break; + // NOTE: this always must be the last case case MSG_ID_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -re45524455c005d4fa1734efcbaf7ed0499302670 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e45524455c005d4fa1734efcbaf7ed0499302670) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file SystemCommMessages.c +* @file SystemCommMessages.c * -* @author (last) Peman Montazemi -* @date (last) 18-Mar-2021 +* @author (last) Dara Navaei +* @date (last) 09-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -6722,4 +6722,26 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } + +/*********************************************************************//** +* @brief +* The handleStopHDRTCClock function handles a request to stop the RTC clock. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleStopHDRTCClock( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( 0 == message->hdr.payloadLen ) + { + result = testSetStopRTC(); + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -re45524455c005d4fa1734efcbaf7ed0499302670 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision e45524455c005d4fa1734efcbaf7ed0499302670) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file SystemCommMessages.h +* @file SystemCommMessages.h * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Dara Navaei +* @date (last) 06-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -23,6 +23,7 @@ #include "BloodLeak.h" #include "BloodPrime.h" #include "Bubble.h" +#include "CommBuffers.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" @@ -56,7 +57,10 @@ * @{ */ -// ********** public definitions ********** +// ********** public definitions ********** + +#define ACK_REQUIRED TRUE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. +#define ACK_NOT_REQUIRED FALSE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. #define ACK_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. @@ -67,7 +71,10 @@ U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); // ACK MSG -BOOL sendACKMsg( MESSAGE_T *message ); +BOOL sendACKMsg( MESSAGE_T *message ); + +// Serialize message +U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); // MSG_ID_DG_CHECK_IN void handleDGCheckIn( MESSAGE_T *message ); @@ -753,6 +760,9 @@ // 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 ); + /**@}*/ #endif Index: firmware/App/Services/WatchdogMgmt.c =================================================================== diff -u -r1c628bfd5d6414b74b8cbd083f66839888a8236b -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 1c628bfd5d6414b74b8cbd083f66839888a8236b) +++ firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-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. * -* @file WatchdogMgmt.c +* @file WatchdogMgmt.c * -* @author (last) Sean Nash -* @date (last) 24-Sep-2020 +* @author (last) Sean Nash +* @date (last) 06-Aug-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ Index: firmware/App/Tasks/TaskBG.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -16,12 +16,14 @@ ***************************************************************************/ #include "Battery.h" +#include "Buttons.h" #include "HDCommon.h" #include "NVDataMgmt.h" #include "SafetyShutdown.h" #include "SystemComm.h" #include "TaskTimer.h" -#include "Timers.h" +#include "Timers.h" +#include "Voltages.h" #include "WatchdogMgmt.h" /** @@ -31,7 +33,7 @@ // ********** private definitions ********** -#define MAX_TIME_FOR_UI_TO_COMMUNICATE_MS 30000 ///< Maximum time we wait for UI to communicate after power up (30 seconds). +#define MAX_TIME_FOR_UI_TO_COMMUNICATE_MS 40000 ///< Maximum time we wait for UI to communicate after power up (40 seconds). // ********** private data ********** @@ -59,13 +61,14 @@ if ( FALSE == uiCommunicated() ) { #ifndef BOARD_WITH_NO_HARDWARE -#ifndef SIMULATE_UI +#ifndef SIMULATE_UI + // Check timeout waiting for UI to check in (via CAN) after startup. if ( TRUE == didTimeout( startUICommTimeout, MAX_TIME_FOR_UI_TO_COMMUNICATE_MS ) ) { activateAlarmNoData( ALARM_ID_UI_COMM_POST_FAILED ); - } + } #endif -#endif +#endif } // Manage the watchdog Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -48,7 +48,7 @@ * Calls the executive functions for most monitors and controllers, the * operation modes, the system communications, and alarms. * @details Inputs: none - * @details Outputs: Executive for the TBD called. + * @details Outputs: Executives running in general task are called. * @return none *************************************************************************/ void taskGeneral( void ) Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -rccfd15568f1e3d304320c2babb2fd4bcf0413304 -r8bd1ae47aa13a843aa8abd6321ddc050deacb4a6 --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision ccfd15568f1e3d304320c2babb2fd4bcf0413304) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 8bd1ae47aa13a843aa8abd6321ddc050deacb4a6) @@ -43,7 +43,7 @@ * The taskPriority function handles the scheduled Priority Task interrupt. * Calls the executive functions for FPGA, pumps, valves, and buttons. * @details Inputs: none - * @details Outputs: Executive for the FPGA, pumps, valves, and buttons called. + * @details Outputs: Executives running in priority task are called. * @return none *************************************************************************/ void taskPriority( void )