Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -rabbad386f4cc94f315300dffef321fe8c03fbd52 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision abbad386f4cc94f315300dffef321fe8c03fbd52) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -49,10 +49,11 @@ #define MAX_BLOOD_PUMP_PWM_DUTY_CYCLE 0.89 ///< Controller will error if PWM duty cycle > 90%, so set max to 89% #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.10 ///< Controller will error if PWM duty cycle < 10%, so set min to 10% +#define BP_CONTROL_INTERVAL_SEC 10 ///< Blood pump control interval (in seconds). /// Interval (ms/task time) at which the blood pump is controlled. -static const U32 BP_CONTROL_INTERVAL = ( 10000 / TASK_GENERAL_INTERVAL ); -#define BP_P_COEFFICIENT 0.00035 ///< P term for blood pump control -#define BP_I_COEFFICIENT 0.00035 ///< I term for blood pump control +static const U32 BP_CONTROL_INTERVAL = ( BP_CONTROL_INTERVAL_SEC * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +#define BP_P_COEFFICIENT 0.0001 ///< P term for blood pump control +#define BP_I_COEFFICIENT 0.00075 ///< I term for blood pump control #define BP_HOME_RATE 100 ///< Target pump speed (in estimate mL/min) for homing. #define BP_HOME_TIMEOUT_MS 10000 ///< Maximum time allowed for homing to complete (in ms). @@ -85,7 +86,7 @@ #ifndef V2_0_SYSTEM #define BP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for blood pump motor - #define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00025 ///< ~40 BP motor RPM = 1% PWM duty cycle + #define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000238 ///< ~42 BP motor RPM = 1% PWM duty cycle #else #define BP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< Conversion factor from ADC counts to RPM for blood pump motor #define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.0003125 ///< ~32 BP motor RPM = 1% PWM duty cycle @@ -107,7 +108,7 @@ #define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) /// Blood flow sensor signal strength low alarm persistence. -#define FLOW_SIG_STRGTH_ALARM_PERSIST ( 5 * MS_PER_SECOND ) +#define FLOW_SIG_STRGTH_ALARM_PERSIST ( BP_CONTROL_INTERVAL_SEC * MS_PER_SECOND ) #define MIN_FLOW_SIG_STRENGTH 0.9 ///< Minimum flow sensor signal strength (90%). /// Blood flow fast read timeout alarm persistence. @@ -247,15 +248,15 @@ BP_P_COEFFICIENT, BP_I_COEFFICIENT, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); - // Initialize persistent alarm for flow sensor + // Initialize persistent alarm for flow sensor signal strength too low initPersistentAlarm( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, 0, BP_FLOW_VS_SPEED_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_OFF_CHECK, 0, BP_OFF_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, 0, BP_MOTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, 0, BP_ROTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, 0, BP_DIRECTION_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, 0, BP_MAX_ROTOR_SPEED_ERROR_PERSIST ); - initPersistentAlarm( ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, 0, FLOW_SIG_STRGTH_ALARM_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, 0, BP_MAX_CURR_ERROR_DURATION_MS ); + initPersistentAlarm( ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, FLOW_SIG_STRGTH_ALARM_PERSIST, FLOW_SIG_STRGTH_ALARM_PERSIST ); initPersistentAlarm( ALARM_ID_HD_BP_FLOW_READ_TIMEOUT_ERROR, 0, BLOOD_FLOW_FAST_READ_TO_PERSIST ); initPersistentAlarm( ALARM_ID_HD_BP_FLOW_SLOW_READ_TIMEOUT_ERROR, 0, BLOOD_FLOW_SLOW_READ_TO_PERSIST ); initPersistentAlarm( ALARM_ID_HD_BP_FLOW_SENSOR_ERROR, 0, BLOOD_FLOW_COMM_ERROR_PERSIST ); @@ -279,8 +280,10 @@ // Direction change while pump is running is not allowed if ( ( FALSE == isBloodPumpOn ) || ( 0 == flowRate ) || ( dir == bloodPumpDirectionSet ) ) { +#ifndef NO_PUMP_FLOW_LIMITS // Verify flow rate - if ( flowRate <= MAX_BLOOD_FLOW_RATE ) + if ( flowRate <= MAX_BLOOD_FLOW_RATE ) +#endif { resetBloodFlowMovingAverage(); targetBloodFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); @@ -319,10 +322,12 @@ } result = TRUE; } +#ifndef NO_PUMP_FLOW_LIMITS else // Requested flow rate too high { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, flowRate ) - } + } +#endif } return result; @@ -608,14 +613,11 @@ else if ( bloodPumpPWMDutyCyclePctSet >= bloodPumpPWMDutyCyclePct ) { resetBloodFlowMovingAverage(); + bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); bloodPumpControlModeSet = bloodPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state - if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) - { - bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; - setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); - } + setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); + bpControlTimerCounter = 0; result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp up @@ -650,14 +652,11 @@ else if ( bloodPumpPWMDutyCyclePctSet <= bloodPumpPWMDutyCyclePct ) { resetBloodFlowMovingAverage(); + bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, bloodPumpPWMDutyCyclePctSet ); bloodPumpControlModeSet = bloodPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state - if ( bloodPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) - { - bloodPumpPWMDutyCyclePctSet = bloodPumpPWMDutyCyclePct; - setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); - } + setBloodPumpControlSignalPWM( bloodPumpPWMDutyCyclePct ); + bpControlTimerCounter = 0; result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp down @@ -1079,7 +1078,9 @@ if ( lastBloodPumpDirectionCount != dirErrorCnt ) { lastBloodPumpDirectionCount = dirErrorCnt; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_BLOOD_PUMP ) +#endif } bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); @@ -1334,6 +1335,7 @@ * TEST SUPPORT FUNCTIONS *************************************************************************/ + /*********************************************************************//** * @brief * The testSetBloodFlowDataPublishIntervalOverride function overrides the Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -rabbad386f4cc94f315300dffef321fe8c03fbd52 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision abbad386f4cc94f315300dffef321fe8c03fbd52) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -42,17 +42,18 @@ // ********** private definitions ********** /// Interval (ms/task time) at which the dialIn flow data is published on the CAN bus. -#define DIAL_IN_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) +#define DIAL_IN_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -#define MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE 0.0133 ///< Max duty cycle change when ramping up ~ 200 mL/min/s. -#define MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE 0.02 ///< Max duty cycle change when ramping down ~ 300 mL/min/s. -#define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.89 ///< Controller will error if PWM duty cycle > 90%, so set max to 89%. -#define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.10 ///< Controller will error if PWM duty cycle < 10%, so set min to 10%. +#define MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE 0.0133 ///< Max duty cycle change when ramping up ~ 200 mL/min/s. +#define MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE 0.02 ///< Max duty cycle change when ramping down ~ 300 mL/min/s. +#define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.89 ///< Controller will error if PWM duty cycle > 90%, so set max to 89%. +#define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.10 ///< Controller will error if PWM duty cycle < 10%, so set min to 10%. +#define DIP_CONTROL_INTERVAL_SEC 10 ///< Dialysate inlet pump control interval (in seconds). /// Interval (ms/task time) at which the dialIn pump is controlled. -static const U32 DIP_CONTROL_INTERVAL = ( 10000 / TASK_GENERAL_INTERVAL ); -#define DIP_P_COEFFICIENT 0.00035 ///< P term for dialIn pump control. -#define DIP_I_COEFFICIENT 0.00035 ///< I term for dialIn pump control. +static const U32 DIP_CONTROL_INTERVAL = ( DIP_CONTROL_INTERVAL_SEC * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +#define DIP_P_COEFFICIENT 0.0001 ///< P term for dialIn pump control. +#define DIP_I_COEFFICIENT 0.00075 ///< I term for dialIn pump control. #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). @@ -85,9 +86,9 @@ #ifndef V2_0_SYSTEM #define DIP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for dialIn pump motor. - #define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00025 ///< ~40 BP motor RPM = 1% PWM duty cycle + #define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000193 ///< ~52 BP motor RPM = 1% PWM duty cycle #else - #define DIP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< Conversion factor from ADC counts to RPM for blood pump motor + #define DIP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< Conversion factor from ADC counts to RPM for dialIn pump motor #define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.0003125 ///< ~32 BP motor RPM = 1% PWM duty cycle #endif #define DIP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for dialIn pump motor. @@ -106,7 +107,7 @@ #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_IN_PUMP_ADC_ZERO ) /// Measured dialIn flow is filtered w/ moving average. -#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) +#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * DIP_CONTROL_INTERVAL_SEC ) /// Dialysate flow sensor signal strength low alarm persistence. #define FLOW_SIG_STRGTH_ALARM_PERSIST ( 5 * MS_PER_SECOND ) @@ -280,8 +281,10 @@ // Direction change while pump is running is not allowed if ( ( FALSE == isDialInPumpOn ) || ( 0 == flowRate ) || ( dir == dialInPumpDirectionSet ) ) { +#ifndef NO_PUMP_FLOW_LIMITS // Verify flow rate - if ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) + if ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) +#endif { resetDialInFlowMovingAverage(); targetDialInFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); @@ -320,10 +323,12 @@ } result = TRUE; } +#ifndef NO_PUMP_FLOW_LIMITS else // Requested flow rate too high { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_IN_FLOW_SET_TOO_HIGH, flowRate ) - } + } +#endif } return result; @@ -579,14 +584,11 @@ else if ( dialInPumpPWMDutyCyclePctSet >= dialInPumpPWMDutyCyclePct ) { resetDialInFlowMovingAverage(); + dialInPumpPWMDutyCyclePctSet = dialInPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_DIALYSATE_FLOW, dialInPumpPWMDutyCyclePctSet ); dialInPumpControlModeSet = dialInPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state - if ( dialInPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) - { - dialInPumpPWMDutyCyclePctSet = dialInPumpPWMDutyCyclePct; - setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePct ); - } + setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePct ); + dipControlTimerCounter = 0; result = DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp up @@ -621,14 +623,11 @@ else if ( dialInPumpPWMDutyCyclePctSet <= dialInPumpPWMDutyCyclePct ) { resetDialInFlowMovingAverage(); + dialInPumpPWMDutyCyclePctSet = dialInPumpPWMDutyCyclePct; resetPIController( PI_CONTROLLER_ID_DIALYSATE_FLOW, dialInPumpPWMDutyCyclePctSet ); dialInPumpControlModeSet = dialInPumpControlMode; - // If open loop mode, set PWM to requested duty cycle where it will stay during control state - if ( dialInPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) - { - dialInPumpPWMDutyCyclePctSet = dialInPumpPWMDutyCyclePct; - setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePct ); - } + setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePct ); + dipControlTimerCounter = 0; result = DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE; } // Continue ramp down @@ -939,6 +938,19 @@ } return result; +} + +/*********************************************************************//** + * @brief + * The getDialInPumpPWMDutyCyclePct function gets the current dialIn pump + * PWM duty cycle percentage. + * @details Inputs: dialInPumpPWMDutyCyclePctSet + * @details Outputs: none + * @return the current dialIn pump PWM duty cycle percentage (0..1). + *************************************************************************/ +F32 getDialInPumpPWMDutyCyclePct( void ) +{ + return dialInPumpPWMDutyCyclePctSet; } /*********************************************************************//** @@ -1095,7 +1107,9 @@ if ( lastDialInPumpDirectionCount != dirErrorCnt ) { lastDialInPumpDirectionCount = dirErrorCnt; +#ifndef DISABLE_PUMP_DIRECTION_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_DIALYSATE_INLET_PUMP ) +#endif } dipMCDir = ( getMeasuredDialInPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); Index: firmware/App/Controllers/DialInFlow.h =================================================================== diff -u -r60e0fc291e3897ab9b86aee7181eeb6d6dd7d35f -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 60e0fc291e3897ab9b86aee7181eeb6d6dd7d35f) +++ firmware/App/Controllers/DialInFlow.h (.../DialInFlow.h) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -71,8 +71,6 @@ F32 getMeasuredDialInPumpMCCurrent( void ); F32 getDialInPumpPWMDutyCyclePct( void ); -BOOL setDialInFlowCalibration( F32 gain, F32 offset ); -void getDialInFlowCalibration( F32 *gain, F32 *offset ); BOOL testSetDialInFlowDataPublishIntervalOverride( U32 value ); BOOL testResetDialInFlowDataPublishIntervalOverride( void ); BOOL testSetTargetDialInFlowRateOverride( S32 value, U32 ctrlMode ); Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r8e08352e9e7d8749d8f093c6bc57e6dbc32605d5 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 8e08352e9e7d8749d8f093c6bc57e6dbc32605d5) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -14,10 +14,12 @@ * @date (original) 02-Mar-2021 * ***************************************************************************/ +#include #include "AlarmMgmt.h" #include "FPGA.h" -#include "ModeTreatmentParams.h" +#include "ModeTreatmentParams.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SafetyShutdown.h" @@ -216,6 +218,7 @@ static U32 syringePumpStallCtr; ///< Counts time when position is not changing during ramp. static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. +static HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T forceSensorCalRecord; ///< HD heparin force sensor calibration record. // ********** private function prototypes ********** @@ -251,6 +254,7 @@ static BOOL checkVolumeVsSafetyVolume( BOOL stopPump, F32 pctMargin ); static BOOL checkForStall( BOOL stopPump ); static void publishSyringePumpData( void ); +static BOOL processCalibrationData( void ); /*********************************************************************//** * @brief @@ -946,6 +950,20 @@ *************************************************************************/ static void execSyringePumpMonitor( void ) { + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + } + + F32 forceSensorBeforCal = ( (F32)getFPGASyringePumpADCChannel0() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; + syringePumpMeasForce.data = pow(forceSensorBeforCal, 4) * forceSensorCalRecord.hdHeparinForceSensor.fourthOrderCoeff + + pow(forceSensorBeforCal, 3) * forceSensorCalRecord.hdHeparinForceSensor.thirdOrderCoeff + + pow(forceSensorBeforCal, 2) * forceSensorCalRecord.hdHeparinForceSensor.secondOrderCoeff + + forceSensorBeforCal * forceSensorCalRecord.hdHeparinForceSensor.gain + + forceSensorCalRecord.hdHeparinForceSensor.offset; + S32 encPosition = getFPGASyringePumpEncoderPosition(); // Get latest FPGA status @@ -957,7 +975,7 @@ // Get latest ADC data and convert to V syringePumpMeasHome.data = ( (F32)getFPGASyringePumpADCChannel2() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; - syringePumpMeasForce.data = ( (F32)getFPGASyringePumpADCChannel0() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; + // Apply home offset to encoder position syringePumpLastPosition = getSyringePumpPosition(); syringePumpPosition.data = encPosition - syringePumpHomePositionOffset; @@ -1059,6 +1077,33 @@ // Publish syringe pump data on interval publishSyringePumpData(); +} + +/*********************************************************************//** + * @brief + * The execSyringePumpSelfTest function executes the state machine for the + * syringe pump self-test. + * @details Inputs: none + * @details Outputs: none + * @return the current state of the BloodFlow self-test. + *************************************************************************/ +SELF_TEST_STATUS_T execSyringePumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + BOOL calStatus = processCalibrationData(); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_SELF_TEST_FAILURE ); + } + + return result; } /*********************************************************************//** @@ -1813,6 +1858,43 @@ broadcastHeparinData( data.syringePumpVolumeDelivered ); syringePumpDataPublicationTimerCounter = 0; } +} + +/*********************************************************************//** + * @brief + * The processCalibrationData function gets the calibration data and makes + * sure it is valid by checking the calibration date. The calibration date + * should not be 0. + * @details Inputs: none + * @details Outputs: forceSensorCalRecord + * @return TRUE if the calibration record is valid, otherwise FALSE + *************************************************************************/ +static BOOL processCalibrationData( void ) +{ + BOOL status = TRUE; + + // Get the calibration record from NVDataMgmt + HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T calData = getHDHeparinForceSensorCalibrationRecord(); + + // Check if the calibration data that was received from NVDataMgmt is legitimate + // The calibration date item should not be zero. If the calibration date is 0, + // then the heparin force sensors data is not stored in the NV memory or it was corrupted. + if ( 0 == calData.hdHeparinForceSensor.calibrationTime ) + { +#ifndef SKIP_CAL_CHECK + activateAlarmNoData( ALARM_ID_HD_HEPARIN_FORCE_SENSOR_INVALID_CAL_RECORD ); + status = FALSE; +#endif + } + + // The calibration data was valid, update the local copy + forceSensorCalRecord.hdHeparinForceSensor.fourthOrderCoeff = calData.hdHeparinForceSensor.fourthOrderCoeff; + forceSensorCalRecord.hdHeparinForceSensor.thirdOrderCoeff = calData.hdHeparinForceSensor.thirdOrderCoeff; + forceSensorCalRecord.hdHeparinForceSensor.secondOrderCoeff = calData.hdHeparinForceSensor.secondOrderCoeff; + forceSensorCalRecord.hdHeparinForceSensor.gain = calData.hdHeparinForceSensor.gain; + forceSensorCalRecord.hdHeparinForceSensor.offset = calData.hdHeparinForceSensor.offset; + + return status; } Index: firmware/App/HDCommon.h =================================================================== diff -u -rabbad386f4cc94f315300dffef321fe8c03fbd52 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision abbad386f4cc94f315300dffef321fe8c03fbd52) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -25,7 +25,7 @@ #define HD_VERSION_MAJOR 0 #define HD_VERSION_MINOR 6 #define HD_VERSION_MICRO 0 -#define HD_VERSION_BUILD 9037 +#define HD_VERSION_BUILD 63 // ********** development build switches ********** @@ -47,14 +47,16 @@ // #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_CAL_CHECK 1 // Disable calibration checks + #define DISABLE_DIALYSATE_TEMP_CHECK 1 // Disable dialysate temperature check // #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position #define SKIP_CAL_CHECK 1 // #define RUN_PUMPS_OPEN_LOOP 1 // BP and DPi pumps will be run open loop (no flow sensor feedback) @@ -63,24 +65,27 @@ // #define EMC_TEST_BUILD 1 // EMC test build - HD/DG run separately but connected, HD pumps toggle on/off w/ stop button #define ALARMS_DEBUG 1 // Triggered alarms sent to debug UART #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_WET_SELF_TESTS 1 // Skip Pre-treatment prime wet self-tests +// #define TEMP_UI_ALARM_SILENCE_FIX 1 // Temporary UI fix for handling alarm silence request msg // #define V2_0_SYSTEM 1 // Build for v2.0 system - #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_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_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 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 DISABLE_SYRINGE_PUMP_ALARMS 1 // Disable some syringe pump alarms that are triggering intermittently +// #define NO_PUMP_FLOW_LIMITS 1 // Allow any commanded flow rate for peristaltic pumps + #define DISABLE_BUBBLE_ALARMS 1 // Disable bubble alarms + #define DISABLE_UI_POST_TEST 1 // Disable the UI POST + // Skip Pre-Treatment and get to treatment as soon as possible +// #define SKIP_UI_INTERACTION 1 // Skip UI interaction. + #define SKIP_SAMPLE_WATER 1 // Skip pre-treatment sample water + #define SKIP_CONSUMABLE_TESTS 1 // Skip pre-treatment consumable Self-tests + #define SKIP_DRY_SELF_TESTS 1 // Skip pre-treatment dry self-tests + #define SKIP_PRIMING 1 // Skip Pre-treatment Prime + #define SKIP_WET_SELF_TESTS 1 // Skip Pre-treatment prime wet self-tests #include #include Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r632bbd302a9ae48df66e40a6faadc3db0c164671 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 632bbd302a9ae48df66e40a6faadc3db0c164671) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -17,6 +17,7 @@ #include "Accel.h" #include "AlarmLamp.h" +#include "Battery.h" #include "BloodFlow.h" #include "Buttons.h" #include "Compatible.h" @@ -43,6 +44,8 @@ /// Delay (in task intervals) after POST completes. #define POST_COMPLETED_DELAY ( 2 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) +/// Maximum wait time for UI to send its final POST result. +#define POST_UI_MAX_WAIT_TIME ( 2 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) // ********** private data ********** @@ -53,13 +56,17 @@ static BOOL uiPOSTPassed; ///< Final result for UI POST tests (TRUE = passed, FALSE = failed). static BOOL dgPOSTPassed; ///< Final result for DG POST tests (TRUE = passed, FALSE = failed). +static BOOL uiPOSTResultReceived; ///< Have we received a final POST result from the UI? +static BOOL dgPOSTResultReceived; ///< Have we received a final POST result from the DG? +static U32 waitForUIPostTimerCtr; ///< Timer counter to limit wait for UI final POST result. static U32 postCompleteDelayTimerCtr; ///< Timer counter for 2 second delay after POST completes and before transitioning to Standbymode. // ********** private function prototypes ********** static HD_POST_STATE_T handlePOSTStatus( SELF_TEST_STATUS_T testStatus ); static SELF_TEST_STATUS_T execFWCompatibilityTest( void ); +static SELF_TEST_STATUS_T execUITest( void ); /*********************************************************************//** * @brief @@ -76,6 +83,9 @@ tempPOSTPassed = TRUE; uiPOSTPassed = FALSE; dgPOSTPassed = FALSE; + uiPOSTResultReceived = FALSE; + dgPOSTResultReceived = FALSE; + waitForUIPostTimerCtr = 0; postCompleteDelayTimerCtr = 0; } @@ -113,8 +123,6 @@ // Ignore stop button in this mode. } - // TODO - send POST status on CAN - // Execute current POST state *Note - these switch cases must be in same order as enum HD_POST_States switch ( postState ) { @@ -123,14 +131,12 @@ break; case POST_STATE_FW_INTEGRITY: - //testStatus = execIntegrityTest(); TODO what happened to this module? - testStatus = SELF_TEST_STATUS_PASSED; + testStatus = execIntegrityTest(); postState = handlePOSTStatus( testStatus ); break; case POST_STATE_BATTERY: - // TODO implement the battery self test - testStatus = SELF_TEST_STATUS_PASSED; + testStatus = execBatteryTest(); postState = handlePOSTStatus( testStatus ); break; @@ -206,8 +212,7 @@ break; case POST_STATE_UI_POST: - // TODO implement the UI POST self test - testStatus = SELF_TEST_STATUS_PASSED; + testStatus = execUITest(); postState = handlePOSTStatus( testStatus ); break; @@ -216,11 +221,10 @@ postState = handlePOSTStatus( testStatus ); break; - // Should be last POST (and last POST test must be a test that completes in a single call) + // Should be last POST (and last POST test must be a test that completes in a single call) case POST_STATE_FPGA: testStatus = execFPGATest(); handlePOSTStatus( testStatus ); // Ignoring return value because last test - if ( TRUE == tempPOSTPassed ) { postState = POST_STATE_COMPLETED; @@ -231,8 +235,6 @@ } break; - // TODO - add POST test requiring all DG and UI POST tests to pass - case POST_STATE_COMPLETED: // Set overall HD POST status to "passed" postPassed = TRUE; @@ -283,6 +285,7 @@ void signalUIPOSTFinalResult( BOOL passed ) { uiPOSTPassed = passed; + uiPOSTResultReceived = TRUE; } /*********************************************************************//** @@ -297,6 +300,7 @@ void signalDGPOSTFinalResult( BOOL passed ) { dgPOSTPassed = passed; + dgPOSTResultReceived = TRUE; } /*********************************************************************//** @@ -375,9 +379,48 @@ { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - // TODO - implement + // TODO - implement (need UI to include its version/compatibility info in its request for f/w versions so we can check compatibility) + //SW_COMPATIBILITY_REV return result; } +/*********************************************************************//** + * @brief + * The execUITest function executes the UI POST passed test. + * @details Inputs: uiPOSTResultReceived, uiPOSTPassed, waitForUIPostTimerCtr + * @details Outputs: waitForUIPostTimerCtr + * @return in progress, passed, or failed + *************************************************************************/ +static SELF_TEST_STATUS_T execUITest( void ) +{ +#ifndef DISABLE_UI_POST_TEST + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + // UI should have sent POST results before we start this test + if ( TRUE == uiPOSTResultReceived ) + { + if ( TRUE == uiPOSTPassed ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_UI_POST_FAILED, 0 ) + result = SELF_TEST_STATUS_FAILED; + } + } + // If UI had not already sent POST results before we started, allow finite period for UI to send. + else if ( ++waitForUIPostTimerCtr > POST_UI_MAX_WAIT_TIME ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_UI_POST_FAILED, 1 ) + result = SELF_TEST_STATUS_FAILED; + } +#else + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; +#endif + + return result; +} + /**@}*/ Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rabc9d65a7158bae927614b646ecb6f38a7ef310c -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision abc9d65a7158bae927614b646ecb6f38a7ef310c) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -101,6 +101,8 @@ #define FPGA_ALARM_AUDIO_VOLUME_SHIFT 3 ///< Shift alarm audio volume 3 bits to left before writing to register. #define FRONT_DOOR_SWITCH_MASK 0x0010 ///< Front door switch bit mask. +#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. @@ -178,13 +180,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,7 +206,8 @@ 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) - U16 fpgaTimerCount_ms; ///< Reg 416. Internal FPGA timer count in ms. + U16 fpgaTimerCount_ms; ///< Reg 416. Free running 1ms timer counter. Rolls over at 65535.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. @@ -1825,6 +1828,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 -rabc9d65a7158bae927614b646ecb6f38a7ef310c -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision abc9d65a7158bae927614b646ecb6f38a7ef310c) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -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/SystemComm.c =================================================================== diff -u -rd8fa48ead3336b1fe090b42030a8648264831076 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision d8fa48ead3336b1fe090b42030a8648264831076) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -327,14 +327,6 @@ { canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); } -#ifdef DEBUG_ENABLED - { - char debugStr[100]; - sprintf( debugStr, "SystemComm-HD resend Last Frame. %2d\n", lastCANPacketSentChannel ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); - sendDebugDataToUI( (U08*)debugStr ); - } -#endif } // We must be only node on CAN bus - nobody is ACKing our transmitted frames else @@ -343,13 +335,6 @@ canXmitRetryCtr = MAX_XMIT_RETRIES; signalCANXmitsCompleted(); // Clear pending xmit flag clearCANXmitBuffers(); // Clear xmit buffers - nothing is going out right now -#ifdef DEBUG_ENABLED - { - char debugStr[100]; - sprintf( debugStr, "SystemComm-HD is only node.\n" ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); - } -#endif } } } @@ -968,13 +953,6 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); #endif } -#ifdef DEBUG_ENABLED - { - char debugStr[100]; - sprintf( debugStr, "SystemComm-HD-Bad Msg CRC.\n" ); - sendDebugDataToUI( (U08*)debugStr ); - } -#endif } /*********************************************************************//** @@ -1557,6 +1535,14 @@ handleTestDialOutPumpHomeRequest( message ); break; + case MSG_ID_SUPER_CLEAR_ALARMS_CMD: + handleTestSuperClearAlarmsRequest( message ); + break; + + case MSG_ID_HD_SET_OP_MODE_REQUEST: + handleTestSetOpModeRequest( message ); + break; + case MSG_ID_HD_FLUID_LEAK_SEND_INTERVAL_OVERRIDE: handleSetFluidLeakBroadcastIntervalOverrideRequest( message ); break; @@ -1589,6 +1575,10 @@ handleBubbleSelfTestRequest( message ); break; + case MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE: + handleBloodPrimeVolumeOverrideRequest( message ); + break; + case MSG_ID_HD_SWITCHES_STATUS_OVERRIDE: handleSetSwitchesStatusOverrideRequest( message ); break; @@ -1597,14 +1587,10 @@ handleTestSwitchesPublishIntervalOverrideRequest( message ); break; - case MSG_ID_HD_SET_OP_MODE_REQUEST: - handleTestSetOpModeRequest( message ); + case MSG_ID_HD_BLOOD_PRIME_SAFETY_VOLUME_OVERRIDE: + handleBloodPrimeSafetyVolumeOverrideRequest( message ); break; - case MSG_ID_SUPER_CLEAR_ALARMS_CMD: - handleTestSuperClearAlarmsRequest( message ); - break; - case MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: handleTestSyringePumpDataBroadcastIntervalOverrideRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rd8fa48ead3336b1fe090b42030a8648264831076 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision d8fa48ead3336b1fe090b42030a8648264831076) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -668,7 +668,7 @@ { if ( 0 == message->hdr.payloadLen ) { - handleTreatmentLogDataRequest(); + sendTreatmentLogDataToUI(); } else { @@ -927,9 +927,75 @@ // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer return serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); } - + /*********************************************************************//** * @brief + * The sendTreatmentLogAlarmEventData function constructs a treatment log + * alarm event data message for UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Treatment log alarm event data msg constructed and queued. + * @param alarmID ID of the occurred alarm + * @param almData1 data associates with the alarm + * @param almData1 data associates with the alarm + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentLogAlarmEventData( ALARM_ID_T alarmID, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ) +{ + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 id = (U32)alarmID; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TREATMENT_LOG_ALARM_EVENT; + msg.hdr.payloadLen = sizeof( ALARM_ID_T ) + 3 * sizeof( F32 ); + + memcpy( payloadPtr, &id, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &almData1.data, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &almData2.data, sizeof( F32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + return serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); +} + +/*********************************************************************//** + * @brief + * The sendTreatmentLogEventData function constructs a treatment log parameter + * change event data message for UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Treatment log event data msg constructed and queued. + * @param event ID of parameter change event + * @param oldValue parameter change event old data value + * @param newValue parameter change event new data value + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentLogEventData( EVENT_ID_T event, F32 oldValue, F32 newValue ) +{ + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 eventID = (U32)event; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TREATMENT_LOG_EVENT; + msg.hdr.payloadLen = sizeof( EVENT_ID_T ) + 3 * sizeof( F32 ); + + memcpy( payloadPtr, &eventID, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &oldValue, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &newValue, sizeof( F32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + return serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); +} + +/*********************************************************************//** + * @brief * The handleSampleWaterCmd function handles a sample water user action command * message from the UI. * @details Inputs: none @@ -3095,11 +3161,11 @@ *************************************************************************/ void handleDGTemperatureData( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof(DG_TEMPERATURES_T) ) + if ( message->hdr.payloadLen == sizeof( TEMPERATURE_SENSORS_DATA_T ) ) { - DG_TEMPERATURES_T payload; - - memcpy( &payload, message->payload, sizeof(DG_TEMPERATURES_T) ); + TEMPERATURE_SENSORS_DATA_T payload; + + memcpy( &payload, message->payload, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); setDialysateTemperatureReadings( payload.TDi, payload.TRo ); } // TODO - what to do if invalid payload length? @@ -3876,9 +3942,11 @@ void handleFWVersionRequest( MESSAGE_T *message ) { MESSAGE_T msg; - HD_VERSIONS_T payload; + HD_VERSIONS_T payload; // TODO - add compatibility data to response U08 *payloadPtr = msg.payload; + // TODO - grab UI version data when UI includes it in this message + // Populate payload payload.major = (U08)HD_VERSION_MAJOR; payload.minor = (U08)HD_VERSION_MINOR; @@ -6011,6 +6079,70 @@ /*********************************************************************//** * @brief + * The handleBloodPrimeVolumeOverrideRequest function handles a request to + * override the calculated blood prime volume (in mL). + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleBloodPrimeVolumeOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodPrimeVolumeOverride( payload.state.f32 ); + } + else + { + result = testResetBloodPrimeVolumeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleBloodPrimeSafetyVolumeOverrideRequest function handles a request to + * override the calculated safety blood prime volume (in mL). + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleBloodPrimeSafetyVolumeOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetBloodPrimeSafetyVolumeOverride( payload.state.f32 ); + } + else + { + result = testResetBloodPrimeSafetyVolumeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief * The handleHDSoftwareResetRequest function handles a request to reset the * HD firmware processor. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rd8fa48ead3336b1fe090b42030a8648264831076 -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision d8fa48ead3336b1fe090b42030a8648264831076) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -306,6 +306,12 @@ // MSG_ID_HD_ACTIVE_ALARMS_LIST_REQUEST_RESPONSE BOOL sendActiveAlarmsList( BOOL accepted, U32 reason, U32 *alarmList, U32 size ); +// MSG_ID_HD_TREATMENT_LOG_ALARM_EVENT +BOOL sendTreatmentLogAlarmEventData( ALARM_ID_T alarmID, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ); + +// MSG_ID_HD_TREATMENT_LOG_EVENT +BOOL sendTreatmentLogEventData( EVENT_ID_T event, F32 oldValue, F32 newValue ); + // *********** public DG command functions ********** // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS @@ -673,6 +679,12 @@ // MSG_ID_HD_BUBBLE_SELF_TEST_REQUEST void handleBubbleSelfTestRequest( MESSAGE_T *message ); +// MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE +void handleBloodPrimeVolumeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_BLOOD_PRIME_SAFETY_VOLUME_OVERRIDE +void handleBloodPrimeSafetyVolumeOverrideRequest( MESSAGE_T *message ); + // MSG_ID_HD_SWITCHES_STATUS_OVERRIDE void handleSetSwitchesStatusOverrideRequest( MESSAGE_T *message ); Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r60e0fc291e3897ab9b86aee7181eeb6d6dd7d35f -r9978c11c54347bac3e696512e02776a5d8ff8490 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 60e0fc291e3897ab9b86aee7181eeb6d6dd7d35f) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 9978c11c54347bac3e696512e02776a5d8ff8490) @@ -26,6 +26,7 @@ #include "OperationModes.h" #include "PresOccl.h" #include "RTC.h" +#include "Switches.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -59,7 +60,10 @@ checkInWithWatchdogMgmt( TASK_GENERAL ); // Do this first to keep timing consistent with watchdog management // Manage data received from other sub-systems - execSystemCommRx(); + execSystemCommRx(); + + // Manage RTC + execRTC(); // Prevent most processing until UI has started communicating #ifndef SIMULATE_UI @@ -91,11 +95,11 @@ // Control dialysate outlet pump (keep after call to BP and DPi controllers) execDialOutFlowController(); -#endif - - // Manage RTC - execRTC(); + // Monitor switches + execSwitches(); +#endif + // Manage NVDataMgmt process record state machine execNVDataMgmtProcessRecord();