Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -rc9df9f42e294adae397a57bf83c2a67fa831b164 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision c9df9f42e294adae397a57bf83c2a67fa831b164) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -67,17 +67,17 @@ #define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). #define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. /// Persist time (task intervals) for flow vs. motor speed error condition. -static const U32 BP_FLOW_VS_SPEED_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_FLOW_VS_SPEED_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) for motor off error condition. -static const U32 BP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_OFF_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) motor speed error condition. -static const U32 BP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_MOTOR_SPEED_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) rotor speed error condition. -static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ( 12 * MS_PER_SECOND ); /// Persist time (task intervals) pump direction error condition. -static const U32 BP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); -/// Persist time (task intervals) blood pump rotor speed too fast error condition. -static const U32 BP_MAX_ROTOR_SPEED_ERROR_PERSIST = ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_DIRECTION_ERROR_PERSIST = ( 250 ); +/// Persist time period blood pump rotor speed too fast error condition. +static const U32 BP_MAX_ROTOR_SPEED_ERROR_PERSIST = ( 1 * MS_PER_SECOND ); #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped #define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running @@ -186,20 +186,11 @@ 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. -static U32 errorBloodMotorSpeedPersistTimerCtr = 0; ///< Persistence timer counter for motor speed error condition. -static U32 errorBloodRotorSpeedPersistTimerCtr = 0; ///< Persistence timer counter for rotor speed error condition. -static U32 errorBloodPumpDirectionPersistTimerCtr = 0; ///< Persistence timer counter for pump direction error condition. -static U32 errorBloodPumpRotorTooFastPersistTimerCtr = 0; ///< Persistence timer counter for pump rotor too fast error condition. - static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< Holds flow samples for a rolling average. static U32 flowReadingsIdx = 0; ///< Index for next sample in rolling average array. static F32 flowReadingsTotal = 0.0; ///< Rolling total - used to calc average. static U32 flowReadingsCount = 0; ///< Number of samples in flow rolling average buffer. -static U32 bpCurrErrorDurationCtr = 0; ///< Used for tracking persistence of bp current errors. - static U08 lastBloodFlowFastPacketReadCtr = 0; ///< Previous read counter for the blood flow fast packets. static U08 lastBloodFlowSlowPacketReadCtr = 0; ///< Previous read counter for the blood flow slow packets. static U08 lastBloodPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. @@ -1045,17 +1036,10 @@ // TODO - alarm??? } - // Ensure rotor speed below maximum - if ( rotorSpeed > BP_MAX_ROTOR_SPEED_RPM ) - { - if ( ++errorBloodPumpRotorTooFastPersistTimerCtr >= BP_MAX_ROTOR_SPEED_ERROR_PERSIST ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, rotorSpeed ) - } - } - else + // Ensure rotor speed below maximum + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, rotorSpeed > BP_MAX_ROTOR_SPEED_RPM ) ) { - errorBloodPumpRotorTooFastPersistTimerCtr = 0; + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, rotorSpeed ) } // If pump is stopped or running very slowly, set rotor speed to zero @@ -1078,6 +1062,7 @@ if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) { MOTOR_DIR_T bpMCDir, bpDir; + BOOL isDirIncorrect; U08 dirErrorCnt = getFPGABloodPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; // Check pump direction error count @@ -1090,35 +1075,26 @@ bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); bpDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - // Check set direction vs. direction from hall sensors - if ( bloodPumpDirectionSet != bpDir ) - { - if ( ++errorBloodPumpDirectionPersistTimerCtr >= BP_DIRECTION_ERROR_PERSIST ) - { -#ifndef DISABLE_PUMP_DIRECTION_CHECKS - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpDir ) -#endif - } - } - // Check set direction vs. direction from sign of motor controller speed - else if ( bloodPumpDirectionSet != bpMCDir ) + // Check set direction vs. direction from hall sensors vs. direction from sign of motor controller speed + isDirIncorrect = ( bloodPumpDirectionSet != bpDir ) || ( bloodPumpDirectionSet != bpMCDir ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, isDirIncorrect ) ) { - if ( ++errorBloodPumpDirectionPersistTimerCtr >= BP_DIRECTION_ERROR_PERSIST ) - { #ifndef DISABLE_PUMP_DIRECTION_CHECKS + if ( bloodPumpDirectionSet != bpDir ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpDir ) + } + else + { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) -#endif } +#endif } - else - { - errorBloodPumpDirectionPersistTimerCtr = 0; - } } else { - errorBloodPumpDirectionPersistTimerCtr = 0; - } + resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK ); + } } /*********************************************************************//** @@ -1139,27 +1115,13 @@ S32 cmdRate = targetBloodFlowRate; // Check for pump running while commanded off - if ( 0 == cmdRate ) - { - if ( measMotorSpeed > BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) - { - if ( ++errorBloodMotorOffPersistTimerCtr >= BP_OFF_ERROR_PERSIST ) - { + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_OFF_CHECK, ( 0 == cmdRate ) && ( measMotorSpeed > BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) ) ) + { #ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); - activateSafetyShutdown(); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif - } - } - else - { - errorBloodMotorOffPersistTimerCtr = 0; - } } - else - { - errorBloodMotorOffPersistTimerCtr = 0; - } if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) { @@ -1169,41 +1131,27 @@ F32 measMotorSpeedInRotorRPM = measMotorSpeed / BP_GEAR_RATIO; F32 deltaRotorSpeed = fabs( measRotorSpeed - measMotorSpeedInRotorRPM ); - // Check measured motor speed vs. commanded motor speed while controlling to target - if ( deltaMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) - { - if ( ++errorBloodMotorSpeedPersistTimerCtr >= BP_MOTOR_SPEED_ERROR_PERSIST ) - { -#ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, (F32)cmdRate, measMotorSpeed ); + // Check measured motor speed vs. commanded motor speed while controlling to target + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, deltaMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, (F32)cmdRate, measMotorSpeed ); #endif - } } - else - { - errorBloodMotorSpeedPersistTimerCtr = 0; - } - // Check measured rotor speed vs. measured motor speed while controlling to target - if ( deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) - { - if ( ++errorBloodRotorSpeedPersistTimerCtr >= BP_ROTOR_SPEED_ERROR_PERSIST ) - { -#ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); + // Check measured rotor speed vs. measured motor speed while controlling to target + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); #endif - } } - else - { - errorBloodRotorSpeedPersistTimerCtr = 0; - } + } + else + { + resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK ); + resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK ); } - else - { - errorBloodMotorSpeedPersistTimerCtr = 0; - errorBloodRotorSpeedPersistTimerCtr = 0; - } } /*********************************************************************//** @@ -1212,38 +1160,31 @@ * against the implied flow of the measured pump speed when in treatment mode * and controlling to target flow. If a sufficient difference persists, a * flow vs. motor speed check error is triggered. - * @details Inputs: measuredBloodFlowRate, bloodPumpSpeedRPM, errorBloodFlowVsMotorSpeedPersistTimerCtr + * @details Inputs: measuredBloodFlowRate, bloodPumpSpeedRPM * @details Outputs: alarm may be triggered * @return none *************************************************************************/ static void checkBloodPumpFlowAgainstSpeed( void ) { - // Check only performed while in treatment mode and while we are in control to target state + // Check only performed while in treatment mode and while we are in control to target state if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) { F32 flow = getMeasuredBloodFlowRate(); F32 speed = getMeasuredBloodPumpSpeed(); F32 impliedSpeed = ( flow / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; F32 delta = fabs( speed - impliedSpeed ); - - if ( delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) - { - if ( ++errorBloodFlowVsMotorSpeedPersistTimerCtr >= BP_FLOW_VS_SPEED_PERSIST ) - { -#ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); -#endif - } + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); +#endif } - else - { - errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; - } + } + else + { + resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK ); } - else - { - errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; - } } /*********************************************************************//** @@ -1256,46 +1197,18 @@ *************************************************************************/ static void checkBloodPumpMCCurrent( void ) { - F32 bpCurr; - - // Blood pump should be off - if ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) - { - bpCurr = fabs( getMeasuredBloodPumpMCCurrent() ); - if ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ) - { - bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) - { -#ifndef DISABLE_MOTOR_CURRENT_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpMCCurrent() ); -#endif - } - } - else - { - bpCurrErrorDurationCtr = 0; - } + F32 const bpCurr = fabs( getMeasuredBloodPumpMCCurrent() ); + // Check blood pump current during off state + BOOL const isOffMCCurrentBad = ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ); + // Check blood pump current during running state + BOOL const isRunningMCCurrentBad = ( BLOOD_PUMP_OFF_STATE != bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, isOffMCCurrentBad || isRunningMCCurrentBad ) ) + { +#ifndef DISABLE_MOTOR_CURRENT_CHECKS + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, bpCurr ); +#endif } - // Blood pump should be running - else - { - bpCurr = fabs( getMeasuredBloodPumpMCCurrent() ); - if ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ) - { - bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) - { -#ifndef DISABLE_MOTOR_CURRENT_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpMCCurrent() ); -#endif - } - } - else - { - bpCurrErrorDurationCtr = 0; - } - } } /*********************************************************************//** @@ -1344,13 +1257,22 @@ // Retrieve blood flow sensor calibration data and check for sensor connected status if ( BFM_SENSOR_PARAM_CORRUPT_STATUS != bfmStatus ) { - bloodFlowCalGain = cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].gain; - bloodFlowCalOffset = cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].offset; - result = SELF_TEST_STATUS_PASSED; +#ifndef DISABLE_CAL_CHECK + if ( cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].calibrationTime == 0 ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BLOOD_FLOW_INVALID_CALIBRATION, cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].calibrationTime, + cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].crc ); + } + else +#endif + { + bloodFlowCalGain = cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].gain; + bloodFlowCalOffset = cal.hdFlowSensors[ CAL_DATA_HD_BLOOD_FLOW_SENSOR ].offset; + result = SELF_TEST_STATUS_PASSED; + } } else { - result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_FLOW_STATUS_SELF_TEST_FAILURE, (U32)bfmStatus ); } Index: firmware/App/HDCommon.h =================================================================== diff -u -r39dd0b7734331c784b8410f2bbd481e0f792892e -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 39dd0b7734331c784b8410f2bbd481e0f792892e) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -23,9 +23,9 @@ // ********** version ********** #define HD_VERSION_MAJOR 0 -#define HD_VERSION_MINOR 5 +#define HD_VERSION_MINOR 6 #define HD_VERSION_MICRO 0 -#define HD_VERSION_BUILD 9037 +#define HD_VERSION_BUILD 37 // ********** development build switches ********** @@ -47,15 +47,15 @@ // #define DISABLE_ACCELS 1 // Disable accelerometer POST and monitoring // #define DISABLE_CRC_ERROR 1 // Do not error on bad CRC for CAN messages // #define DISABLE_ACK_ERRORS 1 // Do not error on failure of other node(s) to ACK a message -// #define DISABLE_MOTOR_CURRENT_CHECKS 1 // Do not error on HD pump current checks -// #define DISABLE_PUMP_FLOW_CHECKS 1 // Do not error on HD pump flow checks -// #define DISABLE_PUMP_SPEED_CHECKS 1 // Do not error on HD pump speed checks -// #define DISABLE_PUMP_DIRECTION_CHECKS 1 // Do not error on HD pump direction checks + #define DISABLE_MOTOR_CURRENT_CHECKS 1 // Do not error on HD pump current checks + #define DISABLE_PUMP_FLOW_CHECKS 1 // Do not error on HD pump flow checks + #define DISABLE_PUMP_SPEED_CHECKS 1 // Do not error on HD pump speed checks + #define DISABLE_PUMP_DIRECTION_CHECKS 1 // Do not error on HD pump direction checks #define DISABLE_SYRINGE_PUMP 1 // Disable syringe pump functionality #define ALWAYS_ALLOW_SYRINGE_PUMP_CMDS 1 // Allow syringe pump commands at any time except when pump is busy #define DISABLE_PRESSURE_CHECKS 1 // Do not error on HD pressure checks -// #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks -// #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position + #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks + #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position #define DISABLE_CAL_CHECK 1 // Disable calibration checks // #define RUN_PUMPS_OPEN_LOOP 1 // BP and DPi pumps will be run open loop (no flow sensor feedback) // #define RAW_FLOW_SENSOR_DATA 1 // Test build will not filter flow sensor data @@ -64,23 +64,23 @@ #define ALARMS_DEBUG 1 // Triggered alarms sent to debug UART #define ALARM_VOLUME_DEFAULT_LOW 1 // Set default alarm volume to lowest // #define TEMP_UI_ALARM_SILENCE_FIX 1 // Temporary UI fix for handling alarm silence request msg - #define SKIP_PRIMING 1 // Skip Pre-treatment Prime +// #define SKIP_PRIMING 1 // Skip Pre-treatment Prime #define SKIP_WET_SELF_TESTS 1 // Skip Pre-treatment prime wet self-tests // #define V2_0_SYSTEM 1 // Build for v2.0 system - #define SKIP_SAMPLE_WATER 1 // Skip pre-treatment sample water +// #define SKIP_SAMPLE_WATER 1 // Skip pre-treatment sample water #define SKIP_CONSUMABLE_TESTS 1 // Skip pre-treatment consumable Self-tests #define SKIP_DRY_SELF_TESTS 1 // Skip pre-treatment dry self-tests - #define SKIP_UI_INTERACTION 1 // Skip UI interaction. -// #define DISABLE_BATT_COMM 1 // Disable battery communication. +// #define SKIP_UI_INTERACTION 1 // Skip UI interaction. + #define DISABLE_BATT_COMM 1 // Disable battery communication. #define SKIP_AIR_BUBBLE_CHECK 1 // Skip air bubble detector self-test. #define DISABLE_OCCLUSION_SELF_TEST 1 // Skip occlusion sensor self-test. -// #define SKIP_CARTRIDGE_REMOVAL 1 // Skip cartridge removal check + #define SKIP_CARTRIDGE_REMOVAL 1 // Skip cartridge removal check #define SKIP_EMPTY_RES_CHECK 1 // Skip reservoir empty check -// #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters -// #define DISABLE_VOLTAGE_MONITOR 1 // Disable voltage monitoring/alarms + #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters + #define DISABLE_VOLTAGE_MONITOR 1 // Disable voltage monitoring/alarms #define ALLOW_1_MIN_TREATMENT_DURATION 1 // Allow user to change treatment duration to as low as 1 minute #define DISABLE_SYRINGE_PUMP_ALARMS 1 // Disable some syringe pump alarms that are triggering intermittently -// #define NO_PUMP_FLOW_LIMITS 1 // Allow any commanded flow rate for peristaltic pumps + #define NO_PUMP_FLOW_LIMITS 1 // Allow any commanded flow rate for peristaltic pumps #define DISABLE_BUBBLE_ALARMS 1 // Disable bubble alarms #include Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r39dd0b7734331c784b8410f2bbd481e0f792892e -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 39dd0b7734331c784b8410f2bbd481e0f792892e) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -23,6 +23,7 @@ #include "CPLD.h" #include "DialInFlow.h" #include "FPGA.h" +#include "Integrity.h" #include "ModeInitPOST.h" #include "NVDataMgmt.h" #include "OperationModes.h" @@ -131,7 +132,8 @@ break; case POST_STATE_FW_INTEGRITY: - postState = POST_STATE_WATCHDOG; + testStatus = execIntegrityTest(); + postState = handlePOSTStatus( testStatus ); break; case POST_STATE_WATCHDOG: @@ -165,8 +167,9 @@ break; case POST_STATE_ALARM_AUDIO: - testStatus = execAlarmAudioSelfTest(); - postState = handlePOSTStatus( testStatus ); +// testStatus = execAlarmAudioSelfTest(); +// postState = handlePOSTStatus( testStatus ); + postState = POST_STATE_ALARM_LAMP; break; case POST_STATE_ALARM_LAMP: @@ -228,7 +231,6 @@ // Should not get here - any failed post test should have already triggered a fault and taken us to fault mode default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_INIT_POST_INVALID_POST_STATE, postState ) - postState = POST_STATE_FAILED; break; } Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -re08cad8c94bec5dd7133fce8606bb4e88151ae28 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision e08cad8c94bec5dd7133fce8606bb4e88151ae28) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -22,6 +22,7 @@ #include "ModePreTreat.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "PresOccl.h" #include "PreTreatmentRecirc.h" #include "Prime.h" #include "SelfTests.h" @@ -659,6 +660,7 @@ { if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) { + setOcclusionInstallLevels(); // Record occlusion pressure levels after a new cartridge is installed. submodeCompleteTransitionTimeCounter = 0; state = HD_PRE_TREATMENT_PRIME_STATE; transitionToPrime(); Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r44a100f8e5210a02c23b8fcc4527d8e96d577381 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 44a100f8e5210a02c23b8fcc4527d8e96d577381) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -60,8 +60,9 @@ #define CLR_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 &= ~BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to disable backup alarm audio. #define ALARM_AUDIO_TEST_TONE 4 ///< Alarm audio state for continuous test tone. -#define ALARM_AUDIO_CURRENT_HG_MIN_MA 10.0 ///< Minimum audio current (high gain) during test tone self-test (in mA). -#define ALARM_AUDIO_CURRENT_LG_MIN_MA 10.0 ///< Minimum audio current (low gain) during test tone self-test (in mA). +#define ALARM_AUDIO_CURRENT_HG_MIN_MA 20.0 ///< Minimum audio current (high gain) during test tone self-test (in mA). // TODO - Why is HG so low? S/B same as LG I think. +#define ALARM_AUDIO_CURRENT_LG_MIN_MA 200.0 ///< Minimum audio current (low gain) during test tone self-test (in mA). +#define ALARM_AUDIO_MAX_TEST_TIME_MS 1000 ///< Maximum time for audio current to reach threshold in test. /// Alarm priority ranking record. typedef struct @@ -71,6 +72,15 @@ U32 timeSinceTriggeredMS; ///< Time (in ms) since this alarm was triggered } ALARM_PRIORITY_RANKS_T; +/// Enumeration of alarm audio self-test states. +typedef enum Alarm_Lamp_Self_Test_States +{ + ALARM_AUDIO_SELF_TEST_STATE_START = 0, ///< Start state of alarm lamp self-test. + ALARM_AUDIO_SELF_TEST_STATE_PRIMARY, ///< Red state of alarm lamp self-test. + ALARM_AUDIO_SELF_TEST_STATE_COMPLETE, ///< Completed state of alarm lamp self-test. + NUM_OF_ALARM_AUDIO_SELF_TEST_STATES ///< Number of states in alarm lamp self-test. +} ALARM_AUDIO_SELF_TEST_STATE_T; + // ********** private data ********** static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm @@ -99,6 +109,8 @@ static BOOL alarmUserRecoveryActionEnabled[ NUMBER_OF_ALARM_USER_ACTIONS ]; ///< Alarm user recovery actions enabled flags. +/// Current state of the alarm audio self tests. +static ALARM_AUDIO_SELF_TEST_STATE_T alarmAudioSelfTestState; /// Flag indicates whether alarm audio test tone should be output. static BOOL alarmAudioTestToneRequested; @@ -173,7 +185,8 @@ alarmStatus.noDialRecirc = FALSE; alarmStatus.usrACKRequired = FALSE; - alarmAudioTestToneRequested = FALSE; + alarmAudioTestToneRequested = FALSE; + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } /*********************************************************************//** @@ -700,7 +713,7 @@ alarmPrimaryAudioCurrentHG.data = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_HG ); alarmPrimaryAudioCurrentLG.data = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); - alarmBackupAudioCurrent.data = getIntADCVoltageConverted( INT_ADC_BACKUP_ALARM_CURRENT ); + alarmBackupAudioCurrent.data = getFPGABackupAlarmAudioCurrent(); // TODO - Check current vs. expected audio output @@ -847,15 +860,23 @@ { U32 volume = getAlarmAudioVolume(); + // If we're not in Init-POST mode, ensure audio test tone request is cancelled. + if ( getCurrentOperationMode() != MODE_INIT ) + { + alarmAudioTestToneRequested = FALSE; + } + + // If audio test in progress, play test tone. if ( TRUE == alarmAudioTestToneRequested ) - { // Play test tone at max volume for next 50 ms + { // Play test tone at max volume setAlarmAudioState( ALARM_AUDIO_TEST_TONE, 0 ); - alarmAudioTestToneRequested = FALSE; } + // If alarm silenced, play no alarm audio. else if ( TRUE == alarmStatus.alarmsSilenced ) { setAlarmAudioState( ALARM_PRIORITY_NONE, volume ); } + // Otherwise, play alarm audio as appropriate based on current alarm status else { if ( alarmStatus.alarmsState < NUM_OF_ALARM_PRIORITIES ) @@ -1238,36 +1259,55 @@ * The execAlarmAudioSelfTest function outputs a test audio tone and * measures the audio current level. The test passes if the audio current * exceeds TBD mA. - * @details Inputs: alarmBackupAudioCurrent + * @details Inputs: alarmAudioSelfTestState * @details Outputs: none * @return the current backup alarm audio current (in mA). *************************************************************************/ SELF_TEST_STATUS_T execAlarmAudioSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + static U32 testStartTime; - if ( alarmAudioTestToneRequested != TRUE ) + switch ( alarmAudioSelfTestState ) { - alarmAudioTestToneRequested = TRUE; - setAlarmAudio(); - } - else - { - F32 almHGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_HG ); - F32 almLGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); + case ALARM_AUDIO_SELF_TEST_STATE_START: + testStartTime = getMSTimerCount(); + // Start test tone + alarmAudioTestToneRequested = TRUE; + setAlarmAudio(); + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_PRIMARY; + break; - // Check if alarm audio current is sufficiently high indicating alarm tone is being output -// TODO - need tone to be on longer than 50ms. make duration long (1 sec) at first to characterize the audio, then change to exit test when threshold met or t/o -// if ( ( almHGCurrent > ALARM_AUDIO_CURRENT_HG_MIN_MA ) && -// ( almLGCurrent > ALARM_AUDIO_CURRENT_LG_MIN_MA ) ) - { - result = SELF_TEST_STATUS_PASSED; - } -// else -// { -// result = SELF_TEST_STATUS_FAILED; -// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ALARM_AUDIO_SELF_TEST_FAILURE, almHGCurrent, almLGCurrent ); -// } + case ALARM_AUDIO_SELF_TEST_STATE_PRIMARY: + { + F32 almHGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_HG ); + F32 almLGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); + + // Check if alarm audio current is sufficiently high indicating alarm tone is being output + if ( ( almHGCurrent > ALARM_AUDIO_CURRENT_HG_MIN_MA ) && + ( almLGCurrent > ALARM_AUDIO_CURRENT_LG_MIN_MA ) ) + { + alarmAudioTestToneRequested = FALSE; + result = SELF_TEST_STATUS_PASSED; + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; + } + else if ( TRUE == didTimeout( testStartTime, ALARM_AUDIO_MAX_TEST_TIME_MS ) ) + { + alarmAudioTestToneRequested = FALSE; + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ALARM_AUDIO_SELF_TEST_FAILURE, almHGCurrent, almLGCurrent ); + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; + } + } + break; + + case ALARM_AUDIO_SELF_TEST_STATE_COMPLETE: + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; // Should only get here if re-starting self-tests. + break; + + default: + // TODO - s/w fault + break; } return result; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r44a100f8e5210a02c23b8fcc4527d8e96d577381 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 44a100f8e5210a02c23b8fcc4527d8e96d577381) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -100,6 +100,8 @@ #define FPGA_ALARM_AUDIO_VOLUME_SHIFT 3 ///< Shift alarm audio volume 3 bits to left before writing to register. +#define FPGA_BACKUP_ALARM_AUDIO_CONVERT 0.4 ///< Converts backup (piezo) alarm audio ADC volts to amps. + // FPGA Sensors Record #pragma pack(push,1) /// Record structure for FPGA header read. @@ -177,13 +179,13 @@ S16 VBVPosition; ///< Reg 360. Encoder position from VBV pinch valve. 0 until PID interface is enabled. S16 VDiPosition; ///< Reg 362. Encoder position from VDi pinch valve. 0 until PID interface is enabled. S16 VDoPosition; ///< Reg 364. Encoder position from VDo pinch valve. 0 until PID interface is enabled. - S16 VSparePosition; ///< Reg 366. Encoder position from VSpare pinch valve. 0 until PID interface is enabled. + S16 fpgaIntVoltage; ///< Reg 366. Internal FPGA Vcc voltage. 3V range over 12 bits (0..4095). U16 valveStatus; ///< Reg 368. Valve status register. U16 VBAPWMTarget; ///< Reg 370. PWM target duty cycle for VBA pinch valve. U16 VBVPWMTarget; ///< Reg 372. PWM target duty cycle for VBV pinch valve. 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 VSparePWMTarget; ///< Reg 378. Internal FPGA Vcc Aux voltage. U08 syringePumpStatus; ///< Reg 380. Syringe pump status register. U08 syringePumpADCReadCounter; ///< Reg 381. Syringe pump ADC read counter. U08 syringePumpADCandDACStatus; ///< Reg 382. Syringe pump ADC and DAC status register. @@ -204,6 +206,7 @@ U16 VSpareSpeed; ///< Reg 412. VSpare speed (Register VAUX5) U16 VSpareCurrent; ///< Reg 414. VSpare current (Register VAUX13) U16 fpgaTimerCount_ms; ///< Reg 416. Internal FPGA timer count in ms. + U16 backupAlarmAudioPeakCurrent; ///< Reg 418. Piezo alarm peak ADC current in previous 10ms. 12 bit unsigned. } FPGA_SENSORS_T; /// Record structure for FPGA continuous priority writes. @@ -1824,6 +1827,22 @@ /*********************************************************************//** * @brief + * The getFPGABackupAlarmAudioCurrent function gets the latest piezo alarm + * audio current reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return Latest piezo alarm audio current reading + *************************************************************************/ +F32 getFPGABackupAlarmAudioCurrent( void ) +{ + U16 adcCnts = fpgaSensorReadings.backupAlarmAudioPeakCurrent; + F32 result = ( ( (F32)adcCnts / (F32)BITS_12_FULL_SCALE ) * FPGA_BACKUP_ALARM_AUDIO_CONVERT ) * (F32)MA_PER_AMP; + + return result; +} + +/*********************************************************************//** + * @brief * The getFPGAAirTrapLevels function gets the latest air trap level sensor * readings. * @details Inputs: fpgaSensorReadings Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r44a100f8e5210a02c23b8fcc4527d8e96d577381 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 44a100f8e5210a02c23b8fcc4527d8e96d577381) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -112,6 +112,8 @@ void getFPGAAccelMaxes( S16 *xm, S16*ym, S16*zm ); void getFPGAAccelStatus( U16 *cnt, U16 *accelFPGAFaultReg ); +F32 getFPGABackupAlarmAudioCurrent( void ); + void getFPGAAirTrapLevels( BOOL *airAtLower, BOOL *airAtUpper ); void setFPGASensorTest( U08 sensorTest ); Index: firmware/App/Services/Interrupts.c =================================================================== diff -u -r9feea867113c62088f0ce91750127972dbd9bf53 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 9feea867113c62088f0ce91750127972dbd9bf53) +++ firmware/App/Services/Interrupts.c (.../Interrupts.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -34,9 +34,6 @@ #include "TaskPriority.h" #include "TaskTimer.h" #include "Utilities.h" -#ifdef DEBUG_ENABLED - #include "SystemCommMessages.h" -#endif /** * @addtogroup Interrupts @@ -57,7 +54,6 @@ static U32 sci2FrameErrorCnt = 0; ///< FPGA serial frame error counter. static U32 sci2OverrunErrorCnt = 0; ///< FPGA serial overrun error counter. -static U32 can1PassiveCnt = 0; ///< CAN passive mode counter. static U32 can1WarningCnt = 0; ///< CAN warning mode counter. static U32 can1BusOffCnt = 0; ///< CAN buss off mode counter. static U32 can1ParityCnt = 0; ///< CAN parity error counter. @@ -74,7 +70,6 @@ void initInterrupts( void ) { // Initialize various time windowed counts for monitoring CAN & UART errors and warnings - initTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_PASSIVE, MAX_COMM_ERRORS, COMM_ERROR_TIME_WINDOW_MS ); initTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_OFF, MAX_COMM_ERRORS, COMM_ERROR_TIME_WINDOW_MS ); initTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_PARITY, MAX_COMM_ERRORS, COMM_ERROR_TIME_WINDOW_MS ); initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_UART_FRAME_ERROR, MAX_COMM_ERRORS, COMM_ERROR_TIME_WINDOW_MS ); @@ -91,15 +86,6 @@ void phantomInterrupt(void) { // TODO - what to do with phantom interrupts? -#ifdef DEBUG_ENABLED - { - char debugStr[ 256 ]; - - sprintf( debugStr, "HD-phantom interrupt\n" ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); - sendDebugDataToUI( (U08*)debugStr ); - } -#endif } /*********************************************************************//** @@ -168,38 +154,33 @@ void canErrorNotification(canBASE_t *node, uint32 notification) { if ( node == canREG1 ) - { + { + // Parity error - message RAM is corrupted if ( notification & canLEVEL_PARITY_ERR ) { can1ParityCnt++; if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_PARITY ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_CAN_PARITY_ERROR ) } - } + } + // Bus off - our transmitter has counted 255+ errors else if ( notification & canLEVEL_BUS_OFF ) { can1BusOffCnt++; if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_OFF ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_CAN_OFF_ERROR ) } - } + } + // Warning - our transmitter has counted 96+ errors else if ( notification & canLEVEL_WARNING ) { can1WarningCnt++; } - else if ( notification & canLEVEL_PASSIVE ) - { - can1PassiveCnt++; - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_CAN_PASSIVE ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_CAN_PASSIVE_WARNING ) - } - } else { - // Ignore - other notifications undefined + // Ignore - other notifications - unhandled } } } Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r421ffbd3887d136b66da26ee3eeb17dcd9a773b8 -r765a17e8b525704386d48df1431688b07b785b40 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 421ffbd3887d136b66da26ee3eeb17dcd9a773b8) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 765a17e8b525704386d48df1431688b07b785b40) @@ -394,8 +394,8 @@ } else { - // Should not get here - not an active message box - // TODO - s/w fault? + // Should not get here - not an active message box + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_BOX, srcCANBox ) } } @@ -997,8 +997,6 @@ } } - // TODO - if no open slot found, s/w fault - return result; } @@ -1060,8 +1058,8 @@ { U16 msgID; - memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); + memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); pendingAckList[ i ].used = FALSE; // Take pending message off of list } } @@ -1267,6 +1265,10 @@ handleUIPOSTFinalResult( message ); break; + case MSG_ID_UI_ACTIVE_ALARMS_LIST_REQUEST: + handleUIActiveAlarmsListRequest( message ); + break; + case MSG_ID_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); break; @@ -1511,14 +1513,14 @@ handleSetFluidLeakStateOverrideRequest( message ); break; - case MSG_ID_HD_BLOOD_LEAK_DATA_SEND_INTERVAL_OVERRIDE: - handleSetBloodLeakDataBroadcastIntervalOverrideRequest( message ); - break; - case MSG_ID_HD_BLOOD_LEAK_STATUS_OVERRIDE: handleSetBloodLeakStatusOverrideRequest( message ); break; + case MSG_ID_HD_BLOOD_LEAK_DATA_SEND_INTERVAL_OVERRIDE: + handleSetBloodLeakDataBroadcastIntervalOverrideRequest( message ); + break; + case MSG_ID_HD_BLOOD_LEAK_ZERO_REQUEST: handleBloodLeakZeroRequest( message ); break; @@ -1619,6 +1621,14 @@ handleTestSyringePumpADCReadCtrOverrideRequest( message ); break; + case MSG_ID_HD_VALVES_CURRENT_OVERRIDE: + handleTestValvesCurrentOverrideRequest( message ); + break; + + case MSD_ID_HD_VALVES_POSITION_COUNT_OVERRIDE: + handleTestValvesPositionCountOverrideRequest( message ); + break; + case MSG_ID_HD_SET_CALIBRATION_RECORD: handleSetHDCalibrationRecord( message ); break;