Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -59,7 +59,10 @@ #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_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the blood pump speed is calculated. +/// 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. +#define BP_SPEED_CALC_BUFFER_LEN ( 1000 / BP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) #define BP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define BP_MAX_ROTOR_SPEED_RPM 100.0 ///< maximum rotor speed allowed for blood pump. @@ -150,12 +153,12 @@ /// 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 OVERRIDE_S32_T targetBloodFlowRate = { 0, 0, 0, 0 }; ///< requested blood flow rate (mL/min) -static OVERRIDE_F32_T measuredBloodFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< measured blood flow rate (mL/min) -static OVERRIDE_F32_T bloodPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump rotor speed (RPM) -static OVERRIDE_F32_T bloodPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor speed (RPM) -static OVERRIDE_F32_T adcBloodPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller speed (RPM) -static OVERRIDE_F32_T adcBloodPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller current (mA) +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 U32 bpControlTimerCounter = 0; ///< determines when to perform control on blood flow @@ -165,9 +168,10 @@ static BOOL bpStopAtHomePosition = FALSE; ///< stop blood pump at next home position static U32 bpHomeStartTime = 0; ///< when did blood pump home command begin? (in ms) -static U16 bpLastMotorHallSensorCount = 0; ///< last hall sensor count for the blood pump motor -static U32 bloodPumpMotorEdgeCount = 0; ///< running counter for blood pump motor revolutions -static U32 bpMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating blood pump motor speed from hall sensor count. +static U32 bloodPumpMotorEdgeCount = 0; ///< running counter for blood pump motor revolutions +static U16 bpLastMotorHallSensorCounts[ BP_SPEED_CALC_BUFFER_LEN ]; ///< last hall sensor readings for the blood pump motor +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 U32 errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. static U32 errorBloodMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. @@ -216,15 +220,22 @@ * @return none *************************************************************************/ void initBloodFlow( void ) -{ - bpLastMotorHallSensorCount = getFPGABloodPumpHallSensorCount(); +{ + U32 i; stopBloodPump(); setBloodPumpDirection( MOTOR_DIR_FORWARD ); // zero rolling flow average buffer resetBloodFlowMovingAverage(); - + + // zero motor hall sensors counts buffer + bpMotorSpeedCalcIdx = 0; + for ( i = 0; i < BP_SPEED_CALC_BUFFER_LEN; i++ ) + { + bpLastMotorHallSensorCounts[ i ] = 0; + } + // initialize blood flow PI controller initializePIController( PI_CONTROLLER_ID_BLOOD_FLOW, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, BP_P_COEFFICIENT, BP_I_COEFFICIENT, @@ -258,7 +269,7 @@ if ( flowRate <= MAX_BLOOD_FLOW_RATE ) { resetBloodFlowMovingAverage(); - targetBloodFlowRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); + targetBloodFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); bloodPumpDirection = dir; bloodPumpControlMode = mode; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed @@ -312,7 +323,7 @@ *************************************************************************/ void signalBloodPumpHardStop( void ) { - targetBloodFlowRate.data = 0; + targetBloodFlowRate = 0; stopBloodPump(); bloodPumpState = BLOOD_PUMP_OFF_STATE; bloodPumpPWMDutyCyclePct = 0.0; @@ -498,7 +509,7 @@ BLOOD_PUMP_STATE_T result = BLOOD_PUMP_OFF_STATE; // if we've been given a flow rate, setup ramp up and transition to ramp up state - if ( getTargetBloodFlowRate() != 0 ) + if ( targetBloodFlowRate != 0 ) { // set initial PWM duty cycle bloodPumpPWMDutyCyclePctSet = BP_PWM_ZERO_OFFSET + MAX_BLOOD_PUMP_PWM_STEP_UP_CHANGE; @@ -526,7 +537,7 @@ BLOOD_PUMP_STATE_T result = BLOOD_PUMP_RAMPING_UP_STATE; // have we been asked to stop the blood pump? - if ( 0 == getTargetBloodFlowRate() ) + if ( 0 == targetBloodFlowRate ) { // start ramp down to stop bloodPumpPWMDutyCyclePctSet -= MAX_BLOOD_PUMP_PWM_STEP_DN_CHANGE; @@ -616,7 +627,7 @@ { if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) { - F32 tgtFlow = (F32)getTargetBloodFlowRate(); + F32 tgtFlow = (F32)targetBloodFlowRate; F32 actFlow = getMeasuredBloodFlowRate(); F32 newPWM; @@ -722,26 +733,6 @@ /*********************************************************************//** * @brief - * The getTargetBloodFlowRate function gets the current target blood flow - * rate. - * @details Inputs: targetBloodFlowRate - * @details Outputs: none - * @return the current target blood flow rate (in mL/min). - *************************************************************************/ -S32 getTargetBloodFlowRate( void ) -{ - S32 result = targetBloodFlowRate.data; - - if ( OVERRIDE_KEY == targetBloodFlowRate.override ) - { - result = targetBloodFlowRate.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The getMeasuredBloodFlowRate function gets the measured blood flow * rate. * @details Inputs: measuredBloodFlowRate @@ -876,7 +867,7 @@ { BLOOD_PUMP_STATUS_PAYLOAD_T payload; - payload.setPoint = (S32)getTargetBloodFlowRate(); + payload.setPoint = targetBloodFlowRate; payload.measFlow = getMeasuredBloodFlowRate(); payload.measRotorSpd = getMeasuredBloodPumpRotorSpeed(); payload.measPumpSpd = getMeasuredBloodPumpSpeed(); @@ -943,8 +934,11 @@ { if ( ++bpMotorSpeedCalcTimerCtr >= BP_SPEED_CALC_INTERVAL ) { - U16 bpMotorHallSensorCount = getFPGABloodPumpHallSensorCount(); - U16 incDelta = ( bpMotorHallSensorCount >= bpLastMotorHallSensorCount ? bpMotorHallSensorCount - bpLastMotorHallSensorCount : ( HEX_64_K - bpLastMotorHallSensorCount ) + bpMotorHallSensorCount ); + U16 bpMotorHallSensorCount = getFPGABloodPumpHallSensorCount(); + U32 nextIdx = INC_WRAP( bpMotorSpeedCalcIdx, 0, BP_SPEED_CALC_BUFFER_LEN - 1 ); + U16 incDelta = ( bpMotorHallSensorCount >= bpLastMotorHallSensorCounts[ nextIdx ] ? \ + bpMotorHallSensorCount - bpLastMotorHallSensorCounts[ nextIdx ] : \ + ( HEX_64_K - bpLastMotorHallSensorCounts[ nextIdx ] ) + bpMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; U16 delta; @@ -962,7 +956,8 @@ bloodPumpMotorEdgeCount += delta; // update last count for next time - bpLastMotorHallSensorCount = bpMotorHallSensorCount; + bpLastMotorHallSensorCounts[ nextIdx ] = bpMotorHallSensorCount; + bpMotorSpeedCalcIdx = nextIdx; bpMotorSpeedCalcTimerCtr = 0; } } @@ -1070,8 +1065,8 @@ *************************************************************************/ static void checkBloodPumpSpeeds( void ) { - F32 measMotorSpeed = fabs( getMeasuredBloodPumpSpeed() ); - S32 cmdRate = getTargetBloodFlowRate(); + F32 measMotorSpeed = fabs( getMeasuredBloodPumpSpeed() ); + S32 cmdRate = targetBloodFlowRate; // check for pump running while commanded off if ( 0 == cmdRate ) @@ -1252,7 +1247,7 @@ F32 sigStrength = getMeasuredBloodFlowSignalStrength(); BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); - checkPersistentAlarm( PERSISTENT_ALARM_BLOOD_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength ); + checkPersistentAlarm( PERSISTENT_ALARM_BLOOD_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength, MIN_FLOW_SIG_STRENGTH ); } #endif } @@ -1428,9 +1423,7 @@ } if ( ctrlMode < NUM_OF_PUMP_CONTROL_MODES ) { - targetBloodFlowRate.ovInitData = targetBloodFlowRate.data; // backup current target flow rate - targetBloodFlowRate.ovData = value; - targetBloodFlowRate.override = OVERRIDE_KEY; + targetBloodFlowRate = value; result = setBloodPumpTargetFlowRate( abs(value), dir, (PUMP_CONTROL_MODE_T)ctrlMode ); } } @@ -1440,30 +1433,6 @@ /*********************************************************************//** * @brief - * The testResetTargetBloodFlowRateOverride function resets the override of the - * target blood flow rate. - * @details Inputs: none - * @details Outputs: targetBloodFlowRate - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetBloodFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - targetBloodFlowRate.data = targetBloodFlowRate.ovInitData; // restore pre-override target flow rate - targetBloodFlowRate.override = OVERRIDE_RESET; - targetBloodFlowRate.ovInitData = 0; - targetBloodFlowRate.ovData = 0; - result = setBloodPumpTargetFlowRate( targetBloodFlowRate.data, bloodPumpDirection, bloodPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The testResetMeasuredBloodFlowRateOverride function overrides the measured * blood flow rate. * @details Inputs: none Index: firmware/App/Controllers/BloodFlow.h =================================================================== diff -u -r6eb873c4bc96fb22e85ac23aeee1c37e5366d731 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/BloodFlow.h (.../BloodFlow.h) (revision 6eb873c4bc96fb22e85ac23aeee1c37e5366d731) +++ firmware/App/Controllers/BloodFlow.h (.../BloodFlow.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -66,7 +66,6 @@ SELF_TEST_STATUS_T execBloodFlowTest( void ); -S32 getTargetBloodFlowRate( void ); F32 getMeasuredBloodFlowRate( void ); F32 getMeasuredBloodFlowSignalStrength( void); F32 getMeasuredBloodPumpRotorSpeed( void ); @@ -79,7 +78,6 @@ BOOL testSetBloodFlowDataPublishIntervalOverride( U32 value ); BOOL testResetBloodFlowDataPublishIntervalOverride( void ); BOOL testSetTargetBloodFlowRateOverride( S32 value, U32 bloodPumpControlMode ); -BOOL testResetTargetBloodFlowRateOverride( void ); BOOL testSetMeasuredBloodFlowRateOverride( F32 value ); BOOL testResetMeasuredBloodFlowRateOverride( void ); BOOL testSetMeasuredBloodPumpRotorSpeedOverride( F32 value ); Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -57,6 +57,55 @@ NUM_OF_DG_PRESSURE_SENSORS ///< Number of pressure sensors. } DG_PRESSURE_SENSORS_T; +/// Payload record structure for an RO pump data message. +typedef struct +{ + U32 setPtPSI; + F32 measFlowRateMlMin; + F32 setPWM; +} DG_RO_PUMP_DATA_PAYLOAD_T; + +/// Payload record structure for a drain pump data message. +typedef struct +{ + U32 setPtRPM; + F32 setPWM; +} DG_DRAIN_PUMP_DATA_PAYLOAD_T; + +/// Payload record structure for a DG pressures data message. +typedef struct +{ + F32 roInPSI; + F32 roOutPSI; + F32 drainInPSI; + F32 drainOutPSI; +} DG_PRESSURES_DATA_PAYLOAD_T; + +/// Payload record structure for a reservoirs data message. +typedef struct +{ + U32 resID; + U32 setFillToVolumeMl; + U32 setDrainToVolumeMl; +} DG_RESERVOIRS_DATA_PAYLOAD_T; + +/// Payload record structure for DG temperature sensors data message. +typedef struct +{ + F32 TPi; + F32 TPo; + F32 TD1; + F32 TD2; + F32 TRo; + F32 TDi; + F32 HtrPrimThermo; + F32 HtrTrimThermo; + F32 HtrPrimColdJunc; + F32 HtrTrimColdJunc; + F32 HtrPrimInternal; + F32 HtrTrimInternal; +} DG_TEMPERATURES_T; + // ********** public function prototypes ********** void initDGInterface( void ); Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -28,6 +28,7 @@ #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" +#include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" @@ -54,7 +55,10 @@ #define DIP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DIP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). -#define DIP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate inlet pump speed is calculated. +/// interval (ms/task time) at which the blood pump speed is calculated (every 40 ms). +#define DIP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) +/// number of hall sensor counts kept in buffer to hold last 1 second of count data. +#define DIP_SPEED_CALC_BUFFER__LEN ( 1000 / DIP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) #define DIP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< maximum difference between measured motor speed and speed implied by measured flow. @@ -144,8 +148,9 @@ static F32 dialInFlowCalGain = 1.0; ///< dialysate flow calibration gain. static F32 dialInFlowCalOffset = 0.0; ///< dialysate flow calibration offset. -static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; ///< interval (in ms) at which to publish dialIn flow data to CAN bus -static OVERRIDE_S32_T targetDialInFlowRate = { 0, 0, 0, 0 }; ///< requested dialIn flow rate +/// interval (in ms) at which to publish dialIn flow data to CAN bus +static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; +static S32 targetDialInFlowRate = 0; ///< requested dialIn flow rate static OVERRIDE_F32_T measuredDialInFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet flow rate static OVERRIDE_F32_T dialInPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump rotor speed static OVERRIDE_F32_T dialInPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump motor speed @@ -159,7 +164,8 @@ static BOOL dipStopAtHomePosition = FALSE; ///< stop dialysate inlet pump at next home position static U32 dipHomeStartTime = 0; ///< when did dialysate inlet pump home command begin? (in ms) -static U16 dipLastMotorHallSensorCount = 0; ///< last hall sensor count for the dialysate inlet pump motor +static U16 dipLastMotorHallSensorCounts[ DIP_SPEED_CALC_BUFFER__LEN ]; ///< last hall sensor count for the blood pump motor +static U32 dipMotorSpeedCalcIdx = 0; ///< index into 1 second buffer of motor speed hall sensor counts static U32 dipMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate inlet pump motor speed from hall sensor count. static U32 errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. @@ -208,15 +214,22 @@ * @return none *************************************************************************/ void initDialInFlow( void ) -{ - dipLastMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); +{ + U32 i; stopDialInPump(); setDialInPumpDirection( MOTOR_DIR_FORWARD ); // zero rolling flow average buffer resetDialInFlowMovingAverage(); + // zero motor hall sensors counts buffer + dipMotorSpeedCalcIdx = 0; + for ( i = 0; i < DIP_SPEED_CALC_BUFFER__LEN; i++ ) + { + dipLastMotorHallSensorCounts[ i ] = 0; + } + // initialize dialysate inlet flow PI controller initializePIController( PI_CONTROLLER_ID_DIALYSATE_FLOW, MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE, DIP_P_COEFFICIENT, DIP_I_COEFFICIENT, @@ -250,7 +263,7 @@ if ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) { resetDialInFlowMovingAverage(); - targetDialInFlowRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); + targetDialInFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); dialInPumpDirection = dir; dialInPumpControlMode = mode; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed @@ -304,7 +317,7 @@ *************************************************************************/ void signalDialInPumpHardStop( void ) { - targetDialInFlowRate.data = 0; + targetDialInFlowRate = 0; stopDialInPump(); dialInPumpState = DIAL_IN_PUMP_OFF_STATE; dialInPumpPWMDutyCyclePct = 0.0; @@ -461,7 +474,7 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_OFF_STATE; // if we've been given a flow rate, setup ramp up and transition to ramp up state - if ( getTargetDialInFlowRate() != 0 ) + if ( targetDialInFlowRate != 0 ) { // set initial PWM duty cycle dialInPumpPWMDutyCyclePctSet = DIP_PWM_ZERO_OFFSET + MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE; @@ -489,7 +502,7 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_RAMPING_UP_STATE; // have we been asked to stop the dialIn pump? - if ( 0 == getTargetDialInFlowRate() ) + if ( 0 == targetDialInFlowRate ) { // start ramp down to stop dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE; @@ -579,7 +592,7 @@ { if ( dialInPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) { - F32 tgtFlow = (F32)getTargetDialInFlowRate(); + F32 tgtFlow = (F32)targetDialInFlowRate; F32 actFlow = getMeasuredDialInFlowRate(); F32 newPWM; @@ -693,15 +706,8 @@ *************************************************************************/ S32 getTargetDialInFlowRate( void ) { - S32 result = targetDialInFlowRate.data; - - if ( OVERRIDE_KEY == targetDialInFlowRate.override ) - { - result = targetDialInFlowRate.ovData; - } - - return result; -} + return targetDialInFlowRate; +} /*********************************************************************//** * @brief @@ -839,7 +845,7 @@ { DIALIN_PUMP_STATUS_PAYLOAD_T payload; - payload.setPoint = (S32)getTargetDialInFlowRate(); + payload.setPoint = targetDialInFlowRate; payload.measFlow = getMeasuredDialInFlowRate(); payload.measRotorSpd = getMeasuredDialInPumpRotorSpeed(); payload.measPumpSpd = getMeasuredDialInPumpSpeed(); @@ -906,7 +912,10 @@ if ( ++dipMotorSpeedCalcTimerCtr >= DIP_SPEED_CALC_INTERVAL ) { U16 dipMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); - U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCount ? dipMotorHallSensorCount - dipLastMotorHallSensorCount : ( HEX_64_K - dipLastMotorHallSensorCount ) + dipMotorHallSensorCount ); + U32 nextIdx = INC_WRAP( dipMotorSpeedCalcIdx, 0, DIP_SPEED_CALC_BUFFER__LEN - 1 ); + U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCounts[ nextIdx ] ? \ + dipMotorHallSensorCount - dipLastMotorHallSensorCounts[ nextIdx ] : \ + ( HEX_64_K - dipLastMotorHallSensorCounts[ nextIdx ] ) + dipMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; U16 delta; @@ -923,7 +932,8 @@ } // update last count for next time - dipLastMotorHallSensorCount = dipMotorHallSensorCount; + dipLastMotorHallSensorCounts[ nextIdx ] = dipMotorHallSensorCount; + dipMotorSpeedCalcIdx = nextIdx; dipMotorSpeedCalcTimerCtr = 0; } } @@ -1017,7 +1027,7 @@ static void checkDialInPumpSpeeds( void ) { F32 measMotorSpeed = getMeasuredDialInPumpSpeed(); - S32 cmdRate = getTargetDialInFlowRate(); + S32 cmdRate = targetDialInFlowRate; // check for pump running while commanded off if ( 0 == cmdRate ) @@ -1028,6 +1038,7 @@ { #ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif } } @@ -1198,7 +1209,7 @@ F32 sigStrength = getMeasuredDialInFlowSignalStrength(); BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); - checkPersistentAlarm( PERSISTENT_ALARM_DIALYSATE_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength ); + checkPersistentAlarm( PERSISTENT_ALARM_DIALYSATE_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength, MIN_FLOW_SIG_STRENGTH ); } #endif } @@ -1374,9 +1385,7 @@ } if ( ctrlMode < NUM_OF_PUMP_CONTROL_MODES ) { - targetDialInFlowRate.ovInitData = targetDialInFlowRate.data; // backup current target flow rate - targetDialInFlowRate.ovData = value; - targetDialInFlowRate.override = OVERRIDE_KEY; + targetDialInFlowRate = value; result = setDialInPumpTargetFlowRate( abs(value), dir, (PUMP_CONTROL_MODE_T)ctrlMode ); } } @@ -1386,30 +1395,6 @@ /*********************************************************************//** * @brief - * The testResetTargetDialInFlowRateOverride function resets the override of the - * target dialysate inlet flow rate. - * @details Inputs: none - * @details Outputs: targetDialInFlowRate - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetDialInFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - targetDialInFlowRate.data = targetDialInFlowRate.ovInitData; // restore pre-override target flow rate - targetDialInFlowRate.override = OVERRIDE_RESET; - targetDialInFlowRate.ovInitData = 0; - targetDialInFlowRate.ovData = 0; - result = setDialInPumpTargetFlowRate( targetDialInFlowRate.data, dialInPumpDirection, dialInPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The testResetMeasuredDialInFlowRateOverride function overrides the measured * dialIn flow rate. * @details Inputs: none Index: firmware/App/Controllers/DialInFlow.h =================================================================== diff -u -r6eb873c4bc96fb22e85ac23aeee1c37e5366d731 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 6eb873c4bc96fb22e85ac23aeee1c37e5366d731) +++ firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -75,7 +75,6 @@ BOOL testSetDialInFlowDataPublishIntervalOverride( U32 value ); BOOL testResetDialInFlowDataPublishIntervalOverride( void ); BOOL testSetTargetDialInFlowRateOverride( S32 value, U32 ctrlMode ); -BOOL testResetTargetDialInFlowRateOverride( void ); BOOL testSetMeasuredDialInFlowRateOverride( F32 value ); BOOL testResetMeasuredDialInFlowRateOverride( void ); BOOL testSetMeasuredDialInPumpRotorSpeedOverride( F32 value ); Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -25,6 +25,7 @@ #include "InternalADC.h" #include "OperationModes.h" #include "PIControllers.h" +#include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" @@ -56,7 +57,10 @@ #define DOP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DOP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). -#define DOP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate outlet pump speed is calculated. +/// interval (ms/task time) at which the blood pump speed is calculated (every 40 ms). +#define DOP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) +/// number of hall sensor counts kept in buffer to hold last 1 second of count data. +#define DOP_SPEED_CALC_BUFFER__LEN ( 1000 / DOP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) #define DOP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. @@ -149,7 +153,8 @@ static BOOL dopStopAtHomePosition = FALSE; ///< stop dialysate outlet pump at next home position static U32 dopHomeStartTime = 0; ///< when did dialysate outlet pump home command begin? (in ms) -static U16 dopLastMotorHallSensorCount = 0; ///< last hall sensor count for the dialysate outlet pump motor +static U16 dopLastMotorHallSensorCounts[ DOP_SPEED_CALC_BUFFER__LEN ]; ///< last hall sensor count for the blood pump motor +static U32 dopMotorSpeedCalcIdx = 0; ///< index into 1 second buffer of motor speed hall sensor counts static U32 dopMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate outlet pump motor speed from hall sensor count. static U32 errorDialOutMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. @@ -160,9 +165,6 @@ static DIAL_OUT_PUMP_SELF_TEST_STATE_T dialOutPumpSelfTestState = DIAL_OUT_PUMP_SELF_TEST_STATE_START; ///< Current state of the dialysate outlet pump self-test state machine. static U32 dialOutPumpSelfTestTimerCount = 0; ///< Timer counter for time reference during self-test. -// Broadcasting record -DIAL_OUT_FLOW_DATA_T dialOutBroadCastVariables; ///< Record containing latest dialysate outlet data for broadcasting. - // ********** private function prototypes ********** static DIAL_OUT_PUMP_STATE_T handleDialOutPumpOffState( void ); @@ -196,26 +198,22 @@ { U32 i; - dopLastMotorHallSensorCount = getFPGADialOutPumpHallSensorCount(); - stopDialOutPump(); setDialOutPumpDirection( MOTOR_DIR_FORWARD ); + // zero motor hall sensors counts buffer + dopMotorSpeedCalcIdx = 0; + for ( i = 0; i < DOP_SPEED_CALC_BUFFER__LEN; i++ ) + { + dopLastMotorHallSensorCounts[ i ] = 0; + } + // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { loadCellWeightInGrams[ i ].data = 0.0; } - // initialize broadcast data - dialOutBroadCastVariables.refUFVolMl = 0.0; - dialOutBroadCastVariables.measUFVolMl = 0.0; - dialOutBroadCastVariables.measRotSpdRPM = 0.0; - dialOutBroadCastVariables.measSpdRPM = 0.0; - dialOutBroadCastVariables.measMCSpdRPM = 0.0; - dialOutBroadCastVariables.measMCCurrmA = 0.0; - dialOutBroadCastVariables.setPWMpct = 0.0; - // initialize dialysate outlet flow PI controller initializePIController( PI_CONTROLLER_ID_ULTRAFILTRATION, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, DOP_P_COEFFICIENT, DOP_I_COEFFICIENT, @@ -722,6 +720,8 @@ // publish dialysate outlet pump and UF volume data on interval if ( ++dialOutFlowDataPublicationTimerCounter >= getPublishDialOutDataInterval() ) { + DIAL_OUT_FLOW_DATA_T dialOutBroadCastVariables; + dialOutBroadCastVariables.refUFVolMl = getTotalTargetDialOutUFVolumeInMl(); dialOutBroadCastVariables.measUFVolMl = getTotalMeasuredUFVolumeInMl(); dialOutBroadCastVariables.measRotSpdRPM = getMeasuredDialOutPumpRotorSpeed(); @@ -749,7 +749,10 @@ if ( ++dopMotorSpeedCalcTimerCtr >= DOP_SPEED_CALC_INTERVAL ) { U16 dopMotorHallSensorCount = getFPGADialOutPumpHallSensorCount(); - U16 incDelta = ( dopMotorHallSensorCount >= dopLastMotorHallSensorCount ? dopMotorHallSensorCount - dopLastMotorHallSensorCount : ( HEX_64_K - dopLastMotorHallSensorCount ) + dopMotorHallSensorCount ); + U32 nextIdx = INC_WRAP( dopMotorSpeedCalcIdx, 0, DOP_SPEED_CALC_BUFFER__LEN - 1 ); + U16 incDelta = ( dopMotorHallSensorCount >= dopLastMotorHallSensorCounts[ nextIdx ] ? \ + dopMotorHallSensorCount - dopLastMotorHallSensorCounts[ nextIdx ] : \ + ( HEX_64_K - dopLastMotorHallSensorCounts[ nextIdx ] ) + dopMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; U16 delta; @@ -766,7 +769,8 @@ } // update last count for next time - dopLastMotorHallSensorCount = dopMotorHallSensorCount; + dopLastMotorHallSensorCounts[ nextIdx ] = dopMotorHallSensorCount; + dopMotorSpeedCalcIdx = nextIdx; dopMotorSpeedCalcTimerCtr = 0; } } @@ -870,6 +874,7 @@ { #ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif } } @@ -1245,26 +1250,6 @@ /*********************************************************************//** * @brief - * The testResetTargetDialOutFlowRateOverride function resets the override of the - * target dialysate outlet flow rate. - * @details Inputs: none - * @details Outputs: pump stopped - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetDialOutFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = setDialOutPumpTargetRate( 0, dialOutPumpDirection, dialOutPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The testSetDialOutUFRefVolumeOverride function overrides the target * dialout vol rate. * @details Inputs: referenceUFVolumeInMl Index: firmware/App/Controllers/DialOutFlow.h =================================================================== diff -u -re7bd79a79d566ef58f09cffb4c97d08fbe277ca7 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision e7bd79a79d566ef58f09cffb4c97d08fbe277ca7) +++ firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -43,6 +43,7 @@ } LOAD_CELL_T; #pragma pack(push, 1) + /// Dialysate outlet pump broadcast record typedef struct DialOutBroadcastingRecord { @@ -54,6 +55,16 @@ F32 measMCCurrmA; ///< Latest measured motor controller current for dialysate outlet pump in mA. F32 setPWMpct; ///< Latest PWM duty cycle for dialysate outlet pump in % (0..100). } DIAL_OUT_FLOW_DATA_T; + +/// Payload record structure for a load cell data message. +typedef struct +{ + F32 res1PrimaryLoadCell; + F32 res1BackupLoadCell; + F32 res2PrimaryLoadCell; + F32 res2BackupLoadCell; +} LOAD_CELL_READINGS_PAYLOAD_T; + #pragma pack(pop) // ********** public function prototypes ********** @@ -85,7 +96,6 @@ BOOL testSetDialOutPumpAndLoadCellDataPublishIntervalOverride( U32 value ); BOOL testResetDialOutPumpAndLoadCellDataPublishIntervalOverride( void ); BOOL testSetTargetDialOutFlowRateOverride( S32 value, U32 ctrlMode ); -BOOL testResetTargetDialOutFlowRateOverride( void ); BOOL testSetDialOutUFRefVolumeOverride( F32 value ); BOOL testResetDialOutUFRefVolumeOverride( void ); BOOL testSetDialOutUFTotVolumeOverride( F32 value ); Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -17,8 +17,10 @@ #include "PresOccl.h" #include "AlarmMgmt.h" -#include "FPGA.h" -#include "OperationModes.h" +#include "FPGA.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -39,10 +41,22 @@ #define VENOUS_PRESSURE_OFFSET ( 1638 ) ///< Offset for 14-bit venous pressure sensor reading. #define VENOUS_PRESSURE_SCALE ( 14745 - VENOUS_PRESSURE_OFFSET ) ///< Scale for venous pressure sensor. -#define VENOUS_PRESSURE_MIN ( 30.0 ) ///< Minimum of scale for venous pressure sensor reading (in TBD u/m). -#define VENOUS_PRESSURE_MAX ( 90.0 ) ///< Maximum of scale for venous pressure sensor reading (in TBD u/m). +#define VENOUS_PRESSURE_MIN ( -30.0 ) ///< Minimum of scale for venous pressure sensor reading (in PSI). +#define VENOUS_PRESSURE_MAX ( 30.0 ) ///< Maximum of scale for venous pressure sensor reading (in PSI). -#define PSI_TO_MMHG ( 51.7149 ) ///< Conversion factor (mmHg/PSI) for converting PSI to mmHg. +#define PSI_TO_MMHG ( 51.7149 ) ///< Conversion factor for converting PSI to mmHg. + +#define VENOUS_PRESSURE_NORMAL_OP 0 ///< Venous pressure status bits indicate normal operation. +#define VENOUS_PRESSURE_CMD_MODE 1 ///< Venous pressure status bits indicate sensor in command mode. +#define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). +#define VENOUS_PRESSURE_DIAG_CONDITION 3 ///< Venous pressure status bits diagnostic condition (alarm). + +#define MAX_TIME_BETWEEN_VENOUS_READINGS ( 500 / TASK_GENERAL_INTERVAL ) ///< Maximum time without fresh inline venous pressure reading. + +#define OCCLUSION_THRESHOLD 25000 ///< Threshold above which an occlusion is detected. +#define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. + +#define PRES_ALARM_PERSISTENCE ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Alarm persistence period for pressure alarms. /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States @@ -66,25 +80,28 @@ static PRESSURE_STATE_T presOcclState = PRESSURE_INIT_STATE; ///< current state of pressure monitor state machine. static U32 presOcclDataPublicationTimerCounter = 0; ///< used to schedule pressure data publication to CAN bus. -static OVERRIDE_U32_T presOcclDataPublishInterval = { PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL, 0, 0 }; ///< interval (in ms) at which to publish pressure/occlusion data to CAN bus. +/// interval (in ms) at which to publish pressure/occlusion data to CAN bus. +static OVERRIDE_U32_T presOcclDataPublishInterval = { PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL, 0, 0 }; static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< measured arterial pressure. static OVERRIDE_F32_T venousPressure = {0.0, 0.0, 0.0, 0 }; ///< measured venous pressure. -static OVERRIDE_F32_T bloodPumpOcclusion = {0.0, 0.0, 0.0, 0 }; ///< measured blood pump occlusion pressure. -static OVERRIDE_F32_T dialInPumpOcclusion = {0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump occlusion pressure. -static OVERRIDE_F32_T dialOutPumpOcclusion = {0.0, 0.0, 0.0, 0 }; ///< measured dialysate outlet pump occlusion pressure. +static OVERRIDE_U32_T bloodPumpOcclusion = {0, 0, 0, 0 }; ///< measured blood pump occlusion pressure. +static OVERRIDE_U32_T dialInPumpOcclusion = {0, 0, 0, 0 }; ///< measured dialysate inlet pump occlusion pressure. +static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< measured dialysate outlet pump occlusion pressure. -static PRESSURE_SELF_TEST_STATE_T presOcclSelfTestState = PRESSURE_SELF_TEST_STATE_START; ///< current pressure self-test state. -static U32 presOcclSelfTestTimerCount = 0; ///< timer counter for pressure self-test. +/// current pressure self-test state. +static PRESSURE_SELF_TEST_STATE_T presOcclSelfTestState = PRESSURE_SELF_TEST_STATE_START; +static U32 bloodPumpSelfTestTimerCount = 0; ///< timer counter for pressure self-test. -// TODO - set thresholds for occlusions -static F32 bloodPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for blood pump occlusion. -static F32 dialInPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for dialysate inlet pump occlusion. -static F32 dialOutPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for dialysate outlet pump occlusion. +static U32 staleVenousPressureCtr = 0; ///< timer counter for stale venous pressure reading. // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclInitState( void ); -static PRESSURE_STATE_T handlePresOcclContReadState( void ); +static PRESSURE_STATE_T handlePresOcclContReadState( void ); +static void convertInlinePressures( void ); +static void convertOcclusionPressures( void ); +static void checkArterialPressureInRange( void ); +static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); static DATA_GET_PROTOTYPE( U32, getPublishPresOcclDataInterval ); @@ -93,48 +110,49 @@ * @brief * The initPresOccl function initializes the initPresOccl module. * @details Inputs: none - * @details Outputs: Pressures and Occlusions module initialized. + * @details Outputs: initPresOccl module initialized. * @return none *************************************************************************/ void initPresOccl( void ) { - // TODO - anything to initialize? + // initialize persistent pressure alarms + initPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_LOW, ALARM_ID_ARTERIAL_PRESSURE_LOW, + isAlarmRecoverable( ALARM_ID_ARTERIAL_PRESSURE_LOW ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_HIGH, ALARM_ID_ARTERIAL_PRESSURE_HIGH, + isAlarmRecoverable( ALARM_ID_ARTERIAL_PRESSURE_HIGH ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_LOW, ALARM_ID_VENOUS_PRESSURE_LOW, + isAlarmRecoverable( ALARM_ID_VENOUS_PRESSURE_LOW ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_HIGH, ALARM_ID_VENOUS_PRESSURE_HIGH, + isAlarmRecoverable( ALARM_ID_VENOUS_PRESSURE_HIGH ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); } +/*********************************************************************//** + * @brief + * The isCartridgeLoaded function determines whether a cartridge has been + * properly loaded by looking at the 3 occlusion pressure sensors. + * @details Inputs: occlusion pressures for the pumps + * @details Outputs: none + * @return TRUE if all 3 occlusion sensors read above loaded threshold, FALSE if not. + *************************************************************************/ +BOOL isCartridgeLoaded( void ) +{ + BOOL result = FALSE; + U32 bpOccl = getMeasuredBloodPumpOcclusion(); + U32 diOccl = getMeasuredDialInPumpOcclusion(); + U32 doOccl = getMeasuredDialOutPumpOcclusion(); + + if ( ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) && + ( diOccl >= CARTRIDGE_LOADED_THRESHOLD ) && + ( doOccl >= CARTRIDGE_LOADED_THRESHOLD ) ) + { + result = TRUE; + } + + return result; +} + /*********************************************************************//** * @brief - * The setOcclusionThreshold function sets the occlusion pressure threshold - * for a given occlusion sensor. - * @details Inputs: none - * @details Outputs: pressure threshold - * @param sensor occlusion sensor we are setting threshold for - * @param threshold pressure threshold above which indicates an occlusion (mmHg) - * @return none - *************************************************************************/ -void setOcclusionThreshold( OCCLUSION_SENSORS_T sensor, F32 threshold ) -{ - switch ( sensor ) // TODO - will threshold be range checked by caller or should we do it here? what is valid range? - { - case OCCLUSION_SENSOR_BLOOD_PUMP: - bloodPumpOcclusionPressureThresholdmmHG = threshold; - break; - - case OCCLUSION_SENSOR_DIAL_IN_PUMP: - dialInPumpOcclusionPressureThresholdmmHG = threshold; - break; - - case OCCLUSION_SENSOR_DIAL_OUT_PUMP: - dialOutPumpOcclusionPressureThresholdmmHG = threshold; - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_PRES_OCCL_INVALID_OCCL_SENSOR, sensor ) - break; - } -} - -/*********************************************************************//** - * @brief * The execPresOccl function executes the pressure and occlusion monitor. * @details Inputs: presOcclState * @details Outputs: presOcclState @@ -166,8 +184,8 @@ * @brief * The handlePresOcclInitState function handles the pres/occl initialize state * of the pressure/occlusion monitor state machine. - * @details Inputs: none - * @details Outputs: none + * @details Inputs: TBD + * @details Outputs: TBD * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclInitState( void ) @@ -187,61 +205,180 @@ *************************************************************************/ static PRESSURE_STATE_T handlePresOcclContReadState( void ) { - PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; - - S32 artPres = getFPGAArterialPressure(); - U16 venPres = getFPGAVenousPressure(); - U16 bldOccl = getFPGABloodPumpOcclusion(); - U16 dliOccl = getFPGADialInPumpOcclusion(); - U16 dloOccl = getFPGADialOutPumpOcclusion(); - F32 venPresPSI; - - // TODO - convert ADC counts to mmHg for each sensor - arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY / ARTERIAL_PRESSURE_V_BIAS ) ); - venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX - VENOUS_PRESSURE_MIN) / (F32)VENOUS_PRESSURE_SCALE ) - VENOUS_PRESSURE_MIN; - venousPressure.data = venPresPSI * PSI_TO_MMHG; - bloodPumpOcclusion.data = (F32)bldOccl; - dialInPumpOcclusion.data = (F32)dliOccl; - dialOutPumpOcclusion.data = (F32)dloOccl; - - // TODO - any filtering required??? - + PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; + + // read latest in-line (arterial and venous) pressures + convertInlinePressures(); + + // read latest occlusion pressures + convertOcclusionPressures(); + + // check in-line pressures are in range + checkArterialPressureInRange(); + checkVenousPressureInRange(); + // check for occlusions - checkOcclusions(); - - // TODO - any other checks - + checkOcclusions(); + return result; } - + +/*********************************************************************//** + * @brief + * The convertInlinePressures function reads inline pressure sensor readings + * and converts to mmHg. Sensor status/alarm is checked. + * @details Inputs: FPGA + * @details Outputs: arterialPressure, venousPressure + * @return none + *************************************************************************/ +static void convertInlinePressures( void ) +{ + U32 fpgaArtPres = getFPGAArterialPressure(); + S32 artPres = (S32)( fpgaArtPres & MASK_OFF_U32_MSB ) - 0x800000; // subtract 2^23 from low 24 bits to get signed reading + U08 artPresAlarm = (U08)( fpgaArtPres >> 24 ); // high byte is alarm code for arterial pressure + U16 fpgaVenPres = getFPGAVenousPressure(); + U16 venPres = fpgaVenPres & 0x3FFF; // 14-bit data + U08 venPresStatus = (U08)( fpgaVenPres >> 14 ); // high 2 bits is status code for venous pressure + F32 venPresPSI; + + // TODO - any filtering required??? + + // convert arterial pressure to mmHg if no alarm + if ( 0 == artPresAlarm ) + { + arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); + } + else + { +#ifndef DISABLE_PRESSURE_CHECKS + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT, (U32)artPresAlarm ) +#endif + } + + // convert venous pressure to PSI + venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX - VENOUS_PRESSURE_MIN) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN; + // convert venous pressure from PSI to mmHg if sensor status is normal + if ( VENOUS_PRESSURE_NORMAL_OP == venPresStatus ) + { + venousPressure.data = venPresPSI * PSI_TO_MMHG; + staleVenousPressureCtr = 0; + } + // if venous pressure sensor status is not normal or reading is stale for too long, fault + else + { + if ( ++staleVenousPressureCtr > MAX_TIME_BETWEEN_VENOUS_READINGS ) + { +#ifndef DISABLE_PRESSURE_CHECKS + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_VENOUS_PRESSURE_SENSOR_FAULT, VENOUS_PRESSURE_STALE_DATA ) +#endif + } + } + + // check for venous pressure sensor alarm or in wrong (cmd) mode + if ( ( VENOUS_PRESSURE_DIAG_CONDITION == venPresStatus ) || ( VENOUS_PRESSURE_CMD_MODE == venPresStatus ) ) + { +#ifndef DISABLE_PRESSURE_CHECKS + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_VENOUS_PRESSURE_SENSOR_FAULT, (U32)venPresStatus ) +#endif + } +} + +/*********************************************************************//** + * @brief + * The convertOcclusionPressures function reads occlusion sensor readings. + * @details Inputs: FPGA + * @details Outputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion + * @return none + *************************************************************************/ +static void convertOcclusionPressures( void ) +{ + // TODO - any filtering required??? + + // occlusion sensor values have no unit - take as is + bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); + dialInPumpOcclusion.data = (U32)getFPGADialInPumpOcclusion(); + dialOutPumpOcclusion.data = (U32)getFPGADialOutPumpOcclusion(); +} + +/*********************************************************************//** + * @brief + * The checkArterialPressureInRange function checks that artieral pressure is + * within the set alarm limits. Alarm is triggered if not. + * @details Inputs: arterialPressure + * @details Outputs: Alarm if out of range + * @return none + *************************************************************************/ +static void checkArterialPressureInRange( void ) +{ + F32 artPres = getMeasuredArterialPressure(); + + // check arterial pressure during treatment mode + if ( MODE_TREA == getCurrentOperationMode() ) + { + F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit, artPres, artLowLimit ); + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit, artPres, artHighLimit ); +#endif + } +} + +/*********************************************************************//** + * @brief + * The checkVenousPressureInRange function checks that venous pressure is + * within the set alarm limits. Alarm is triggered if not. + * @details Inputs: venousPressure + * @details Outputs: Alarm if out of range + * @return none + *************************************************************************/ +static void checkVenousPressureInRange( void ) +{ + F32 venPres = getMeasuredVenousPressure(); + + // check arterial pressure during treatment mode + if ( MODE_TREA == getCurrentOperationMode() ) + { + F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_LOW, venPres < venLowLimit, venPres, venLowLimit ); + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_HIGH, venPres > venHighLimit, venPres, venHighLimit ); +#endif + } +} + /*********************************************************************//** * @brief * The checkPressureLimits function gets the pressure/occlusion data * publication interval. * @details Inputs: occlusion pressures for the pumps - * @details Outputs: alarm(s) may be triggered + * @details Outputs: Alarm if occlusion limit exceeded * @return none *************************************************************************/ static void checkOcclusions( void ) { - F32 bpOccl = getMeasuredBloodPumpOcclusion(); - F32 diOccl = getMeasuredDialInPumpOcclusion(); - F32 doOccl = getMeasuredDialOutPumpOcclusion(); - + U32 bpOccl = getMeasuredBloodPumpOcclusion(); + U32 diOccl = getMeasuredDialInPumpOcclusion(); + U32 doOccl = getMeasuredDialOutPumpOcclusion(); + + // TODO - add persistence #ifndef DISABLE_PRESSURE_CHECKS - if ( bpOccl > bloodPumpOcclusionPressureThresholdmmHG ) + if ( bpOccl > OCCLUSION_THRESHOLD ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) // TODO - stop blood pump immediately, ... } - if ( diOccl > dialInPumpOcclusionPressureThresholdmmHG ) + if ( diOccl > OCCLUSION_THRESHOLD ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) // TODO - stop dialysate inlet pump immediately, ... } - if ( doOccl > dialOutPumpOcclusionPressureThresholdmmHG ) + if ( doOccl > OCCLUSION_THRESHOLD ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) // TODO - stop dialysate outlet pump immediately, ... } #endif @@ -255,7 +392,17 @@ * @details Outputs: none * @return the current pressure/occlusion data publication interval (in task intervals). *************************************************************************/ -DATA_GET( U32, getPublishPresOcclDataInterval, presOcclDataPublishInterval ) +U32 getPublishPresOcclDataInterval( void ) +{ + U32 result = presOcclDataPublishInterval.data; + + if ( OVERRIDE_KEY == presOcclDataPublishInterval.override ) + { + result = presOcclDataPublishInterval.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -264,7 +411,17 @@ * @details Outputs: none * @return the current arterial pressure (in mmHg). *************************************************************************/ -DATA_GET( F32, getMeasuredArterialPressure, arterialPressure ) +F32 getMeasuredArterialPressure( void ) +{ + F32 result = arterialPressure.data; + + if ( OVERRIDE_KEY == arterialPressure.override ) + { + result = arterialPressure.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -273,7 +430,17 @@ * @details Outputs: none * @return the current venous pressure (in mmHg). *************************************************************************/ -DATA_GET( F32, getMeasuredVenousPressure, venousPressure ) +F32 getMeasuredVenousPressure( void ) +{ + F32 result = venousPressure.data; + + if ( OVERRIDE_KEY == venousPressure.override ) + { + result = venousPressure.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -283,7 +450,17 @@ * @details Outputs: none * @return the current blood pump occlusion pressure (in mmHg). *************************************************************************/ -DATA_GET( F32, getMeasuredBloodPumpOcclusion, bloodPumpOcclusion ) +U32 getMeasuredBloodPumpOcclusion( void ) +{ + U32 result = bloodPumpOcclusion.data; + + if ( OVERRIDE_KEY == bloodPumpOcclusion.override ) + { + result = bloodPumpOcclusion.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -293,7 +470,17 @@ * @details Outputs: none * @return the current dialysis inlet pump occlusion pressure (in mmHg). *************************************************************************/ -DATA_GET( F32, getMeasuredDialInPumpOcclusion, dialInPumpOcclusion ) +U32 getMeasuredDialInPumpOcclusion( void ) +{ + U32 result = dialInPumpOcclusion.data; + + if ( OVERRIDE_KEY == dialInPumpOcclusion.override ) + { + result = dialInPumpOcclusion.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -303,7 +490,17 @@ * @details Outputs: none * @return the current dialysis outlet pump occlusion pressure (in mmHg). *************************************************************************/ -DATA_GET( F32, getMeasuredDialOutPumpOcclusion, dialOutPumpOcclusion ) +U32 getMeasuredDialOutPumpOcclusion( void ) +{ + U32 result = dialOutPumpOcclusion.data; + + if ( OVERRIDE_KEY == dialOutPumpOcclusion.override ) + { + result = dialOutPumpOcclusion.ovData; + } + + return result; +} /*********************************************************************//** * @brief @@ -317,14 +514,16 @@ { // publish pressure/occlusion data on interval if ( ++presOcclDataPublicationTimerCounter >= getPublishPresOcclDataInterval() ) - { - F32 artPres = getMeasuredArterialPressure(); - F32 venPres = getMeasuredVenousPressure(); - F32 bpOccl = getMeasuredBloodPumpOcclusion(); - F32 diOccl = getMeasuredDialInPumpOcclusion(); - F32 doOccl = getMeasuredDialOutPumpOcclusion(); + { + PRESSURE_OCCLUSION_DATA_T data; - broadcastPresOcclData( artPres, venPres, bpOccl, diOccl, doOccl ); + data.arterialPressure = getMeasuredArterialPressure(); + data.venousPressure = getMeasuredVenousPressure(); + data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); + data.diPumpOcclusion = getMeasuredDialInPumpOcclusion(); + data.doPumpOcclusion = getMeasuredDialOutPumpOcclusion(); + + broadcastPresOcclData( data ); presOcclDataPublicationTimerCounter = 0; } } @@ -492,13 +691,13 @@ /*********************************************************************//** * @brief * The testSetBloodPumpOcclusionOverride function overrides the measured - * blood pump occlusion pressure.n + * blood pump occlusion pressure. * @details Inputs: none * @details Outputs: bloodPumpOcclusion - * @param value override measured blood pump occlusion pressure with (in mmHg) + * @param value override measured blood pump occlusion pressure with * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetBloodPumpOcclusionOverride( F32 value ) +BOOL testSetBloodPumpOcclusionOverride( U32 value ) { BOOL result = FALSE; @@ -540,10 +739,10 @@ * dialysate inlet pump occlusion pressure.n * @details Inputs: none * @details Outputs: dialInPumpOcclusion - * @param value override measured dialysate inlet pump occlusion pressure (in mmHg) + * @param value override measured dialysate inlet pump occlusion pressure * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetDialInPumpOcclusionOverride( F32 value ) +BOOL testSetDialInPumpOcclusionOverride( U32 value ) { BOOL result = FALSE; @@ -585,10 +784,10 @@ * dialysate outlet pump occlusion pressure. * @details Inputs: none * @details Outputs: dialOutPumpOcclusion - * @param value override measured dialysate outlet pump occlusion pressure (in mmHg) + * @param value override measured dialysate outlet pump occlusion pressure * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetDialOutPumpOcclusionOverride( F32 value ) +BOOL testSetDialOutPumpOcclusionOverride( U32 value ) { BOOL result = FALSE; Index: firmware/App/Controllers/PresOccl.h =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -48,32 +48,42 @@ NUM_OF_OCCLUSION_SENSORS ///< Number of occlusion sensors } OCCLUSION_SENSORS_T; +/// Payload record structure for the pressure & occlusions data message. +typedef struct +{ + F32 arterialPressure; + F32 venousPressure; + U32 bldPumpOcclusion; + U32 diPumpOcclusion; + U32 doPumpOcclusion; +} PRESSURE_OCCLUSION_DATA_T; + // ********** public function prototypes ********** void initPresOccl( void ); void execPresOccl( void ); -void setOcclusionThreshold( OCCLUSION_SENSORS_T sensor, F32 threshold ); - SELF_TEST_STATUS_T execPresOcclTest( void ); -F32 getMeasuredArterialPressure( void ); -F32 getMeasuredVenousPressure( void ); -F32 getMeasuredBloodPumpOcclusion( void ); -F32 getMeasuredDialInPumpOcclusion( void ); -F32 getMeasuredDialOutPumpOcclusion( void ); - +F32 getMeasuredArterialPressure( void ); +F32 getMeasuredVenousPressure( void ); +U32 getMeasuredBloodPumpOcclusion( void ); +U32 getMeasuredDialInPumpOcclusion( void ); +U32 getMeasuredDialOutPumpOcclusion( void ); + +BOOL isCartridgeLoaded( void ); + BOOL testSetPresOcclDataPublishIntervalOverride( U32 value ); BOOL testResetPresOcclDataPublishIntervalOverride( void ); BOOL testSetArterialPressureOverride( F32 value ); BOOL testResetArterialPressureOverride( void ); BOOL testSetVenousPressureOverride( F32 value ); BOOL testResetVenousPressureOverride( void ); -BOOL testSetBloodPumpOcclusionOverride( F32 value ); +BOOL testSetBloodPumpOcclusionOverride( U32 value ); BOOL testResetBloodPumpOcclusionOverride( void ); -BOOL testSetDialInPumpOcclusionOverride( F32 value ); +BOOL testSetDialInPumpOcclusionOverride( U32 value ); BOOL testResetDialInPumpOcclusionOverride( void ); -BOOL testSetDialOutPumpOcclusionOverride( F32 value ); +BOOL testSetDialOutPumpOcclusionOverride( U32 value ); BOOL testResetDialOutPumpOcclusionOverride( void ); /**@}*/ Index: firmware/App/HDCommon.h =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -77,6 +77,43 @@ // **** Common Definitions **** +#pragma pack(push,1) + +/// Payload record structure for an HD versions message. +typedef struct +{ + U08 major; + U08 minor; + U08 micro; + U16 build; + U08 fpgaId; + U08 fpgaMajor; + U08 fpgaMinor; + U08 fpgaLab; +} HD_VERSIONS_T; + +/// Payload record structure for a peristaltic pump data message. +typedef struct +{ + U32 setPoint; + F32 measFlow; + F32 measRotorSpd; + F32 measPumpSpd; + F32 measMCSpd; + F32 measMCCurr; + F32 pwmDC; +} PERISTALTIC_PUMP_STATUS_PAYLOAD_T; + +/// Payload record structure for a pump set point override message. +typedef struct +{ + BOOL reset; + S32 setPt; + U32 ctrlMode; +} OVERRIDE_PUMP_SET_PT_PAYLOAD_T; + +#pragma pack(pop) + // **** Common Macros **** /**@}*/ Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -140,11 +140,6 @@ postState = handlePOSTStatus( testStatus ); break; - case POST_STATE_VALVES: - testStatus = execValvesSelfTest(); - postState = handlePOSTStatus( testStatus ); - break; - case POST_STATE_ACCELEROMETER: #ifndef DISABLE_ACCELS testStatus = execAccelTest(); @@ -154,6 +149,11 @@ postState = handlePOSTStatus( testStatus ); break; + case POST_STATE_VALVES: + testStatus = execValvesSelfTest(); + postState = POST_STATE_STUCK_BUTTON; + break; + // Should be last POST case POST_STATE_STUCK_BUTTON: testStatus = execStuckButtonTest(); Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -30,6 +30,7 @@ #include "TaskGeneral.h" #include "Timers.h" #include "TreatmentStop.h" +#include "Utilities.h" #include "Valves.h" #ifdef RM46_EVAL_BOARD_TARGET #include "Timers.h" @@ -708,6 +709,93 @@ /*********************************************************************//** * @brief + * The verifyPressureLimitsChange function verifies a user change request + * for in-line pressure alarm limits. If valid, new limits are accepted + * and set. + * @details Inputs: none + * @details Outputs: new pressure limits set, response sent + * @return TRUE if new pressure limits accepted, FALSE if not. + *************************************************************************/ +BOOL verifyPressureLimitsChange( PRESSURE_LIMIT_CHANGE_REQUEST_T *data ) +{ + BOOL result = TRUE; + CRITICAL_DATAS_T proposedNewArtLowLimit, proposedNewArtHighLimit; + CRITICAL_DATAS_T proposedNewVenLowLimit, proposedNewVenHighLimit; + PRESSURE_LIMIT_CHANGE_RESPONSE_T respRecord = { FALSE, 0, 0, 0, 0, 0 }; + + proposedNewArtLowLimit.sInt = data->artLowLimit; + proposedNewArtHighLimit.sInt = data->artHighLimit; + proposedNewVenLowLimit.sInt = data->venLowLimit; + proposedNewVenHighLimit.sInt = data->venHighLimit; + + // check ranges for changed limits + if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT, proposedNewArtLowLimit ) ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT, proposedNewArtHighLimit ) ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT, proposedNewVenLowLimit ) ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT, proposedNewVenHighLimit ) ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + + // if ranges ok, check separation between low/high limits + if ( TRUE == result ) + { + S32 arterialPresLimitDelta = data->artHighLimit - data->artLowLimit; + S32 venousPresLimitDelta = data->venHighLimit - data->venLowLimit; + + // check arterial alarm limits dependency + if ( arterialPresLimitDelta < MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_ARTERIAL_PRESSURE_LOW_VS_HIGH; + result = FALSE; + } + + // check venous alarm limits dependency + if ( venousPresLimitDelta < MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ) + { + respRecord.rejReasonCode = REQUEST_REJECT_REASON_VENOUS_PRESSURE_LOW_VS_HIGH; + result = FALSE; + } + } + + // set overall result - are changes accepted? + respRecord.accepted = result; + + // if changes accepted, set new pressure limits + if ( TRUE == result ) + { + setTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT, data->artLowLimit ); + setTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT, data->artHighLimit ); + setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT, data->venLowLimit ); + setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT, data->venHighLimit ); + } + + // read back limits for transmit to UI. + respRecord.artLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + respRecord.artHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + respRecord.venLowLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + respRecord.venHighLimit = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + // send response + sendPressureLimitsChangeResponse( &respRecord ); + + return result; +} + +/*********************************************************************//** + * @brief * The broadcastTreatmentTimeAndState function broadcasts treatment time and * state data during treatment. * @details Inputs: treatment time and state data Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -ra21a04cc7f2624b9c74992a8e918b71933802dd6 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision a21a04cc7f2624b9c74992a8e918b71933802dd6) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -32,6 +32,49 @@ // ********** public definitions ********** +/// Payload record structure for a treatment time status message. +typedef struct +{ + U32 treatmentTimePrescribedinSec; + U32 treatmentTimeElapsedinSec; + U32 treatmentTimeRemaininginSec; +} TREATMENT_TIME_DATA_T; + +/// Payload record structure for a treatment state message. +typedef struct +{ + U32 treatmentSubMode; + U32 uFState; + U32 salineBolusState; +} TREATMENT_STATE_DATA_T; + +/// Payload record structure for an ultrafiltration volume change confirmation message. +typedef struct +{ + F32 volume_mL; + U32 adjustType; +} UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T; + +/// Payload record structure for the in-line pressure limits change request. +typedef struct +{ + S32 artLowLimit; + S32 artHighLimit; + S32 venLowLimit; + S32 venHighLimit; +} PRESSURE_LIMIT_CHANGE_REQUEST_T; + +/// Payload record structure for the in-line pressure limits change response. +typedef struct +{ + BOOL accepted; + U32 rejReasonCode; + S32 artLowLimit; + S32 artHighLimit; + S32 venLowLimit; + S32 venHighLimit; +} PRESSURE_LIMIT_CHANGE_RESPONSE_T; + // ********** private function prototypes ********** void initTreatmentMode( void ); // initialize this module @@ -47,6 +90,7 @@ BOOL verifyUFSettingsChange( F32 uFVolume ); BOOL verifyUFSettingsConfirmation( F32 uFVolume, U32 adjustment ); BOOL verifyBloodAndDialysateRateSettingsChange( U32 bloodRate, U32 dialRate ); +BOOL verifyPressureLimitsChange( PRESSURE_LIMIT_CHANGE_REQUEST_T *data ); /**@}*/ Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -38,7 +38,6 @@ // ********** private definitions ********** #define MAX_DIALYSATE_VOLUME_ML ( 150 * ML_PER_LITER ) ///< Maximum dialysate volume (in mL) -#define MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ( 25 ) ///< Minimum pressure alarm limit delta (in mmHg) /// Record for range and default of treatment parameters. typedef struct @@ -95,7 +94,6 @@ static HD_TREATMENT_PARAMS_MODE_STATE_T handleWaitForUI2ConfirmState( void ); static BOOL checkTreatmentParamsInRange( U32 *reasons ); static BOOL checkTreatmentParamsDependencies( U32 *reasons ); -static BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ); static void extractTreatmentParamsFromPayload( TREATMENT_PARAMS_DATA_PAYLOAD_T payload ); static void sendTreatmentParamsResponse( BOOL rejected, U32 *reasons ); @@ -498,7 +496,7 @@ * @param value value of parameter to check range for * @return TRUE if given treatment parameter is in range, FALSE if not *************************************************************************/ -static BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ) +BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ) { BOOL result = FALSE; Index: firmware/App/Modes/ModeTreatmentParams.h =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/ModeTreatmentParams.h (.../ModeTreatmentParams.h) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Modes/ModeTreatmentParams.h (.../ModeTreatmentParams.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -32,6 +32,8 @@ // ********** public definitions ********** +#define MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ( 30 ) ///< Minimum pressure alarm limit delta (in mmHg) + /// Record structure for a treatment parameters payload. typedef struct { @@ -69,21 +71,22 @@ // ********** Public function prototypes ********** -void initTreatParamsMode( void ); // initialize this module -void transitionToTreatParamsMode( void ); // prepares for transition to treatment parameters mode -U32 execTreatParamsMode( void ); // execute the treatment parameters mode state machine (call from OperationModes) +void initTreatParamsMode( void ); // initialize this module +void transitionToTreatParamsMode( void ); // prepares for transition to treatment parameters mode +U32 execTreatParamsMode( void ); // execute the treatment parameters mode state machine (call from OperationModes) -BOOL validateAndSetTreatmentParameters( TREATMENT_PARAMS_DATA_PAYLOAD_T params ); // user provided treatment params to be set and validated -BOOL signalUserConfirmationOfTreatmentParameters( void ); // User has confirmed treatment parameters -BOOL signalUserRejectionOfTreatmentParameters( void ); // User has rejected treatment parameters -BOOL signalUserCancelTreatment( void ); // User has cancelled treatment +BOOL validateAndSetTreatmentParameters( TREATMENT_PARAMS_DATA_PAYLOAD_T params ); // user provided treatment params to be set and validated +BOOL signalUserConfirmationOfTreatmentParameters( void ); // User has confirmed treatment parameters +BOOL signalUserRejectionOfTreatmentParameters( void ); // User has rejected treatment parameters +BOOL signalUserCancelTreatment( void ); // User has cancelled treatment -BOOL setTreatmentParameterU32( TREATMENT_PARAM_T param, U32 value ); // Set a specified unsigned integer treatment parameter value -BOOL setTreatmentParameterS32( TREATMENT_PARAM_T param, S32 value ); // Set a specified signed integer treatment parameter value -BOOL setTreatmentParameterF32( TREATMENT_PARAM_T param, F32 value ); // Set a specified floating point treatment parameter value -U32 getTreatmentParameterU32( TREATMENT_PARAM_T param ); // Get a specified unsigned integer treatment parameter -S32 getTreatmentParameterS32( TREATMENT_PARAM_T param ); // Get a specified signed integer treatment parameter -F32 getTreatmentParameterF32( TREATMENT_PARAM_T param ); // Get a specified floating point treatment parameter +BOOL setTreatmentParameterU32( TREATMENT_PARAM_T param, U32 value ); // Set a specified unsigned integer treatment parameter value +BOOL setTreatmentParameterS32( TREATMENT_PARAM_T param, S32 value ); // Set a specified signed integer treatment parameter value +BOOL setTreatmentParameterF32( TREATMENT_PARAM_T param, F32 value ); // Set a specified floating point treatment parameter value +U32 getTreatmentParameterU32( TREATMENT_PARAM_T param ); // Get a specified unsigned integer treatment parameter +S32 getTreatmentParameterS32( TREATMENT_PARAM_T param ); // Get a specified signed integer treatment parameter +F32 getTreatmentParameterF32( TREATMENT_PARAM_T param ); // Get a specified floating point treatment parameter +BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ); // Check range for a proposed treatment parameter value BOOL testSetTreatmentParameter( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ); // Set a specific treatment parameter value Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -43,6 +43,7 @@ // ********** private data ********** static volatile BOOL modeRequest[ NUM_OF_MODES - 1 ]; ///< Pending operation mode change requests. +static HD_OP_MODE_T lastMode = MODE_INIT; ///< Last operation mode prior to current mode. static HD_OP_MODE_T currentMode = MODE_INIT; ///< Current operation mode. static U32 currentSubMode = 0; ///< The currently active state of the active mode. static U32 broadcastModeIntervalCtr = 11; ///< Interval counter used to determine when to broadcast operation mode. Initialize to 11 to stagger broadcast. @@ -124,6 +125,7 @@ if ( currentMode != newMode ) { // handle transition to new mode + lastMode = currentMode; transitionToNewOperationMode( newMode ); currentMode = newMode; } Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r1afb454d97cc2b73d61ea291205a6ed06d85577d -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 1afb454d97cc2b73d61ea291205a6ed06d85577d) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -18,7 +18,7 @@ #include "mibspi.h" #include "AlarmLamp.h" -#include "OperationModes.h" +#include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -37,7 +37,9 @@ #define ALM_ESC_1_MIN (1 * SEC_PER_MIN * MS_PER_SECOND) ///< Number of ms in 1 minute. #define ALM_ESC_4_MIN (4 * SEC_PER_MIN * MS_PER_SECOND) ///< Number of ms in 4 minutes. #define ALM_ESC_5_MIN (5 * SEC_PER_MIN * MS_PER_SECOND) ///< Number of ms in 5 minutes. -#define ALM_ESC_10_MIN (10 * SEC_PER_MIN * MS_PER_SECOND) ///< Number of ms in 10 minutes. +#define ALM_ESC_10_MIN (10 * SEC_PER_MIN * MS_PER_SECOND) ///< Number of ms in 10 minutes. + +#define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. #pragma pack(push,1) /// Record defining the properties of each individual alarm. @@ -160,12 +162,13 @@ { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DG_THERMISOTRS_TEMPERATURE_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DG_DIALYSATE_FILL_OUT_OF_TIME - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_CP1_SPEED_CONTROL_ERROR = 100 - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_CP2_SPEED_CONTROL_ERROR = 101 - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_FLOW_RATE_OUT_OF_RANGE = 102 + { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_CP1_SPEED_CONTROL_ERROR + { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_CP2_SPEED_CONTROL_ERROR + { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_FLOW_RATE_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DRAIN_PUMP_RPM_OUT_OF_RANGE { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DG_HEATERS_NEGATIVE_COLD_JUNCTION_TEMPERATURE + { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_DG_HEATERS_FAULT }; // *** This declaration will cause a compiler error if alarmTable does not have same # of alarms as the Alarm_List enumeration. @@ -869,6 +872,7 @@ { BOOL result = FALSE; + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; @@ -893,6 +897,7 @@ { BOOL result = FALSE; + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -920,6 +925,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { if ( TRUE == state ) @@ -952,6 +958,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -978,6 +985,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { U32 tim = getMSTimerCount(); @@ -1009,6 +1017,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { + // verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -1018,6 +1027,50 @@ } return result; +} + +/*********************************************************************//** + * @brief + * The testClearAllAlarms function clears all active alarms, even if they + * are non-recoverable or faults. The caller of this function must provide + * the correct 32-bit key. A Dialin user must also be logged into HD. + * @details Inputs: none + * @details Outputs: alarmIsActive[], alarmStartedAt[] + * @param key 32-bit supervior alarm key required to perform this function + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testClearAllAlarms( U32 key ) +{ + BOOL result = FALSE; + + // verify key + if ( SUPERVISOR_ALARM_KEY == key ) + { + // verify tester has logged in with HD + if ( TRUE == isTestingActivated() ) + { + ALARM_ID_T a; + + // clear all active alarms + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == alarmIsActive[ a ] ) + { + broadcastAlarmCleared( a ); + alarmIsActive[ a ] = FALSE; + alarmStartedAt[ a ].data = 0; + // clear FIFO if this alarm was in it + if ( alarmPriorityFIFO[ alarmTable[ a ].alarmPriority ] == a ) + { + resetAlarmPriorityFIFO( alarmTable[ a ].alarmPriority ); + } + } + } + result = TRUE; + } + } + + return result; } /**@}*/ Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -45,7 +45,7 @@ NUM_OF_ALARM_DATA_TYPES ///< Total number of alarm data types. } ALARM_DATA_TYPES_T; -#pragma pack(push,4) +#pragma pack(push, 4) /// Record structure for detailing the properties of the current composite alarm status. typedef struct { @@ -106,6 +106,18 @@ ALARM_DATA_TYPES_T dataType; ///< The type of alarm data provided. ALARM_DATAS_T data; ///< The alarm data of specified type. } ALARM_DATA_T; +#pragma pack(pop) + +#pragma pack(push, 2) +/// Payload record structure for an alarm status message. +typedef struct +{ + U32 alarmState; ///< Alarm state: 0 = no alarms, 1 = low priority, 2 = medium priority, 3 = high priority + U32 alarmTop; ///< ID of top active alarm + U32 escalatesIn; ///< Top active alarm escalates in this many seconds + U32 silenceExpiresIn; ///< Silencing of alarms expires in this many seconds + U16 alarmsFlags; ///< bit flags: 1 = true, 0 = false for each bit flag +} ALARM_COMP_STATUS_PAYLOAD_T; #pragma pack(pop) /// Listing of specific software faults for logging purposes. @@ -153,19 +165,19 @@ SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_DIRECTION, SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_STATE, // 40 SW_FAULT_ID_DIAL_OUT_FLOW_SET_TOO_HIGH, - SW_FAULT_ID_BLOOD_FLOW_INVALID_FILTER_STATE, - SW_FAULT_ID_DIAL_IN_FLOW_INVALID_FILTER_STATE, + SW_FAULT_ID____AVAILABLE_1, + SW_FAULT_ID____AVAILABLE_2, SW_FAULT_ID_RTC_EXEC_INVALID_STATE, SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, // 45 SW_FAULT_ID_RTC_TRANSACTION_SERVICE_INVALID_STATE, SW_FAULT_ID_PRES_OCCL_INVALID_STATE, - SW_FAULT_ID_PRES_OCCL_INVALID_PRES_SENSOR, - SW_FAULT_ID_PRES_OCCL_INVALID_OCCL_SENSOR, + SW_FAULT_ID____AVAILABLE_3, + SW_FAULT_ID____AVAILABLE_4, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL, // 50 SW_FAULT_ID_PI_CTRL_INVALID_CONTROLLER, SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL, - SW_FAULT_ID_DIAL_OUT_INVALID_MEASURED_SIGNAL_STATE, - SW_FAULT_ID_DIAL_OUT_SET_RX_OUT_OF_RANGE, + SW_FAULT_ID____AVAILABLE_5, + SW_FAULT_ID____AVAILABLE_6, SW_FAULT_ID_DIALYSIS_INVALID_STATE, // 55 SW_FAULT_ID_DIALYSIS_INVALID_UF_STATE, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, @@ -224,7 +236,8 @@ BOOL testSetAlarmStateOverride( U32 alarmID, BOOL value ); BOOL testResetAlarmStateOverride( U32 alarmID ); BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ); -BOOL testResetAlarmStartOverride( U32 alarmID ); +BOOL testResetAlarmStartOverride( U32 alarmID ); +BOOL testClearAllAlarms( U32 key ); /**@}*/ Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rc9e1a93ccd8cfbdc9737c8ffc9e6a3dbe9ba7c44 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision c9e1a93ccd8cfbdc9737c8ffc9e6a3dbe9ba7c44) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -8,7 +8,7 @@ * @file FPGA.c * * @author (last) Sean Nash -* @date (last) 09-Sep-2020 +* @date (last) 14-Oct-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -78,6 +78,9 @@ #define FPGA_ADC1_AUTO_READ_ENABLE 0x01 ///< Auto-read enable bit for ADC1 control register. +#define FPGA_AIRTRAP_LEVEL_LOW_MASK 0x0008 ///< Bit mask for air trap lower level sensor. +#define FPGA_AIRTRAP_LEVEL_HIGH_MASK 0x0004 ///< Bit mask for air trap upper level sensor. + // FPGA Sensors Record #pragma pack(push,1) /// Record structure for FPGA header read. @@ -164,6 +167,23 @@ U16 VDiPWMTarget; ///< Reg 374. PWM target duty cycle for VDi pinch valve. U16 VDoPWMTarget; ///< Reg 376. PWM target duty cycle for VDo pinch valve. U16 VSparePWMTarget; ///< Reg 378. PWM target duty cycle for Vspare pinch valve. + U16 SyringePumpStatus; ///< Reg 380. Syringe pump status register + U16 SyringePumpEncStatus; ///< Reg 382. Syringe pump encoder status + U32 SyringePumpEncPosition; ///< Reg 384. Syringe pump encoder position + U16 sPumpAdcDataReadChannel0; ///< Reg 388. + U16 sPumpAdcDataReadCh1; ///< Reg 390. + U16 sPumpAdcDataReadCh2; ///< Reg 392. + U16 sPumpAdcDataReadCh3; ///< Reg 394. + U16 VBASpeed; ///< Reg 396. VBA pinch valve speed (Register VAUX0) + U16 VBVSpeed; ///< Reg 398. VBV pinch valve speed (Register VAUX1) + U16 VBVCurrent; ///< Reg 400. VBV pinch valve current (Register VAUX2) + U16 VDoCurrent; ///< Reg 402. VDo pinch valve current (Register VAUX3) + U16 VBACurrent; ///< Reg 404. VBA pinch valve current (Register VAUX8) + U16 VDiSpeed; ///< Reg 406. VDi pinch valve current (Register VAUX9) + U16 VDoSpeed; ///< Reg 408. VDo pinch valve speed (Register VAUX10) + U16 VDiCurrent; ///< Reg 410. VDi pinch valve current (Register VAUX11) + U16 VSpareSpeed; ///< Reg 412. VSpare speed (Register VAUX5) + U16 VSpareCurrent; ///< Reg 414. VSpare current (Register VAUX13) } FPGA_SENSORS_T; /// Record structure for FPGA continuous priority writes. @@ -183,6 +203,7 @@ U08 AlarmControl; ///< Reg 34. Alarm (audio) control register. } FPGA_ACTUATORS_T; +// TODO clean up the struct /// Record structure for FPGA async (as needed) reads. typedef struct // TODO - add all sensor readings to this structure per FPGA register map { @@ -268,9 +289,8 @@ /*********************************************************************//** * @brief * The initFPGA function initializes the FPGA module. - * @details - * Inputs : none - * Outputs : FPGA module initialized. + * @details Inputs: none + * @details Outputs: FPGA module initialized. * @return none *************************************************************************/ void initFPGA( void ) @@ -379,9 +399,8 @@ * @brief * The resetFPGACommFlags function resets the various fpga comm flags and * counters. - * @details - * Inputs : none - * Outputs : fpga comm flags & counters reset + * @details Inputs: none + * @details Outputs: fpga comm flags & counters reset * @return none *************************************************************************/ static void resetFPGACommFlags( void ) @@ -399,9 +418,8 @@ * @brief * The signalFPGAReceiptCompleted function increments a counter to indicate * that another DMA receipt from the FPGA has completed. - * @details - * Inputs : none - * Outputs : fpgaReceiptCounter + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter * @return none *************************************************************************/ void signalFPGAReceiptCompleted( void ) @@ -434,9 +452,8 @@ * @brief * The signalFPGATransmitCompleted function increments a counter to indicate * that another DMA transmit to the FPGA has completed. - * @details - * Inputs : none - * Outputs : fpgaReceiptCounter + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter * @return none *************************************************************************/ void signalFPGATransmitCompleted( void ) @@ -447,9 +464,8 @@ /*********************************************************************//** * @brief * The execFPGA function manages incoming data exchanges with the FPGA. - * @details - * Inputs : fpgaState - * Outputs : fpgaState + * @details Inputs: fpgaState + * @details Outputs: fpgaState * @return none *************************************************************************/ void execFPGAIn( void ) @@ -506,9 +522,8 @@ /*********************************************************************//** * @brief * The execFPGAOut function manages outgoing data exchanges with the FPGA. - * @details - * Inputs : fpgaState - * Outputs : fpgaState + * @details Inputs: fpgaState + * @details Outputs: fpgaState * @return none *************************************************************************/ void execFPGAOut( void ) @@ -553,9 +568,8 @@ * @brief * The handleFPGAReadHeaderState function handles the FPGA state where * the read header registers command is sent to the FPGA. - * @details - * Inputs : none - * Outputs : read command sent to FPGA + * @details Inputs: none + * @details Outputs: read command sent to FPGA * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAReadHeaderState( void ) @@ -585,9 +599,8 @@ * @brief * The handleFPGAReceiveHeaderState function handles the FPGA state * where the header registers read response should be ready to take in. - * @details - * Inputs : none - * Outputs : header register values updated + * @details Inputs: none + * @details Outputs: header register values updated * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAReceiveHeaderState( void ) @@ -637,9 +650,8 @@ * @brief * The handleFPGAWriteAllActuatorsState function handles the FPGA state * where the bulk write command is sent to the FPGA. - * @details - * Inputs : actuator set points - * Outputs : actuator set points sent to FPGA + * @details Inputs: actuator set points + * @details Outputs: actuator set points sent to FPGA * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ) @@ -686,9 +698,8 @@ * @brief * The handleFPGAReceiveAllSensorsState function handles the FPGA state * where the bulk read response should be ready to parse. - * @details - * Inputs : none - * Outputs : sensor values updated + * @details Inputs: none + * @details Outputs: sensor values updated * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ) @@ -749,9 +760,8 @@ * @brief * The handleFPGAReadAllSensorsAsyncState function handles the FPGA state where * the read async sensors command is sent to the FPGA. - * @details - * Inputs : none - * Outputs : read async sensors command sent to FPGA + * @details Inputs: none + * @details Outputs: read async sensors command sent to FPGA * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAReadAllSensorsAsyncState( void ) @@ -781,9 +791,8 @@ * @brief * The handleFPGAReceiveAllSensorsAsyncState function handles the FPGA state * where the bulk async read response should be ready to parse. - * @details - * Inputs : none - * Outputs : async sensor values updated + * @details Inputs: none + * @details Outputs: async sensor values updated * @return next FPGA state *************************************************************************/ static FPGA_STATE_T handleFPGAReceiveAllSensorsAsyncState( void ) @@ -833,9 +842,8 @@ /*********************************************************************//** * @brief * The execFPGATest function executes the FPGA self-test. - * @details - * Inputs : fpgaHeader - * Outputs : none + * @details Inputs: fpgaHeader + * @details Outputs: none * @return passed, or failed *************************************************************************/ SELF_TEST_STATUS_T execFPGATest( void ) @@ -862,11 +870,30 @@ /*********************************************************************//** * @brief + * The consumeUnexpectedData function checks to see if a byte is sitting in + * the SCI2 received data register. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return fpgaDiag + *************************************************************************/ +static void consumeUnexpectedData( void ) +{ + // clear any errors + sciRxError( scilinREG ); + + // if a byte is pending read, read it + if ( sciIsRxReady( scilinREG ) != 0 ) + { + sciReceiveByte( scilinREG ); + } +} + +/*********************************************************************//** + * @brief * The setupDMAForWriteCmd function sets the byte count for the next DMA * write command to the FPGA. - * @details - * Inputs : none - * Outputs : number of bytes for next FPGA write command is set + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA write command is set * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA * @return none *************************************************************************/ @@ -887,9 +914,8 @@ * @brief * The startDMAWriteCmd function initiates the DMA transmit for the next * DMA write command to the FPGA. - * @details - * Inputs : none - * Outputs : DMA write command to FPGA is initiated + * @details Inputs: none + * @details Outputs: DMA write command to FPGA is initiated * @return none *************************************************************************/ static void startDMAWriteCmd( void ) @@ -903,9 +929,8 @@ * @brief * The setupDMAForWriteResp function sets the expected byte count for the * next DMA write command response from the FPGA. - * @details - * Inputs : none - * Outputs : number of expected bytes for next FPGA write command response is set + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA write command response is set * @param bytes2Receive number of bytes expected to be transmitted via DMA from the FPGA * @return none *************************************************************************/ @@ -926,9 +951,8 @@ * @brief * The startDMAReceiptOfWriteResp function initiates readiness of the DMA * receiver for the next DMA write command response from the FPGA. - * @details - * Inputs : none - * Outputs : DMA write command response is ready to be received from the FPGA + * @details Inputs: none + * @details Outputs: DMA write command response is ready to be received from the FPGA * @return none *************************************************************************/ static void startDMAReceiptOfWriteResp( void ) @@ -942,9 +966,8 @@ * @brief * The setupDMAForReadCmd function sets the byte count for the next DMA * read command to the FPGA. - * @details - * Inputs : none - * Outputs : number of bytes for next FPGA read command is set + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA read command is set * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA * @return none *************************************************************************/ @@ -965,9 +988,8 @@ * @brief * The startDMAReadCmd function initiates the DMA transmit for the next * DMA read command to the FPGA. - * @details - * Inputs : none - * Outputs : DMA read command to FPGA is initiated + * @details Inputs: none + * @details Outputs: DMA read command to FPGA is initiated * @return none *************************************************************************/ static void startDMAReadCmd( void ) @@ -981,9 +1003,8 @@ * @brief * The setupDMAForReadResp function sets the expected byte count for the * next DMA read command response from the FPGA. - * @details - * Inputs : none - * Outputs : number of expected bytes for next FPGA read command response is set + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA read command response is set * @param bytes2Receive number of expected bytes to be transmitted via DMA from the FPGA * @return none *************************************************************************/ @@ -1004,9 +1025,8 @@ * @brief * The startDMAReceiptOfReadResp function initiates readiness of the DMA * receiver for the next DMA read command response from the FPGA. - * @details - * Inputs : none - * Outputs : DMA read command response is ready to be received from the FPGA + * @details Inputs: none + * @details Outputs: DMA read command response is ready to be received from the FPGA * @return none *************************************************************************/ static void startDMAReceiptOfReadResp( void ) @@ -1019,9 +1039,8 @@ /*********************************************************************//** * @brief * The getFPGAVersions function gets the fpga version numbers. - * @details - * Inputs : fpgaHeader - * Outputs : none + * @details Inputs: fpgaHeader + * @details Outputs: none * @return none *************************************************************************/ void getFPGAVersions( U08 *Id, U08 *Maj, U08 *Min, U08 *Lab ) @@ -1036,9 +1055,8 @@ * @brief * The getFPGABloodFlowSignalStrength function gets the latest blood flow * signal strength reading. - * @details - * Inputs : fpgaSensorReadings2 - * Outputs : none + * @details Inputs: fpgaSensorReadings2 + * @details Outputs: none * @return last blood flow signal strength reading *************************************************************************/ F32 getFPGABloodFlowSignalStrength( void ) @@ -1050,9 +1068,8 @@ * @brief * The getFPGADialysateFlowSignalStrength function gets the latest dialysate * flow signal strength reading. - * @details - * Inputs : fpgaSensorReadings2 - * Outputs : none + * @details Inputs: fpgaSensorReadings2 + * @details Outputs: none * @return last dialysate flow signal strength reading *************************************************************************/ F32 getFPGADialysateFlowSignalStrength( void ) @@ -1063,9 +1080,8 @@ /*********************************************************************//** * @brief * The getFPGABloodFlow function gets the latest blood flow reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last blood flow reading *************************************************************************/ F32 getFPGABloodFlow( void ) @@ -1076,9 +1092,8 @@ /*********************************************************************//** * @brief * The getFPGADialysateFlow function gets the latest dialysate flow reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate flow reading *************************************************************************/ F32 getFPGADialysateFlow( void ) @@ -1093,9 +1108,8 @@ * counting up, indicates motor is running in forward direction. If counter is * counting down, indicates motor is running in reverse direction. Counter will * wrap at 0/65535. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last blood pump hall sensor count reading. *************************************************************************/ U16 getFPGABloodPumpHallSensorCount( void ) @@ -1110,9 +1124,8 @@ * Bit 0 - Derived direction of the blood pump motor (0=Fwd, 1=Rev) * Bit 1 - A direction error was detected in the current hall sensor phase * Bit 2 - A direction error was detected since the last read of this register - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last blood pump hall sensor status reading. *************************************************************************/ U08 getFPGABloodPumpHallSensorStatus( void ) @@ -1127,9 +1140,8 @@ * counting up, indicates motor is running in forward direction. If counter is * counting down, indicates motor is running in reverse direction. Counter will * wrap at 0/65535. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate inlet pump hall sensor count reading. *************************************************************************/ U16 getFPGADialInPumpHallSensorCount( void ) @@ -1144,9 +1156,8 @@ * Bit 0 - Derived direction of the dialyste inlet pump motor (0=Fwd, 1=Rev) * Bit 1 - A direction error was detected in the current hall sensor phase * Bit 2 - A direction error was detected since the last read of this register - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate inlet pump hall sensor status reading. *************************************************************************/ U08 getFPGADialInPumpHallSensorStatus( void ) @@ -1161,9 +1172,8 @@ * counting up, indicates motor is running in forward direction. If counter is * counting down, indicates motor is running in reverse direction. Counter will * wrap at 0/65535. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate outlet pump hall sensor count reading. *************************************************************************/ U16 getFPGADialOutPumpHallSensorCount( void ) @@ -1178,9 +1188,8 @@ * Bit 0 - Derived direction of the dialysate outlet pump motor (0=Fwd, 1=Rev) * Bit 1 - A direction error was detected in the current hall sensor phase * Bit 2 - A direction error was detected since the last read of this register - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate outlet pump hall sensor status reading. *************************************************************************/ U08 getFPGADialOutPumpHallSensorStatus( void ) @@ -1191,9 +1200,8 @@ /*********************************************************************//** * @brief * The getFPGABloodPumpOcclusion function gets the latest blood occlusion reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last blood occlusion reading *************************************************************************/ U16 getFPGABloodPumpOcclusion( void ) @@ -1205,9 +1213,8 @@ * @brief * The getFPGADialInPumpOcclusion function gets the latest dialysate * inlet occlusion reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate inlet occlusion reading *************************************************************************/ U16 getFPGADialInPumpOcclusion( void ) @@ -1219,9 +1226,8 @@ * @brief * The getFPGADialOutPumpOcclusion function gets the latest dialysate * outlet occlusion reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last dialysate outlet occlusion reading *************************************************************************/ U16 getFPGADialOutPumpOcclusion( void ) @@ -1235,9 +1241,8 @@ * High byte indicates alarm status for ADC channel. * Low 24-bits are channel reading. Subtract 2^23 from low 24 bits to get * signed channel reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last arterial pressure reading *************************************************************************/ U32 getFPGAArterialPressure( void ) @@ -1251,9 +1256,8 @@ * The high 2 bits are status bits: 00=ok, 01=cmd mode, 10=stale data, 11=diag * The low 14 bits are data. Zero is at 1638. Values above are positive, * below are negative. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @return last venous pressure reading *************************************************************************/ U16 getFPGAVenousPressure( void ) @@ -1265,9 +1269,8 @@ * @brief * The getFPGAAccelAxes function gets the accelerometer axis readings. * Axis readings are in ADC counts. 0.004 g per LSB. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @param x Populate this param with X axis reading * @param y Populate this param with Y axis reading * @param z Populate this param with Z axis reading @@ -1285,9 +1288,8 @@ * The getFPGAAccelMaxes function gets the maximum accelerometer axis readings. * from last FPGA read (every 10ms). * Axis readings are in ADC counts. 0.004 g per LSB. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @param x Populate this param with maximum X axis reading * @param y Populate this param with maximum Y axis reading * @param z Populate this param with maximum Z axis reading @@ -1304,9 +1306,8 @@ * @brief * The getFPGAAccelStatus function gets the accelerometer reading count * and error register values. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none + * @details Inputs: fpgaSensorReadings + * @details Outputs: none * @param cnt Populate this param with latest sample counter value * @param err Populate this param with latest error * @return none @@ -1319,22 +1320,316 @@ /*********************************************************************//** * @brief - * The consumeUnexpectedData function checks to see if a byte is sitting in - * the SCI2 received data register. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @return fpgaDiag + * The getFPGAAirTrapLevels function gets the latest air trap level sensor + * readings. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return none *************************************************************************/ -static void consumeUnexpectedData( void ) +void getFPGAAirTrapLevels( BOOL *airAtLower, BOOL *airAtUpper ) { - // clear any errors - sciRxError( scilinREG ); - // if a byte is pending read, read it - if ( sciIsRxReady( scilinREG ) != 0 ) - { - sciReceiveByte( scilinREG ); - } + U16 fpgaGPIO = fpgaSensorReadings.fpgaGPIO; + U16 lower = fpgaGPIO & FPGA_AIRTRAP_LEVEL_LOW_MASK; + U16 upper = fpgaGPIO & FPGA_AIRTRAP_LEVEL_HIGH_MASK; + + *airAtLower = ( 0 == lower ? FALSE : TRUE ); + *airAtUpper = ( 0 == upper ? FALSE : TRUE ); } -/**@}*/ +/*********************************************************************//** + * @brief + * The setFPGAValvesControlMode function sets the valves control mode. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param bits : The bits to enable the PID controller of a valve + * @return none + *************************************************************************/ +void setFPGAValvesControlMode( U16 bits ) +{ + fpgaActuatorSetPoints.fpgaPIDControl = bits; +} + +/*********************************************************************//** + * @brief + * The getValvesStatus function reads the status of the valves + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return The status of the valves + *************************************************************************/ +U16 getFPGAValvesStatus( void ) +{ + return fpgaSensorReadings.valveStatus; +} + +/*********************************************************************//** + * @brief + * The setValveDialyzerInletPosition function sets the position of VDi + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerInletPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VDiSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveDialyzerInletPosition function reads the current position + * of VDi in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VDi + *************************************************************************/ +S16 getFPGAValveDialyzerInletPosition( void ) +{ + return fpgaSensorReadings.VDiPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerInletCurrentCounts function reads the current \n + * of VDi in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VDi + *************************************************************************/ +U16 getFPGAValveDialyzerInletCurrentCounts( void ) +{ + return fpgaSensorReadings.VDiCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerInletPWM function sets the PWM of VDI in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VDI in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerInletPWM( U16 count ) +{ + fpgaActuatorSetPoints.VDiPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerInletPWM function reads the current PWM target + * of VDI. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VDI + *************************************************************************/ +U16 getFPGAValveDialyzerInletPWM( void ) +{ + return fpgaSensorReadings.VDiPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerOutletPosition function sets the position of VDo + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerOutletPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VDoSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletPosition function reads the current position + * of VDo in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VDo + *************************************************************************/ +S16 getFPGAValveDialyzerOutletPosition( void ) +{ + return fpgaSensorReadings.VDoPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletCurrentCounts function reads the current + * of VDo in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VDo + *************************************************************************/ +U16 getFPGAValveDialyzerOutletCurrentCounts( void ) +{ + return fpgaSensorReadings.VDoCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerOutletPWM function sets the PWM of VDO in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VDO in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerOutletPWM( U16 count ) +{ + fpgaActuatorSetPoints.VDoPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletPWM function reads the current PWM target + * of VDO. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VDO + *************************************************************************/ +U16 getFPGAValveDialyzerOutletPWM( void ) +{ + return fpgaSensorReadings.VDoPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setValveBloodVenousPosition function sets the position of VBV + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodVenousPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VBVSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveBloodVenousPosition function reads the current position + * of VBV in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VBV + *************************************************************************/ +S16 getFPGAValveBloodVenousPosition( void ) +{ + return fpgaSensorReadings.VBVPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodVenousCurrentCounts function reads the current + * of VBV in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VBV + *************************************************************************/ +U16 getFPGAValveBloodVenousCurrentCounts( void ) +{ + return fpgaSensorReadings.VBVCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveBloodVenousPWM function sets the PWM of VBV in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VBV in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodVenousPWM( U16 count ) +{ + fpgaActuatorSetPoints.VBVPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodVenousPWM function returns the PWM of VBV in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: none + * @return returns the PWM of VBV in counts + *************************************************************************/ +U16 getFPGAValveBloodVenousPWM( void ) +{ + return fpgaSensorReadings.VBVPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setValveBloodArterialPosition function sets the position of VBA + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodArterialPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VBASetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveBloodArterialPosition function reads the current position + * of VBA in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VBA + *************************************************************************/ +S16 getFPGAValveBloodArterialPosition( void ) +{ + return fpgaSensorReadings.VBAPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodArterialCurrentCounts function reads the current + * of VBA in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VBA + *************************************************************************/ +U16 getFPGAValveBloodArterialCurrentCounts( void ) +{ + return fpgaSensorReadings.VBACurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveBloodArterialPWM function sets a PWM for VBA in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VBA in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodArterialPWM( U16 count ) +{ + fpgaActuatorSetPoints.VBAPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodArterialPWM function returns the current PWM of + * VBA in counts. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VBA in counts + *************************************************************************/ +U16 getFPGAValveBloodArterialPWM( void ) +{ + return fpgaSensorReadings.VBAPWMTarget; +} +#endif + +/**@}*/ Index: firmware/App/Services/FPGA.h =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -58,7 +58,7 @@ U16 getFPGADialOutPumpHallSensorCount( void ); U08 getFPGADialOutPumpHallSensorStatus( void ); -S32 getFPGAArterialPressure( void ); +U32 getFPGAArterialPressure( void ); U16 getFPGAVenousPressure( void ); U16 getFPGABloodPumpOcclusion( void ); U16 getFPGADialInPumpOcclusion( void ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -1195,6 +1195,10 @@ handleUIUserEndTreatmentRequest( message ); break; + case MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST: + handleChangePressureLimitsRequest( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; @@ -1439,6 +1443,18 @@ handleTestDialOutPumpHomeRequest( message ); break; + case MSG_ID_SUPER_CLEAR_ALARMS_CMD: + handleTestSuperClearAlarmsRequest( message ); + break; + + case MSG_ID_HD_REQUEST_CALIBRATION_DATA: + handleTestHDCalibrationDataRequest( message ); + break; + + case MSG_ID_HD_ERASE_CALIBRATION_DATA: + handleTestEraseHDCalibrationDataRequest( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r1afb454d97cc2b73d61ea291205a6ed06d85577d -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 1afb454d97cc2b73d61ea291205a6ed06d85577d) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -24,7 +24,6 @@ #include "Buttons.h" #include "DGInterface.h" #include "FPGA.h" -#include "MessagePayloads.h" #include "ModePreTreat.h" #include "ModeStandby.h" #include "ModeTreatment.h" @@ -400,8 +399,37 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; -} - +} + +/*********************************************************************//** + * @brief + * The sendChangePressureLimitsChangeResponse function constructs a change + * pressure limits response to the UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Pressure limits change response msg constructed and queued. + * @param data response data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendPressureLimitsChangeResponse( PRESSURE_LIMIT_CHANGE_RESPONSE_T *data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE; + msg.hdr.payloadLen = sizeof( PRESSURE_LIMIT_CHANGE_RESPONSE_T ); + + memcpy( payloadPtr, (U08*)data, sizeof( PRESSURE_LIMIT_CHANGE_RESPONSE_T ) ); + + // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} + /*********************************************************************//** * @brief * The sendTreatmentParamsRangesToUI function constructs a treatment parameter @@ -894,26 +922,19 @@ * @param doOccl Latest measured dialysate outlet pump occlusion pressure * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL broadcastPresOcclData( F32 artPres, F32 venPres, F32 bpOccl, F32 diOccl, F32 doOccl ) +BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; - PRESSURE_OCCLUSION_DATA_T payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_PRESSURE_OCCLUSION_DATA; msg.hdr.payloadLen = sizeof( PRESSURE_OCCLUSION_DATA_T ); - payload.arterialPressure = artPres; - payload.venousPressure = venPres; - payload.bldPumpOcclusion = bpOccl; - payload.diPumpOcclusion = diOccl; - payload.doPumpOcclusion = doOccl; + memcpy( payloadPtr, &data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); - memcpy( payloadPtr, &payload, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); @@ -1793,6 +1814,31 @@ /*********************************************************************//** * @brief + * The handleChangePressureLimitsRequest function handles a pressure limits + * change message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleChangePressureLimitsRequest( MESSAGE_T *message ) +{ + if ( sizeof( PRESSURE_LIMIT_CHANGE_REQUEST_T ) == message->hdr.payloadLen ) + { + PRESSURE_LIMIT_CHANGE_REQUEST_T data; + + memcpy( &data, &message->payload[0], sizeof(PRESSURE_LIMIT_CHANGE_REQUEST_T) ); + + verifyPressureLimitsChange( &data ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief * The handleSalineBolusRequest function handles a saline bolus request * message from the UI. * @details Inputs: none @@ -2284,14 +2330,7 @@ if ( sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) == message->hdr.payloadLen ) { memcpy( &payload, message->payload, sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) ); - if ( FALSE == payload.reset ) - { - result = testSetTargetBloodFlowRateOverride( payload.setPt, payload.ctrlMode ); - } - else - { - result = testResetTargetBloodFlowRateOverride(); - } + result = testSetTargetBloodFlowRateOverride( payload.setPt, payload.ctrlMode ); } // respond to request @@ -2540,14 +2579,7 @@ if ( sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) == message->hdr.payloadLen ) { memcpy( &payload, message->payload, sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) ); - if ( FALSE == payload.reset ) - { - result = testSetTargetDialInFlowRateOverride( payload.setPt, payload.ctrlMode ); - } - else - { - result = testResetTargetDialInFlowRateOverride(); - } + result = testSetTargetDialInFlowRateOverride( payload.setPt, payload.ctrlMode ); } // respond to request @@ -2572,14 +2604,7 @@ if ( sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) == message->hdr.payloadLen ) { memcpy( &payload, message->payload, sizeof(OVERRIDE_PUMP_SET_PT_PAYLOAD_T) ); - if ( FALSE == payload.reset ) - { - result = testSetTargetDialOutFlowRateOverride( payload.setPt, payload.ctrlMode ); - } - else - { - result = testResetTargetDialOutFlowRateOverride(); - } + result = testSetTargetDialOutFlowRateOverride( payload.setPt, payload.ctrlMode ); } // respond to request @@ -3839,4 +3864,99 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleTestSuperClearAlarmsRequest function handles a request to clear + * all active alarms. + * @details + * Inputs : none + * Outputs : message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + U32 key; + + memcpy( &key, message->payload, sizeof(U32) ); + result = testClearAllAlarms( key ); + + result = TRUE; + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestHDCalibrationDataRequest function handles a request for + * HD calibration data. + * @details + * Inputs : none + * Outputs : message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestHDCalibrationDataRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( 0 == message->hdr.payloadLen ) + { + CALIBRATION_DATA_T cal; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // get calibration data + result = getCalibrationData( &cal ); + if ( TRUE == result ) + { + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_CALIBRATION_DATA; + msg.hdr.payloadLen = sizeof( CALIBRATION_DATA_T ); + + memcpy( payloadPtr, &cal, sizeof( CALIBRATION_DATA_T ) ); + + // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestEraseHDCalibrationDataRequest function handles a request for + * HD calibration data erasure. + * @details + * Inputs : none + * Outputs : message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestEraseHDCalibrationDataRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + U32 key; + + memcpy( &key, message->payload, sizeof(U32) ); + + result = testResetCalibrationData( key ); + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -25,7 +25,10 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" +#include "ModeTreatment.h" #include "MsgQueues.h" +#include "NVDataMgmt.h" +#include "PresOccl.h" #include "Valves.h" /** @@ -141,6 +144,12 @@ // MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_RESPONSE BOOL sendChangeBloodDialysateRateChangeResponse( BOOL accepted, U32 reason, U32 bloodRate, U32 dialRate ); +// MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST +void handleChangePressureLimitsRequest( MESSAGE_T *message ); + +// MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE +BOOL sendPressureLimitsChangeResponse( PRESSURE_LIMIT_CHANGE_RESPONSE_T *data ); + // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS BOOL sendDialysateTempTargetsToDG( F32 primary, F32 trimmer ); @@ -187,7 +196,7 @@ BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); // MSG_ID_PRESSURE_OCCLUSION_DATA -BOOL broadcastPresOcclData( F32 artPres, F32 venPres, F32 bpOccl, F32 diOccl, F32 doOccl ); +BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ); // MSG_ID_RTC_EPOCH BOOL broadcastRTCEpoch( U32 epoch ); @@ -411,6 +420,15 @@ // MSG_ID_HD_AIR_TRAP_LEVEL_SENSOR_OVERRIDE void handleSetAirTrapLevelSensorOverrideRequest( MESSAGE_T *message ); +// MSG_ID_SUPER_CLEAR_ALARMS_CMD +void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ); + +// MSG_ID_HD_REQUEST_CALIBRATION_DATA +void handleTestHDCalibrationDataRequest( MESSAGE_T *message ); + +// MSG_ID_HD_ERASE_CALIBRATION_DATA +void handleTestEraseHDCalibrationDataRequest( MESSAGE_T *message ); + /**@}*/ #endif Index: results/Build_Status_Report.csv =================================================================== diff -u -raf8ec2ae93239816473d5e1ae671eb8c293a4ee6 -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- results/Build_Status_Report.csv (.../Build_Status_Report.csv) (revision af8ec2ae93239816473d5e1ae671eb8c293a4ee6) +++ results/Build_Status_Report.csv (.../Build_Status_Report.csv) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -1,6 +1,6 @@ Running Project, hdfirmware -Date, Tue Nov 24 10:11:39 PST 2020 +Date, Tue Dec 1 11:22:41 PST 2020 VectorCAST Pass/Fail Status, Passed @@ -26,7 +26,9 @@ dialysis,handleUFRunningState dialysis,handleSalineBolusInProgressState -Integration Test Coverage, Passed +Integration Test Coverage, Failed +The following test(s) failed: +VectorCAST_MinGW_C_LinuxTestSuite_INT_UTILITIES_management_report.html,Coverage(%):,90 Integration Test Manual Cases Module, Function Name @@ -46,6 +48,7 @@ nvdatamgmt,getMfgData nvdatamgmt,setCalibrationData nvdatamgmt,getCalibrationData +nvdatamgmt,testResetCalibrationData nvdatamgmt,setServiceDate nvdatamgmt,getServiceDate nvdatamgmt,writeLogData @@ -67,11 +70,8 @@ nvdatamgmt,enqueueBank7Sector0Records nvdatamgmt,eraseDataLogSectors accel,getAccelCalibration -utilities,hexStrToDec -presoccl,setOcclusionThreshold +presoccl,isCartridgeLoaded presoccl,handlePresOcclInitState -presoccl,getMeasuredArterialPressure -presoccl,getMeasuredVenousPressure presoccl,execPresOcclTest safetyshutdown,isSafetyShutdownActivated modetreatment,handleTreatmentDialysisState @@ -118,6 +118,7 @@ dialinflow,handleDialInPumpRampingUpState dialinflow,handleDialInPumpRampingDownState dialinflow,handleDialInPumpControlToTargetState +dialinflow,getTargetDialInFlowRate dialinflow,execDialInFlowTest dialinflow,getDialInFlowCalibration airtrap,startAirTrapControl Fisheye: Tag fff308d96794e7df7e91149173c3760ff3fda10c refers to a dead (removed) revision in file `results/VectorCAST.log'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag fff308d96794e7df7e91149173c3760ff3fda10c refers to a dead (removed) revision in file `results/cppcheckError.csv'. Fisheye: No comparison available. Pass `N' to diff?