Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -rfa41b85cf47fb01cd905b2ed53d472a9cb0c1706 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision fa41b85cf47fb01cd905b2ed53d472a9cb0c1706) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -20,10 +20,6 @@ #include "can.h" #include "etpwm.h" -// TODO - Test includes - remove later -#include "DialInFlow.h" -#include "PresOccl.h" - #include "BloodFlow.h" #include "FPGA.h" #include "InternalADC.h" @@ -35,7 +31,8 @@ #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" -#include "Timers.h" +#include "Timers.h" +#include "Utilities.h" /** * @addtogroup BloodFlow @@ -53,7 +50,7 @@ #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.12 ///< Controller will error if PWM duty cycle < 10%, so set min to 12% /// Interval (ms/task time) at which the blood pump is controlled. -#define BP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) +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 @@ -63,19 +60,24 @@ #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. #define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured speed and speed implied by measured flow. #define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). -#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define BP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for flow vs. motor speed error condition. -#define BP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for motor off error condition. -#define BP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) motor speed error condition. -#define BP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) rotor speed error condition. -#define BP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) pump direction error condition. -#define BP_MAX_ROTOR_SPEED_ERROR_PERSIST ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) blood pump rotor speed too fast error condition. +#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); +/// Persist time (task intervals) for motor off error condition. +static const U32 BP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) motor speed error condition. +static const U32 BP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) rotor speed error condition. +static const U32 BP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// 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); #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 @@ -382,7 +384,7 @@ *************************************************************************/ U32 getBloodPumpMotorCount( void ) { - return bloodPumpMotorEdgeCount / BP_HALL_EDGE_COUNTS_PER_REV; + return bloodPumpMotorEdgeCount; } /*********************************************************************//** @@ -931,25 +933,28 @@ if ( ++bpMotorSpeedCalcTimerCtr >= BP_SPEED_CALC_INTERVAL ) { 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 last = bpLastMotorHallSensorCounts[ bpMotorSpeedCalcIdx ]; + U32 nextIdx = INC_WRAP( bpMotorSpeedCalcIdx, 0, BP_SPEED_CALC_BUFFER_LEN - 1 ); + U16 incDelta = u16DiffWithWrap( bpLastMotorHallSensorCounts[ nextIdx ], bpMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; - U16 delta; - + U16 spdDelta; + S16 delta; + // Determine blood pump speed/direction from delta hall sensor count since last interval if ( incDelta < decDelta ) { - delta = incDelta; - bloodPumpSpeedRPM.data = ( (F32)delta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN; + spdDelta = incDelta; + bloodPumpSpeedRPM.data = ( (F32)spdDelta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN; } else { - delta = decDelta; - bloodPumpSpeedRPM.data = ( (F32)delta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN * -1.0; + spdDelta = decDelta; + bloodPumpSpeedRPM.data = ( (F32)spdDelta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN * -1.0; } - bloodPumpMotorEdgeCount += delta; + + // Keep a running 32-bit edge count used for safety check on volume in some functions + delta = u16BiDiffWithWrap( last, bpMotorHallSensorCount ); + bloodPumpMotorEdgeCount += (U16)delta; // Update last count for next time bpLastMotorHallSensorCounts[ nextIdx ] = bpMotorHallSensorCount; @@ -1261,25 +1266,18 @@ *************************************************************************/ SELF_TEST_STATUS_T execBloodFlowTest( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; U08 const bfmStatus = getFPGABloodFlowMeterStatus(); + // Get the flow sensors calibration record + HD_FLOW_SENSORS_CAL_RECORD_T cal = getHDFlowSensorsCalibrationRecord(); + // Retrieve blood flow sensor calibration data and check for sensor connected status - if ( BFM_SENSOR_PARAM_CORRUPT_STATUS != bfmStatus ) + if ( BFM_SENSOR_PARAM_CORRUPT_STATUS != getFPGABloodFlowMeterStatus() ) { -#ifndef SKIP_CALIBRATION_TESTS - CALIBRATION_DATA_T cal; - - if ( TRUE == getCalibrationData( &cal ) ) - { - bloodFlowCalGain = cal.bloodFlowGain; - bloodFlowCalOffset = cal.bloodFlowOffset_mL_min; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } -#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 { @@ -1294,58 +1292,7 @@ /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ - - -/*********************************************************************//** - * @brief - * The setBloodFlowCalibration function sets the blood flow calibration - * factors and has them stored in non-volatile memory. - * @details Inputs: none - * @details Outputs: bloodFlowCalGain, bloodFlowCalOffset - * @param gain gain calibration factor for blood flow sensor - * @param offset offset calibration factor for blood flow sensor - * @return TRUE if calibration factors successfully set/stored, FALSE if not - *************************************************************************/ -BOOL setBloodFlowCalibration( F32 gain, F32 offset ) -{ - BOOL result = FALSE; - if ( TRUE == isTestingActivated() ) - { - CALIBRATION_DATA_T cal; - - getCalibrationData( &cal ); - // Keep locally and apply immediately - bloodFlowCalGain = gain; - bloodFlowCalOffset = offset; - // Also update calibration record in non-volatile memory - cal.bloodFlowGain = gain; - cal.bloodFlowOffset_mL_min = offset; - if ( TRUE == setCalibrationData( cal ) ) - { - result = TRUE; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The getBloodFlowCalibration function retrieves the current blood flow - * calibration factors. - * @details Inputs: bloodFlowCalGain, bloodFlowCalOffset - * @details Outputs: none - * @param gain value to populate with gain calibration factor for blood flow sensor - * @param offset value to populate with offset calibration factor for blood flow sensor - * @return none - *************************************************************************/ -void getBloodFlowCalibration( F32 *gain, F32 *offset ) -{ - *gain = bloodFlowCalGain; - *offset = bloodFlowCalOffset; -} - /*********************************************************************//** * @brief * The testSetBloodFlowDataPublishIntervalOverride function overrides the Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rba7a576375ad7bbfa0d5a879d82b8783e5182899 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision ba7a576375ad7bbfa0d5a879d82b8783e5182899) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -36,7 +36,6 @@ #define RESERVOIR_SETTLE_TIME_MS 5000 ///< Time (in ms) allotted for reservoir to settle (after fill, before drain). -#define SIZE_OF_SMALL_LOAD_CELL_AVG 8 ///< Small load cell moving average has 8 samples. #define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. /// States of the treatment reservoir management state machine. @@ -49,7 +48,7 @@ TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE, ///< Wait for fill to complete. TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE, ///< Wait a bit for filled reservoir to settle before getting baseline weight (volume). TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE, ///< Wait for active reservoir to be consumed and switch cmd given - then back to flush DG lines state. - TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Wait for inactive reservoir to settle before getting final weight (volume) before starting to drain. + TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE, ///< Wait for inactive reservoir to settle before getting final weight (volume) before starting to drain. NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir mgmt. states. } TREATMENT_RESERVOIR_MGMT_STATE_T; @@ -78,16 +77,10 @@ /// Measured weight from load cells. static OVERRIDE_F32_T loadCellWeightInGrams[ NUM_OF_LOAD_CELLS ]; -/// Filtered (8 sample) weight of reservoirs. -static F32 smFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; /// Filtered (32 sample) weight of reservoirs. static F32 lgFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; // Load cell filtering data -/// Holds load cell samples for small load cell moving average. -static F32 smLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_SMALL_LOAD_CELL_AVG ]; -static U32 smLoadCellReadingsIdx = 0; ///< Index for next sample in small load cell rolling average sample array. -static F32 smLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc small load cell moving average. /// Holds load cell samples for large load cell moving average. static F32 lgLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. @@ -145,12 +138,7 @@ // initialize reservoirs weights for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) { - smFilteredReservoirWeightInGrams[ i ] = 0.0; lgFilteredReservoirWeightInGrams[ i ] = 0.0; - for ( j = 0; j < SIZE_OF_SMALL_LOAD_CELL_AVG; j++ ) - { - smLoadCellReadings[ i ][ j ] = 0.0; - } for ( j = 0; j < SIZE_OF_LARGE_LOAD_CELL_AVG; j++ ) { lgLoadCellReadings[ i ][ j ] = 0.0; @@ -165,9 +153,6 @@ dgCmdResp[ i ].rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } - smLoadCellReadingsIdx = 0; - smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; - smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; lgLoadCellReadingsIdx = 0; lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; @@ -204,6 +189,19 @@ resMgmtTimer = 0; resUseTimer = getMSTimerCount(); resUseVolumeMl = 0.0; +} + +/*********************************************************************//** + * @brief + * The dialysisResumed function initializes the reservoir re-use timer + * when dialysis is started/resumed so that dialysate usage can be tracked. + * @details Inputs: none + * @details Outputs: resUseTimer + * @return none + *************************************************************************/ +void dialysisResumed( void ) +{ + resUseTimer = getMSTimerCount(); } /*********************************************************************//** @@ -220,22 +218,22 @@ U32 dgSubMode = getDGSubMode(); U32 msSinceLastVolumeCalc = calcTimeSince( resUseTimer ); F32 flowRateMlPerMs = (F32)getTargetDialInFlowRate() / (F32)( MS_PER_SECOND * SEC_PER_MIN ); - + // Calculate volume used from active reservoir - do not accumulate if saline bolus in progress if ( SALINE_BOLUS_STATE_IN_PROGRESS != getSalineBolusState() ) { - resUseVolumeMl += ( flowRateMlPerMs * msSinceLastVolumeCalc ); // TODO - should this calc be done and kept by Dialysis sub-mode? + resUseVolumeMl += ( flowRateMlPerMs * msSinceLastVolumeCalc ); } - resUseTimer = getMSTimerCount(); - + resUseTimer = getMSTimerCount(); + // Treatment reservoir mgmt. state machine switch ( currentTrtResMgmtState ) { case TREATMENT_RESERVOIR_MGMT_START_STATE: currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; break; - case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: + case TREATMENT_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: if ( DG_MODE_CIRC == dgOpMode ) { if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) @@ -256,7 +254,7 @@ case TREATMENT_RESERVOIR_MGMT_DRAIN_RESERVOIR_STATE: if ( DG_MODE_CIRC == dgOpMode ) { - currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; + currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; } break; @@ -279,7 +277,7 @@ if ( DG_MODE_FILL == dgOpMode ) { currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; - } + } break; case TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE: @@ -326,8 +324,8 @@ // Reset to start state to restart drain, fill, switch process. currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; } - break; - + break; + default: // TODO - s/w fault currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; @@ -470,13 +468,13 @@ /*********************************************************************//** * @brief - * The getLoadCellWeightInGrams function gets the load cell weight. + * The getLoadCellWeight function gets the current load cell weight. * @details Inputs: loadCellWeightInGrams * @details Outputs: none * @param loadCellID ID of load cell to get * @return the current load cell weight in grams *************************************************************************/ -F32 getLoadCellWeightInGrams( LOAD_CELL_ID_T loadCellID ) +F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ) { F32 result = 0.0; @@ -501,27 +499,6 @@ /*********************************************************************//** * @brief - * The getReservoirWeightSmallFilter function gets the load cell weight - * of the given reservoir after small (8 sample) filter applied. - * @details Inputs: lgFilteredReservoirWeightInGrams[] - * @details Outputs: none - * @param resID ID of reservoir to get filtered weight for - * @return the current filtered weight of the given reservoir in grams - *************************************************************************/ -F32 getReservoirWeightSmallFilter( DG_RESERVOIR_ID_T resID ) -{ - F32 result = 0.0; - - if ( resID < NUM_OF_DG_RESERVOIRS ) - { - result = smFilteredReservoirWeightInGrams[ resID ]; - } - - return result; -} - -/*********************************************************************//** - * @brief * The getReservoirWeightLargeFilter function gets the load cell weight * of the given reservoir after large (32 sample) filter applied. * @details Inputs: lgFilteredReservoirWeightInGrams[] @@ -560,7 +537,7 @@ } else { - // TODO + // TODO - s/w fault } } @@ -617,7 +594,7 @@ } else { - // TODO + // TODO - s/w fault } } @@ -697,16 +674,11 @@ for ( res = DG_RESERVOIR_1; res < NUM_OF_DG_RESERVOIRS; res++ ) { F32 wt = ( res == DG_RESERVOIR_1 ? res1Primary : res2Primary ); - smLoadCellReadingsTotal[ res ] -= smLoadCellReadings[ res ][ smLoadCellReadingsIdx ]; lgLoadCellReadingsTotal[ res ] -= lgLoadCellReadings[ res ][ lgLoadCellReadingsIdx ]; - smLoadCellReadings[ res ][ smLoadCellReadingsIdx ] = wt; lgLoadCellReadings[ res ][ lgLoadCellReadingsIdx ] = wt; - smLoadCellReadingsTotal[ res ] += wt; lgLoadCellReadingsTotal[ res ] += wt; - smFilteredReservoirWeightInGrams[ res ] = smLoadCellReadingsTotal[ res ] / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; lgFilteredReservoirWeightInGrams[ res ] = lgLoadCellReadingsTotal[ res ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; } - smLoadCellReadingsIdx = INC_WRAP( smLoadCellReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); lgLoadCellReadingsIdx = INC_WRAP( lgLoadCellReadingsIdx, 0, SIZE_OF_LARGE_LOAD_CELL_AVG - 1 ); } Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r174c9ba02da6790f01ea9141ab1cc1d28388f2f8 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 174c9ba02da6790f01ea9141ab1cc1d28388f2f8) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -32,7 +32,7 @@ // ********** public definitions ********** -#define DRAIN_RESERVOIR_TO_VOLUME_ML 200 ///< Drain reservoir to this volume (in mL) during treatment. +#define DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during treatment. #ifndef V1_5_SYSTEM #define FILL_RESERVOIR_TO_VOLUME_ML 1700 ///< Fill reservoir to this volume (in mL) during treatment. #else @@ -127,6 +127,7 @@ U32 getDGSubMode( void ); DG_RESERVOIR_ID_T getDGActiveReservoir( void ); DG_RESERVOIR_ID_T getDGInactiveReservoir( void ); +BOOL hasDGCompletedReservoirSwitch( void ); F32 getDGPressure( DG_PRESSURE_SENSORS_T sensorID ); U32 getDGROPumpPressureSetPt( void ); F32 getDGROPumpFlowRateMlMin( void ); @@ -148,15 +149,16 @@ void cmdStopDG( void ); void cmdSetDGActiveReservoir( DG_RESERVOIR_ID_T resID ); void cmdChangeDGValveSetting( DG_VALVE_SETTING_ID_T valveSettingID ); -void cmdStartDGFill( U32 fillToVolMl ); +void cmdStartDGFill( U32 fillToVolMl ); +void cmdStopDGFill( void ); void cmdStartDGDrain( U32 drainToVolMl, BOOL tareLoadCell ); void cmdStartDGTrimmerHeater( void ); -void cmdStopDGTrimmerHeater( void ); -void cmdDGSampleWater( void ); +void cmdStopDGTrimmerHeater( void ); +void cmdDGSampleWater( SAMPLE_WATER_CMD_T cmd ); void handleDGCommandResponse( DG_CMD_RESPONSE_T *dgCmdRespPtr ); BOOL getDGCommandResponse( U32 commandID, DG_CMD_RESPONSE_T *cmdRespPtr ); - + BOOL testSetDialOutLoadCellWeightOverride( U32 sensor, F32 value ); BOOL testResetDialOutLoadCellWeightOverride( U32 sensor ); Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -rfa41b85cf47fb01cd905b2ed53d472a9cb0c1706 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision fa41b85cf47fb01cd905b2ed53d472a9cb0c1706) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -48,8 +48,9 @@ #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.88 ///< Controller will error if PWM duty cycle > 90%, so set max to 88%. #define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.12 ///< Controller will error if PWM duty cycle < 10%, so set min to 12%. - -#define DIP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialIn pump is controlled + +/// 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. @@ -64,12 +65,18 @@ #define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured motor speed and speed implied by measured flow. #define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. #define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). -#define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define DIP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for flow vs. motor speed error condition. -#define DIP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) for motor off error condition. -#define DIP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) motor speed error condition. -#define DIP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) rotor speed error condition. -#define DIP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< Persist time (task intervals) pump direction error condition. +#define DIP_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 DIP_FLOW_VS_SPEED_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) for motor off error condition. +static const U32 DIP_OFF_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) motor speed error condition. +static const U32 DIP_MOTOR_SPEED_ERROR_PERSIST = ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) rotor speed error condition. +static const U32 DIP_ROTOR_SPEED_ERROR_PERSIST = ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +/// Persist time (task intervals) pump direction error condition. +static const U32 DIP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. @@ -1218,25 +1225,16 @@ *************************************************************************/ SELF_TEST_STATUS_T execDialInFlowTest( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; U08 const dfmStatus = getFPGADialysateFlowMeterStatus(); + // Get the flow sensors calibration record + HD_FLOW_SENSORS_CAL_RECORD_T cal = getHDFlowSensorsCalibrationRecord(); - // Retrieve dialysate flow sensor calibration data - if ( DFM_SENSOR_PARAM_CORRUPT_STATUS != dfmStatus ) + if ( DFM_SENSOR_PARAM_CORRUPT_STATUS != getFPGADialysateFlowMeterStatus() ) { -#ifndef SKIP_CALIBRATION_TESTS - CALIBRATION_DATA_T cal; - - if ( TRUE == getCalibrationData( &cal ) ) - { - dialInFlowCalGain = cal.dialysateFlowGain; - dialInFlowCalOffset = cal.dialysateFlowOffset_mL_min; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } -#endif + dialInFlowCalGain = cal.hdFlowSensors[ CAL_DATA_HD_DIALYZER_FLOW_SENSOR ].gain; + dialInFlowCalOffset = cal.hdFlowSensors[ CAL_DATA_HD_DIALYZER_FLOW_SENSOR ].offset; + result = SELF_TEST_STATUS_PASSED; } else { @@ -1252,57 +1250,6 @@ * TEST SUPPORT FUNCTIONS *************************************************************************/ - -/*********************************************************************//** - * @brief - * The setDialInFlowCalibration function sets the dialysate flow calibration - * factors and has them stored in non-volatile memory. - * @details Inputs: none - * @details Outputs: dialInFlowCalGain, dialInFlowCalOffset - * @param gain gain calibration factor for dialysate flow sensor - * @param offset offset calibration factor for dialysate flow sensor - * @return TRUE if calibration factors successfully set/stored, FALSE if not - *************************************************************************/ -BOOL setDialInFlowCalibration( F32 gain, F32 offset ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - CALIBRATION_DATA_T cal; - - getCalibrationData( &cal ); - // Keep locally and apply immediately - dialInFlowCalGain = gain; - dialInFlowCalOffset = offset; - // Also update calibration record in non-volatile memory - cal.dialysateFlowGain = gain; - cal.dialysateFlowOffset_mL_min = offset; - if ( TRUE == setCalibrationData( cal ) ) - { - result = TRUE; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The getDialInFlowCalibration function retrieves the current dialysate flow - * calibration factors. - * @details Inputs: dialInFlowCalGain, dialInFlowCalOffset - * @details Outputs: none - * @param gain value to populate with gain calibration factor for dialysate flow sensor - * @param offset value to populate with offset calibration factor for dialysate flow sensor - * @return none - *************************************************************************/ -void getDialInFlowCalibration( F32 *gain, F32 *offset ) -{ - *gain = dialInFlowCalGain; - *offset = dialInFlowCalOffset; -} - /*********************************************************************//** * @brief * The testSetDialInFlowDataPublishIntervalOverride function overrides the Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -re23087e0c17f6ea81d60641fdb52121a8dd5a099 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision e23087e0c17f6ea81d60641fdb52121a8dd5a099) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -78,7 +78,6 @@ static const U32 DOP_DIRECTION_ERROR_PERSIST = (250 / TASK_PRIORITY_INTERVAL); #define DOP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. -#define DOP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< Motor controller current should always exceed this when pump should be running. #define DOP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. #define DOP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. @@ -940,7 +939,7 @@ else { dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); - if ( ( dopCurr < DOP_MIN_CURR_WHEN_RUNNING_MA ) || ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) ) + if ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) { dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r838df450f09668adbd73e61fadbff8c81fe7926e -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 838df450f09668adbd73e61fadbff8c81fe7926e) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -57,11 +57,13 @@ #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. +static const U32 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 EMPTY_SALINE_BAG_THRESHOLD_MMHG -300.0 ///< Threshold below which the saline bag is considered empty (in mmHg). TODO - get real threshold from Systems +static const U32 EMPTY_SALINE_BAG_PERSISTENCE = ( 250 / TASK_GENERAL_INTERVAL ); ///< Time that saline bag looks empty before saying it is empty. /// Occlusion sensors minimum pressure reading limit when no cartridge is loaded. #define OCCLUSION_NO_CARTRIDGE_PRESSURE_READING_MIN 2000 /// Occlusion sensors maximum pressure reading limit when cartridge is considered loaded. @@ -100,6 +102,7 @@ static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate outlet pump occlusion pressure. static U32 staleVenousPressureCtr = 0; ///< Timer counter for stale venous pressure reading. +static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. // ********** private function prototypes ********** @@ -115,9 +118,9 @@ /*********************************************************************//** * @brief - * The initPresOccl function initializes the initPresOccl module. + * The initPresOccl function initializes the PresOccl module. * @details Inputs: none - * @details Outputs: initPresOccl module initialized. + * @details Outputs: PresOccl module initialized. * @return none *************************************************************************/ void initPresOccl( void ) @@ -154,6 +157,35 @@ return result; } +/*********************************************************************//** + * @brief + * The isSalineBagEmpty function determines whether the saline bag is empty. + * It is assumed that this function will only be called from mode handling + * (General Task) when pumping (BP) from the saline bag. + * Determination is based on pressure going below a negative threshold. + * @details Inputs: arterial line pressure + * @details Outputs: none + * @return TRUE if arterial line pressure is below threshold, FALSE if not. + *************************************************************************/ +BOOL isSalineBagEmpty( void ) +{ + BOOL result = FALSE; + + if ( getMeasuredArterialPressure() < EMPTY_SALINE_BAG_THRESHOLD_MMHG ) + { + if ( ++emptySalineBagCtr >= EMPTY_SALINE_BAG_PERSISTENCE ) + { + result = TRUE; + } + } + else + { + emptySalineBagCtr = 0; + } + + return result; +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. @@ -185,7 +217,7 @@ /*********************************************************************//** * @brief - * The handlePresOcclInitState function handles the pres/occl initialize state + * The handlePresOcclInitState function handles the initialize state * of the pressure/occlusion monitor state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -295,8 +327,6 @@ *************************************************************************/ 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(); @@ -401,7 +431,6 @@ U32 diOccl = getMeasuredDialInPumpOcclusion(); U32 doOccl = getMeasuredDialOutPumpOcclusion(); - // TODO - add persistence #ifndef DISABLE_PRESSURE_CHECKS if ( bpOccl > OCCLUSION_THRESHOLD ) { @@ -429,7 +458,7 @@ * @details Outputs: none * @return the current pressure/occlusion data publication interval (in task intervals). *************************************************************************/ -U32 getPublishPresOcclDataInterval( void ) +static U32 getPublishPresOcclDataInterval( void ) { U32 result = presOcclDataPublishInterval.data; Index: firmware/App/Controllers/PresOccl.h =================================================================== diff -u -r27f3db92495948d4c1192421c1b0c20338c4a034 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 27f3db92495948d4c1192421c1b0c20338c4a034) +++ firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -63,7 +63,7 @@ void initPresOccl( void ); void execPresOccl( void ); -SELF_TEST_STATUS_T execPresOcclTest( void ); +void execPresOcclTest( void ); SELF_TEST_STATUS_T execPresOcclDryTest( void ); F32 getMeasuredArterialPressure( void ); Index: firmware/App/HDCommon.h =================================================================== diff -u -r838df450f09668adbd73e61fadbff8c81fe7926e -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 838df450f09668adbd73e61fadbff8c81fe7926e) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -32,26 +32,28 @@ // TODO - remove build switches before release #ifndef _RELEASE_ #ifndef _VECTORCAST_ + #define BOARD_WITH_NO_HARDWARE 1 // #define RUN_WITHOUT_DG 1 // Run HD w/o DG // #define SIMULATE_UI 1 // Build w/o requirement that UI be there // #define TASK_TIMING_OUTPUT_ENABLED 1 // Re-purposes alarm lamp pins for task timing // #define DISABLE_ALARM_AUDIO 1 // Disable alarm audio #define SKIP_POST 1 // Skip POST tests - all pass -// #define LIMITED_NVDATA_CRC_CHECKS 1 // Only perform POST CRC checks on nv-data records that are implemented so far + #define DONT_SKIP_NV_POST 1 #define DISABLE_AIR_TRAP_LEVELING 1 // Disable air trap level control // #define DISABLE_3WAY_VALVES 1 // Disable 3-way valves // #define TST_3WAY_VALVES_ALWAYS_OPEN 1 // After POST and homing, open all 4 valves #define DISABLE_ACCELS 1 // Disable accelerometer POST and monitoring - #define DISABLE_CRC_ERROR 1 // Do not error on bad CRC for CAN messages - #define DISABLE_ACK_ERRORS 1 // Do not error on failure of other node(s) to ACK a message +// #define DISABLE_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_SALINE_BOLUS_CHECKS 1 // Do not error on HD saline bolus checks + #define DISABLE_SYRINGE_PUMP 1 // Disable syringe pump functionality #define DISABLE_PRESSURE_CHECKS 1 // Do not error on HD pressure checks - #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks +// #define DISABLE_UF_ALARMS 1 // Do not error on HD ultrafiltration checks #define DISABLE_VALVE_ALARMS 1 // Do not error on HD valve position +// #define DISABLE_CAL_CHECK 1 // #define RUN_PUMPS_OPEN_LOOP 1 // BP and DPi pumps will be run open loop (no flow sensor feedback) // #define RAW_FLOW_SENSOR_DATA 1 // Test build will not filter flow sensor data // #define READ_FPGA_ASYNC_DATA 1 // Test build reads non-priority register page every other time @@ -62,7 +64,6 @@ // #define V1_5_SYSTEM 1 // Build for v1.5 system #define SKIP_SAMPLE_WATER 1 // Skip pre-treatment sample water #define SKIP_CONSUMABLE_TESTS 1 // Skip pre-treatment consumable Self-tests - #define SKIP_CALIBRATION_TESTS 1 // Skip pre-treatment self-tests involving calibration #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. Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r965e120959988f653f340d48a0ec22d3ea8206bc -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 965e120959988f653f340d48a0ec22d3ea8206bc) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. @@ -16,14 +16,17 @@ ***************************************************************************/ #include "AlarmMgmt.h" -#include "Buttons.h" +#include "ConsumableSelfTest.h" #include "FPGA.h" #include "ModePreTreat.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PreTreatmentRecirc.h" #include "Prime.h" #include "SelfTests.h" +#include "SampleWater.h" #include "SystemCommMessages.h" +#include "TaskGeneral.h" /** * @addtogroup HDPreTreatmentMode @@ -32,25 +35,77 @@ // ********** private definitions ********** +/// Interval (ms/task time) at which the pre-treatment state data is published on the CAN bus. +#define PRE_TREATMENT_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) + +/// Wait time for ui to transition on completion of a sub-mode (ms/task time). +#define SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + +#define DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN 100 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. + +#define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. +#define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML 700 ///< Fill reservoir two to this volume (in mL) during pre-treatment mode. + +#define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 ///< Primary heater target temperature offset from trimmer heater temperature. + + +/// States of the pre-treatment reservoir management state machine. +typedef enum PreTreatmentReservoirMgmt_States +{ + PRE_TREATMENT_RESERVOIR_MGMT_START_STATE = 0, ///< Wait for signal to start drain and fill reservoirs + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE, ///< Command DG to start draining reservoir + PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE, ///< After sending drain command, process DG drain command response + PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE, ///< Command DG to start filling reservoir + PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE, ///< After sending fill command, process DG fill command response + PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE, ///< Reservoir fill has completed + PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE, ///< Wait for prime operation to switch reservoir + PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE, ///< Pre-treatment reservoir management complete state + NUM_OF_PRE_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of pre-treatments reservoir mgmt. states +} PRE_TREATMENT_RESERVOIR_MGMT_STATE_T; + // ********** private data ********** -static BOOL treatStartReqReceived = FALSE; ///< Flag indicates user requests treatment begin. -static BOOL alarmActionStopReceived = FALSE; ///< Flag indicates an alarm w/ stop property was triggered. +static BOOL confirmInstallRequested = FALSE; ///< Flag indicates user confirms disposable installation. +static BOOL continueToTreatmentRequested = FALSE; ///< Flag indicates user requests to continue to treatment from re-circ. +static BOOL setUFVolStatus; ///< The status of set UF volume operation. +static BOOL patientConnectionConfirm; ///< Flag indicates user has confirmed patient connection complete. +static BOOL treatmentStartRequested = FALSE; ///< Flag indicates user requests treatment begin. + static BOOL alarmActionResumeReceived = FALSE; ///< Flag indicates alarm action resume received. static HD_PRE_TREATMENT_MODE_STATE_T currentPreTreatmentState; ///< Current state of pre-treatment mode state machine. +static U32 preTreatmentPublishTimerCounter; ///< Pre-treatment data broadcast timer counter used to schedule when to transmit data. +static U32 submodeCompleteTransitionTimeCounter; ///< Sub-mode completed transition wait time counter. +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T currentReservoirMgmtState; ///< Current pre-treatment reservoir management state. +static BOOL fillReservoirOneStartRequested; ///< Flag indicates fill reservoir one has been requested. +static BOOL reservoirFilledStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Flag indicates a reservoir has been filled. + // ********** private function prototypes ********** +static void publishPreTreatmentState( void ); static void resetSignalFlags( void ); +static void transitionToCartridgeInstallation( void ); +static void transitionToPatientConnection( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ); +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestNoCartState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleInstallState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestDryState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePrimeState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handleRecirculateState( void ); static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ); +static void execPreTreatmentReservoirMgmt( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ); +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ); + /*********************************************************************//** * @brief * The initPreTreatmentMode function initializes the Pre-Treatment Mode module. @@ -61,7 +116,17 @@ void initPreTreatmentMode( void ) { currentPreTreatmentState = HD_PRE_TREATMENT_START_STATE; + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + fillReservoirOneStartRequested = FALSE; + submodeCompleteTransitionTimeCounter = 0; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = FALSE; + reservoirFilledStatus[ DG_RESERVOIR_2 ] = FALSE; + + initSampleWater(); + initConsumableSelfTest(); initPrime(); initSelfTests(); @@ -84,6 +149,7 @@ setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); initPreTreatmentMode(); + cmdStopDGTrimmerHeater(); } /*********************************************************************//** @@ -106,16 +172,20 @@ switch ( currentPreTreatmentState ) { case HD_PRE_TREATMENT_START_STATE: - cmdStartDG(); - cmdSetDGDialysateTargetTemps( 39.0, 37.0 ); +#ifndef SKIP_SAMPLE_WATER + transitionToSampleWater(); +#endif currentPreTreatmentState = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; break; case HD_PRE_TREATMENT_WATER_SAMPLE_STATE: - transitionToNoCartSelfTests(); - currentPreTreatmentState = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + currentPreTreatmentState = handleWaterSampleState(); break; + case HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE: + currentPreTreatmentState = handleSelfTestConsumableState(); + break; + case HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE: currentPreTreatmentState = handleSelfTestNoCartState(); break; @@ -146,38 +216,133 @@ break; } + // Execute reservoir management for pre-treatment mode + execPreTreatmentReservoirMgmt(); + // Alarm response request flags should be handled at this point, reset in case not handled in current state resetSignalFlags(); + // Broadcast pre-treatment data + publishPreTreatmentState(); + return (U32)currentPreTreatmentState; } /*********************************************************************//** * @brief - * The signalUserBeginningTreatment function handles user start of a - * treatment. + * The signalUserConfirmInstallation function handles user confirmation of + * disposable installation. * @details Inputs: none - * @details Outputs: treatStartReqReceived, send response to treatment start + * @details Outputs: confirmInstallRequested * @return TRUE if signal accepted, FALSE if not *************************************************************************/ -BOOL signalUserBeginningTreatment( void ) +void signalUserConfirmInstallation( void ) { - BOOL result = FALSE; + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_CART_INSTALL_STATE == currentPreTreatmentState ) ) + { + confirmInstallRequested = TRUE; + } +} - // TODO: check patient connection sub-mode state - if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) +/*********************************************************************//** + * @brief + * The signalUserContinueToTreatment function handles user request to continue + * to treatment. + * @details Inputs: none + * @details Outputs: handled and send response to continue to treatment request + * @return none + *************************************************************************/ +void signalUserContinueToTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( HD_PRE_TREATMENT_RECIRCULATE_STATE == currentPreTreatmentState ) { - treatStartReqReceived = TRUE; - result = TRUE; + continueToTreatmentRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; } - sendTreatmentStartResponseMsg( result, 0 ); // TODO - provide reason code if rejected + sendContinueToTreatmentCmdResponse( accepted, rejReason ); +} - return result; +/*********************************************************************//** + * @brief + * The setUserSetUFVolumeStatus function sets the status for user sets UF + * volume operation. + * @details Inputs: set UF volume operation status + * @details Outputs: setUFVolStatus + * @return none + *************************************************************************/ +void setUserSetUFVolumeStatus( BOOL status ) +{ + setUFVolStatus = status; } /*********************************************************************//** * @brief + * The signalUserConfirmPatientConnection function handles user confirms + * patient connection message. + * @details Inputs: none + * @details Outputs: handled and send response to patient connection confirmation + * @return none + *************************************************************************/ +void signalUserConfirmPatientConnection( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_UF_VOLUME_NOT_SET; + + if ( TRUE == setUFVolStatus ) + { + if ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) + { + patientConnectionConfirm = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendPatientConnectionConfirmCmdResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief + * The signalUserStartTreatment function handles user requests to start treatment. + * @details Inputs: patientConnectionConfirm, currentPreTreatmentState + * @details Outputs: handled and send response to treatment start request + * @return none + *************************************************************************/ +void signalUserStartTreatment( void ) +{ + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NO_PATIENT_CONNECTION_CONFIRM; + +#ifndef SKIP_UI_INTERACTION + if ( TRUE == patientConnectionConfirm ) +#endif + { + if ( ( MODE_PRET == getCurrentOperationMode() ) && ( HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE == currentPreTreatmentState ) ) + { + treatmentStartRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + } + } + + sendStartTreatmentResponse( accepted, rejReason ); +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToPreTreatmentMode function executes the given alarm action * as appropriate while in PreTreatment Mode. * @details Inputs: none @@ -190,15 +355,22 @@ switch( action ) { case ALARM_ACTION_STOP: - alarmActionStopReceived = TRUE; + // Stop signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: alarmActionResumeReceived = TRUE; break; case ALARM_ACTION_END_TREATMENT: - requestNewOperationMode( MODE_STAN ); + if ( HD_PRE_TREATMENT_PRIME_STATE > currentPreTreatmentState ) + { + requestNewOperationMode( MODE_STAN ); + } + else + { + requestNewOperationMode( MODE_POST ); + } break; case ALARM_ACTION_ACK: @@ -213,20 +385,187 @@ /*********************************************************************//** * @brief + * The getReservoirFillStatus function returns the fill complete status for + * given reservoir. + * @details Inputs: reservoirFilledStatus + * @details Outputs: none + * @return TRUE if reservoir has been filled, otherwise FALSE; + *************************************************************************/ +BOOL getReservoirFillStatus( DG_RESERVOIR_ID_T reservoirID ) +{ + return reservoirFilledStatus[ reservoirID ]; +} + +/*********************************************************************//** + * @brief + * The publishPreTreatmentState function broadcasts pre-treatment sub-mode + * and current sub-mode state. + * @details Inputs: pre-treatment sub-mode, state + * @details Outputs: pre-treatment sub-mode, state messages sent on interval + * @return none + *************************************************************************/ +static void publishPreTreatmentState( void ) +{ + // Broadcast treatment time and state data at interval + if ( ++preTreatmentPublishTimerCounter >= PRE_TREATMENT_DATA_PUB_INTERVAL ) + { + PRE_TREATMENT_STATE_DATA_T preTreatmentData; + + preTreatmentData.preTreatmentSubMode = currentPreTreatmentState; + preTreatmentData.sampleWaterState = getSampleWaterState(); + preTreatmentData.consumableSelfTestsState = getConsumableSelfTestState(); + preTreatmentData.noCartSelfTestsState = getNoCartSelfTestsState(); + preTreatmentData.installState = 0; + preTreatmentData.drySelfTestsState = getDrySelfTestsState(); + preTreatmentData.primeState = getPrimeState(); + preTreatmentData.recircState = getPreTreatmentRecircState(); + preTreatmentData.patientConnectionState = 0; + + broadcastPreTreatmentState( &preTreatmentData ); + preTreatmentPublishTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief * The resetSignalFlags function resets all signal flags. * @details Inputs: none * @details Outputs: signal flags set to FALSE * @return none *************************************************************************/ static void resetSignalFlags( void ) { - treatStartReqReceived = FALSE; - alarmActionStopReceived = FALSE; + treatmentStartRequested = FALSE; + confirmInstallRequested = FALSE; + continueToTreatmentRequested = FALSE; + alarmActionResumeReceived = FALSE; } /*********************************************************************//** * @brief + * The transitionToCartridgeInstallation function prepares actuators before + * transition to pre-treatment install state. + * @details Inputs: none + * @details Outputs: valves are in insert position + * @return none + *************************************************************************/ +static void transitionToCartridgeInstallation( void ) +{ + VALVE_T valve; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_A_INSERT_EJECT ); + } + + setValveAirTrap( STATE_CLOSED ); +} + +/*********************************************************************//** + * @brief + * The transitionToPatientConnection function prepares actuators before + * transition to pre-treatment patient connection state. + * @details Inputs: none + * @details Outputs: Stopped pumps + * @return none + *************************************************************************/ +static void transitionToPatientConnection( void ) +{ + VALVE_T valve; + setUFVolStatus = FALSE; + patientConnectionConfirm = FALSE; + treatmentStartRequested = FALSE; + + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + setValvePosition( valve, VALVE_POSITION_C_CLOSE ); + } + + signalBloodPumpHardStop(); + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + cmdStartDGTrimmerHeater(); +} + +/*********************************************************************//** + * @brief + * The handleWaterSampleState function handles sample water state during + * pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed sample water state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleWaterSampleState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_WATER_SAMPLE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + execSampleWater(); + +#ifndef SKIP_SAMPLE_WATER + if ( SAMPLE_WATER_COMPLETE_STATE == getSampleWaterState() ) +#endif + { + cmdDGSampleWater( SAMPLE_WATER_CMD_END ); + + if ( SELF_TEST_STATUS_PASSED == getSampleWaterResult() ) + { + if ( ( DG_MODE_STAN == dgOpMode ) && ( DG_STANDBY_MODE_STATE_IDLE == dgSubMode ) ) + { + state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + F32 const trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + F32 const primaryHeaterTemp = trimmerHeaterTemp + PRIMARY_HEATER_TARGET_TEMP_OFFSET; + + cmdStartDG(); + cmdSetDGDialysateTargetTemps( primaryHeaterTemp, trimmerHeaterTemp ); + transitionToConsumableSelfTest(); + } + else + { + cmdStopDG(); + } + } + else + { + requestNewOperationMode( MODE_STAN ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleSelfTestConsumableState function handles consumable self-test state + * during pre-treatment mode. + * @details Inputs: none + * @details Outputs: executed consumable self-test state machine + * @return current state (sub-mode) + *************************************************************************/ +static HD_PRE_TREATMENT_MODE_STATE_T handleSelfTestConsumableState( void ) +{ + HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE; + + execConsumableSelfTest(); + + if ( CONSUMABLE_SELF_TESTS_COMPLETE_STATE == getConsumableSelfTestState() ) + { + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE; + fillReservoirOneStartRequested = TRUE; + transitionToNoCartSelfTests(); + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleSelfTestNoCartState function handles self-test with no cartridge. * @details Inputs: none * @details Outputs: home blood pump and dialysate pumps @@ -243,19 +582,20 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopSelfTests(); - } - execNoCartSelfTests(); - if ( TRUE == isNoCartSelfTestsPassed() ) + if ( NO_CART_SELF_TESTS_COMPLETE_STATE == getNoCartSelfTestsState() ) { - state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_CART_INSTALL_STATE; + transitionToCartridgeInstallation(); + } } return state; @@ -273,9 +613,14 @@ { HD_PRE_TREATMENT_MODE_STATE_T state = HD_PRE_TREATMENT_CART_INSTALL_STATE; - // TODO: handle install verification and transition - transitionToDrySelfTests(); - state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; +#ifndef SKIP_UI_INTERACTION + if ( TRUE == confirmInstallRequested ) +#endif + { + confirmInstallRequested = FALSE; + state = HD_PRE_TREATMENT_SELF_TEST_DRY_STATE; + transitionToDrySelfTests(); + } return state; } @@ -298,20 +643,20 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumeSelfTests(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopSelfTests(); - } - execDrySelfTests(); - if ( TRUE == isDrySelfTestsPassed() ) + if ( DRY_SELF_TESTS_COMPLETE_STATE == getDrySelfTestsState() ) { - transitionToPrime(); - state = HD_PRE_TREATMENT_PRIME_STATE; + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_PRIME_STATE; + transitionToPrime(); + } } return state; @@ -336,21 +681,21 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePrime(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPrime(); - } - execPrime(); - if ( TRUE == isPrimeCompleted() ) + if ( HD_PRIME_COMPLETE == getPrimeState() ) { - state = HD_PRE_TREATMENT_RECIRCULATE_STATE; - activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); - transitionToPreTreatmentRecirc(); + if ( submodeCompleteTransitionTimeCounter++ >= SUBMODE_COMPLETE_UI_TRANSITION_TIME_COUNT ) + { + submodeCompleteTransitionTimeCounter = 0; + state = HD_PRE_TREATMENT_RECIRCULATE_STATE; + activateAlarmNoData( ALARM_ID_PRIME_COMPLETED_LOW_PRIORITY ); + transitionToPreTreatmentRecirc(); + } } return state; @@ -375,19 +720,19 @@ if ( TRUE == alarmActionResumeReceived ) { + alarmActionResumeReceived = FALSE; signalResumePreTreatmentRecirc(); } - if ( TRUE == alarmActionStopReceived ) - { - signalStopPreTreatmentRecirc(); - } - execPreTreatmentRecirc(); - if ( TRUE == isPatientConnectionRequested() ) +#ifndef SKIP_UI_INTERACTION + if ( TRUE == continueToTreatmentRequested ) +#endif { + continueToTreatmentRequested = FALSE; state = HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; + transitionToPatientConnection(); } return state; @@ -403,15 +748,259 @@ *************************************************************************/ static HD_PRE_TREATMENT_MODE_STATE_T handlePatientConnectionState( void ) { - DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); - - if ( TRUE == treatStartReqReceived ) + if ( TRUE == treatmentStartRequested ) { + DG_RESERVOIR_ID_T const activeRes = getDGActiveReservoir(); setStartReservoirVolume( activeRes ); requestNewOperationMode( MODE_TREA ); } return HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE; } +/*********************************************************************//** + * @brief + * The execPreTreatmentReservoirMgmt function executes the state machine for + * reservoir management during pre-treatment mode. + * @details Inputs: currentReservoirMgmtState + * @details Outputs: DG reservoirs' fills managed. + * @return none + *************************************************************************/ +static void execPreTreatmentReservoirMgmt( void ) +{ + // treatment reservoir mgmt. state machine + switch ( currentReservoirMgmtState ) + { + case PRE_TREATMENT_RESERVOIR_MGMT_START_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtStartState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtDrainCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCmdRespState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtFillCompleteState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE: + currentReservoirMgmtState = handlePreTreatmentReservoirMgmtWaitReservoirSwitchState(); + break; + + case PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE: + break; + + default: + currentReservoirMgmtState = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRIME_RESERVOIR_MGMT_INVALID_STATE, (U32)currentReservoirMgmtState ); + break; + } +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtStartState function handles reservoir + * management start state for pre-treatment mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtStartState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_STATE; + + if ( TRUE == fillReservoirOneStartRequested ) + { + fillReservoirOneStartRequested = FALSE; + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdState function sends drain + * command to DG when DG is in re-circulate mode. + * @details Inputs: fillReservoirOneStartRequested + * @details Outputs: processed fill reservoir one request + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + // If DG has not started yet, start DG + if ( DG_MODE_STAN == dgOpMode ) + { + cmdStartDG(); + } + + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtDrainCmdRespState function waits + * and processes DG drain command response. + * @details Inputs: DG drain command response + * @details Outputs: processed DG drain command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtDrainCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + if ( DG_MODE_DRAI == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdState function sends fill + * command to DG when DG is in re-circulate mode. + * @details Inputs: DG operation mode and operation sub-mode + * @details Outputs: sent fill command to DG + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + + if ( DG_RESERVOIR_1 == getDGInactiveReservoir() ) + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML ); + } + else + { + cmdStartDGFill( PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML ); + } + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCmdRespState function waits + * and processes DG fill command response. + * @details Inputs: DG fill command response + * @details Outputs: processed DG fill command response + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCmdRespState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_CMD_RESP_STATE; + DG_CMD_RESPONSE_T dgCmdResp; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + + + if ( ( TRUE == getDGCommandResponse( DG_CMD_START_FILL, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejectCode ) ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_START_FILL_STATE; + } + + if ( DG_MODE_FILL == dgOpMode ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtFillCompleteState function switches + * reservoir after the first one fill is complete and restart reservoir management + * state machine. + * @details Inputs: DG operation mode + * @details Outputs: switch active reservoir and signal prime fill complete status + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtFillCompleteState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_FILL_COMPLETE_STATE; + DG_OP_MODE_T dgOpMode = getDGOpMode(); + U32 dgSubMode = getDGSubMode(); + + if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) + { + if ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = TRUE; + } + else if ( ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) && ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) ) + { + reservoirFilledStatus[ DG_RESERVOIR_2 ] = TRUE; + state = PRE_TREATMENT_RESERVOIR_MGMT_COMPLETE_STATE; + } + } + + return state; +} + + +/*********************************************************************//** + * @brief + * The handlePreTreatmentReservoirMgmtWaitReservoirSwitchState function waits + * until prime operation switches the active reservoir before filling up next reservoir. + * @details Inputs: DG intactive reservoir + * @details Outputs: start filling next reservoir + * @return current state of pre-treatment reservoir management + *************************************************************************/ +static PRE_TREATMENT_RESERVOIR_MGMT_STATE_T handlePreTreatmentReservoirMgmtWaitReservoirSwitchState( void ) +{ + PRE_TREATMENT_RESERVOIR_MGMT_STATE_T state = PRE_TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RESERVOIR_SWITCH_STATE; + + if ( DG_RESERVOIR_2 == getDGInactiveReservoir() ) + { + state = PRE_TREATMENT_RESERVOIR_MGMT_DRAIN_CMD_STATE; + } + + return state; +} + /**@}*/ Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rbb114842e73659f097bb8b8ec0d670bfa4f8cb73 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision bb114842e73659f097bb8b8ec0d670bfa4f8cb73) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -23,10 +23,14 @@ #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" +#include "ModePostTreat.h" +#include "ModePreTreat.h" +#include "ModeStandby.h" +#include "ModeTreatment.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "SystemComm.h" #include "SystemCommMessages.h" -#include "ModeStandby.h" #ifdef EMC_TEST_BUILD // TODO - test code #include "FPGA.h" #endif @@ -103,23 +107,25 @@ #ifndef RUN_WITHOUT_DG if ( TRUE == stop ) { - activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); + activateAlarmNoData( ALARM_ID_TREATMENT_STOPPED_BY_USER ); // TODO - remove alarm? Nothing to stop here. } // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: - // Temporary test code - TODO - remove later - if ( TRUE == isDGCommunicating() ) - { - currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; - } + currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; break; case STANDBY_WAIT_FOR_TREATMENT_STATE: if ( TRUE == treatStartReqReceived ) { + // Initialize treatment modes before starting a new treatment + initTreatParamsMode(); + initPreTreatmentMode(); + initTreatmentMode(); + initPostTreatmentMode(); + // Start treatment workflow with treatment parameters mode requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } @@ -264,7 +270,7 @@ *************************************************************************/ void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ) { - // TODO - implement + // Alarm actions not handled in Standby mode } /**@}*/ Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -rbb114842e73659f097bb8b8ec0d670bfa4f8cb73 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision bb114842e73659f097bb8b8ec0d670bfa4f8cb73) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -24,6 +24,7 @@ #include "DialOutFlow.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "SyringePump.h" #include "SystemCommMessages.h" /** @@ -61,10 +62,10 @@ { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=3}, {.uInt=0} }, // TREATMENT_PARAM_DIALYZER_TYPE { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=60}, {.uInt=30} }, // TREATMENT_PARAM_BP_MEAS_INTERVAL { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=150}, {.uInt=75} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATE - { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=200}, {.sInt=-300} }, // TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=200}, {.sInt=100} }, // TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=-100}, {.sInt=600}, {.sInt=-100} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=100}, {.sInt=600}, {.sInt=400} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=0}, {.sInt=-300} }, // TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=0}, {.sInt=0} }, // TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=600}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=600}, {.sInt=400} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=1.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_DISPENSE_RATE { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=2.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME { CRITICAL_DATA_TYPE_F32, {.sFlt=35.0}, {.sFlt=38.0}, {.sFlt=37.0} }, // TREATMENT_PARAM_DIALYSATE_TEMPERATURE @@ -103,6 +104,8 @@ void initTreatParamsMode( void ) { currentTreatmentParamsState = HD_TREATMENT_PARAMS_MODE_STATE_START; + // Reset all treatment parameters + resetAllTreatmentParameters(); } /*********************************************************************//** @@ -118,9 +121,6 @@ // Reset this mode initTreatParamsMode(); - // Reset all treatment parameters when transitioning to this mode - resetAllTreatmentParameters(); - validTreatParamsReceived = FALSE; treatParamsConfirmed = FALSE; treatParamsRejected = FALSE; @@ -258,6 +258,13 @@ *************************************************************************/ U32 execTreatParamsMode( void ) { + BOOL stop = isStopButtonPressed(); + + if ( TRUE == stop ) + { + // Ignore stop button in this mode. + } + // Execute mode state machine switch ( currentTreatmentParamsState ) { @@ -332,10 +339,7 @@ // Set all treatment parameters (except UF volume which is not yet received) for ( param = TREATMENT_PARAM_FIRST_UINT; param < TREATMENT_PARAM_UF_VOLUME; param++ ) { - if ( FALSE == setCriticalData( &treatmentParameters[ param ], stagedParams[ param ] ) ) - { - // TODO - should never get here - s/w fault? - } + setCriticalData( &treatmentParameters[ param ], stagedParams[ param ] ); } // Retain original settings for treatment that may be adjusted later during treatment origTreatmentParams.bloodFlowRate_mL_min = getCriticalData( &treatmentParameters[ TREATMENT_PARAM_BLOOD_FLOW ] ).uInt; @@ -346,6 +350,16 @@ origTreatmentParams.venousPressureLowLimit_mmHg = getCriticalData( &treatmentParameters[ TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ] ).sInt; origTreatmentParams.venousPressureHighLimit_mmHg = getCriticalData( &treatmentParameters[ TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ] ).sInt; + // If using Heparin in this treatment, set state to stopped otherwise off + if ( ( stagedParams[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].sFlt > 0.0 ) || ( stagedParams[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].sFlt > 0.0 ) ) + { + setHeparinStopped(); + } + else + { + setHeparinOff(); + } + // Go to pre-treatment mode requestNewOperationMode( MODE_PRET ); @@ -593,11 +607,12 @@ *************************************************************************/ static void sendTreatmentParamsResponse( BOOL rejected, U32 *reasons ) { + BOOL accepted = ( TRUE == rejected ? FALSE : TRUE ); U32 respPayload[NUM_OF_TREATMENT_PARAMS]; memcpy( &respPayload[0], &reasons[0], sizeof(TREATMENT_PARAMS_DATA_PAYLOAD_T) ); - sendTreatmentParametersResponseMsg( rejected, (U08*)(&respPayload[0]), ( NUM_OF_TREATMENT_PARAMS - 1 ) * sizeof(U32) ); // UF vol. param not included in reject reasons + sendTreatmentParametersResponseMsg( accepted, (U08*)(&respPayload[0]), ( NUM_OF_TREATMENT_PARAMS - 1 ) * sizeof(U32) ); // UF vol. param not included in reject reasons } /*********************************************************************//** Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r0eee20d6e821c444dbfbc7ba98b9dd64e2b08ec8 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 0eee20d6e821c444dbfbc7ba98b9dd64e2b08ec8) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -38,7 +38,7 @@ // ********** private data ********** /// HD operation mode broadcast interval (in task interval/sec). -static const U32 BROADCAST_HD_OP_MODE_INTERVAL = ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); +static const U32 BROADCAST_HD_OP_MODE_INTERVAL = ( 250 / TASK_GENERAL_INTERVAL ); // ********** private data ********** @@ -56,7 +56,7 @@ /* INIT */{ MODE_FAUL, MODE_NLEG, MODE_INIT, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, }, /* STAN */{ MODE_FAUL, MODE_SERV, MODE_NLEG, MODE_STAN, MODE_TPAR, MODE_NLEG, MODE_NLEG, MODE_NLEG, }, /* TPAR */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_TPAR, MODE_PRET, MODE_NLEG, MODE_NLEG, }, -/* PRET */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_PRET, MODE_TREA, MODE_POST, }, +/* PRET */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_PRET, MODE_TREA, MODE_POST, }, /* TREA */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_TREA, MODE_POST, }, /* POST */{ MODE_FAUL, MODE_NLEG, MODE_NLEG, MODE_STAN, MODE_NLEG, MODE_NLEG, MODE_NLEG, MODE_POST, }, }; Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r174c9ba02da6790f01ea9141ab1cc1d28388f2f8 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 174c9ba02da6790f01ea9141ab1cc1d28388f2f8) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -38,22 +38,14 @@ #define MAX_PRIME_TIME ( 10 * SEC_PER_MIN ) ///< Maximum prime time (in seconds). #define PRIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the prime data is published on the CAN bus. -#define BLOOD_PUMP_FLOW_RATE_PURGE_AIR 100 ///< Blood pump flow rate during prime purge air state. +#define BLOOD_PUMP_FLOW_RATE_PURGE_AIR 500 ///< Blood pump flow rate during prime purge air state. #define BLOOD_PUMP_FLOW_RATE_CIRC_BLOOD_CIRCUIT 300 ///< Blood pump flow rate during prime recirculate blood circuit state. #define DIALYSATE_PUMP_PRIME_FLOW_RATE 300 ///< Dialysate pump flow rate during priming fluid path. #define LOAD_CELL_VOLUME_NOISE_TOLERANCE 0.05 ///< Allow 5% tolerance on load cell readings. -#define PRIME_DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during prime. - -#define PRIME_CONSUMED_DIALYSATE_VOLUME_ML 100 ///< Volume of dialysate consumed during prime. - -/// Fill reservoir 1 to this volume (in mL) during prime. -#define PRIME_FILL_RESERVOIR_ONE_VOLUME_ML ( FILL_RESERVOIR_TO_VOLUME_ML - PRIME_CONSUMED_DIALYSATE_VOLUME_ML ) -#define PRIME_FILL_RESERVOIR_TWO_VOLUME_ML 500 ///< Fill reservoir 2 to this volume (in mL) during prime. - -#define NO_AIR_DETECTED_COUNT ( 10 * MS_PER_SECOND ) ///< No air detected time period count. -#define PURGE_AIR_TIME_OUT_COUNT ( 30 * MS_PER_SECOND ) ///< Time period count for purge air time out. +#define NO_AIR_DETECTED_COUNT ( 20 * MS_PER_SECOND ) ///< No air detected time period count. +#define PURGE_AIR_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for purge air time out. #define MIN_LOAD_CELL_STEADY_VOLUME_TIME ( 10 * MS_PER_SECOND ) ///< Minimum time load cell reading need to remain steady in ms. #define PRIME_DIALYSATE_DIALYZER_TIME_LIMIT ( 120 * MS_PER_SECOND ) ///< Time limit for priming dialysate dialyzer circuit. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 120 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. @@ -79,29 +71,26 @@ static HD_PRE_TREATMENT_PRIME_STATE_T previousPrimeState; ///< Previous state of the prime sub-mode, to use when resuming from pause. static PRIME_RESERVOIR_MGMT_STATE_T currentReservoirMgmtState; ///< Current reservoir management state. -static BOOL primeCompleted; ///< Prime complete status. static U32 primeStartTime; ///< Starting time of priming (in ms). static U32 primePauseStartTime; ///< Priming pause start time (in ms). static U32 primeStatusBroadcastTimerCounter; ///< Prime status data broadcast timer counter used to schedule when to transmit data. static BOOL primeStartRequested; ///< Flag indicates user requesting to start prime. -static BOOL primeStopRequested; ///< Flag indicates alarm requesting to stop prime. static BOOL primeResumeRequested; ///< Flag indicates user requesting prime resume. -static BOOL reservoirFilledStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Flag indicates a reservoir has been filled. static U32 noAirDetectedStartTime; ///< starting time when detecting no air. static U32 purgeAirTimeOutStartTime; ///< Starting time for purge air state time out. static U32 primeDialysateDialyzerStartTime; ///< Starting time of priming dialysate dialyzer circuit. static U32 primeDialysateBypassStartTime; ///< Starting time of priming dialysate bypass circuit. static U32 previousLoadCellReading; ///< Previous load cell reading. static U32 loadcellSteadyVolumeStartTime; ///< Load cell steady volume starting time. +static BOOL runBloodCircuitPrimeAgain; ///< Flag indicates HD should run blood circuit prime once more time. // ********** private function prototypes ********** static void resetPrimeFlags(); -static void handlePrimePauseRequest( void ); +static void setupForPrimePause( void ); static void broadcastPrimingStatus( void ); -static void execPrimeReservoirMgmt( void ); static void purgeAirValvesBloodPumpControl( void ); static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeWaitForUserStartState( void ); @@ -141,14 +130,11 @@ currentPrimeState = HD_PRIME_START_STATE; currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_START_STATE; - primeCompleted = FALSE; primeStartTime = getMSTimerCount(); primePauseStartTime = 0; primeStatusBroadcastTimerCounter = 0; + runBloodCircuitPrimeAgain = TRUE; - reservoirFilledStatus[ DG_RESERVOIR_1 ] = FALSE; - reservoirFilledStatus[ DG_RESERVOIR_2 ] = FALSE; - setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_END_TREATMENT, TRUE ); @@ -169,7 +155,6 @@ switch ( currentPrimeState ) { case HD_PRIME_START_STATE: - cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); #ifdef SKIP_PRIMING currentPrimeState = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; #else @@ -214,7 +199,6 @@ break; case HD_PRIME_COMPLETE: - primeCompleted = TRUE; break; case HD_PRIME_PAUSE: @@ -230,52 +214,56 @@ // Prime flags should be handled by now resetPrimeFlags(); - // Handle prime pause request - handlePrimePauseRequest(); - // Broadcast priming data broadcastPrimingStatus(); - - // Exec reservoir management for priming - execPrimeReservoirMgmt(); } /*********************************************************************//** * @brief - * The isPrimeCompleted function returns the status of prime. - * @details Inputs: none + * The getPrimeState function returns the current state of prime sub-mode. + * @details Inputs: currentPrimeState * @details Outputs: none - * @return TRUE if prime has completed succesfully, otherwise FALSE + * @return current prime state *************************************************************************/ -BOOL isPrimeCompleted( void ) +U32 getPrimeState( void ) { - return primeCompleted; + return (U32)currentPrimeState; } /*********************************************************************//** * @brief - * The signalResumePrime function signals the prime sub-mode to resume - * previous operation. + * The signalStartPrime function signals the prime sub-mode the user requested + * to start priming operation. * @details Inputs: none - * @details Outputs: primeResumeRequested + * @details Outputs: primeStartRequested * @return none *************************************************************************/ -void signalResumePrime( void ) +void signalStartPrime( void ) { - primeResumeRequested = TRUE; + BOOL accepted = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE; + + if ( HD_PRIME_WAIT_FOR_USER_START_STATE == currentPrimeState ) + { + primeStartRequested = TRUE; + accepted = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + + sendStartPrimeCmdResponse( accepted, rejReason ); } /*********************************************************************//** * @brief - * The signalStopPrime function signals the prime sub-mode to stop when an - * alarm with stop property has been triggered. + * The signalResumePrime function signals the prime sub-mode to resume + * previous operation. * @details Inputs: none - * @details Outputs: primeStopRequested + * @details Outputs: primeResumeRequested * @return none *************************************************************************/ -void signalStopPrime( void ) +void signalResumePrime( void ) { - primeStopRequested = TRUE; + primeResumeRequested = TRUE; } /*********************************************************************//** @@ -287,32 +275,25 @@ *************************************************************************/ static void resetPrimeFlags( void ) { - // TODO: set to false after integration with UI - primeStartRequested = TRUE; + primeStartRequested = FALSE; primeResumeRequested = FALSE; - primeStopRequested = FALSE; } /*********************************************************************//** * @brief - * The handlePrimePauseRequest function handles prime pause request. + * The setupForPrimePause function stop pumps handles prime pause request. * @details Inputs: none * @details Outputs: stop all pumps, switch to prime pause state. * @return none *************************************************************************/ -static void handlePrimePauseRequest( void ) +static void setupForPrimePause( void ) { - if ( ( TRUE == primeStopRequested ) && ( HD_PRIME_PAUSE != currentPrimeState ) ) - { - signalDialOutPumpHardStop(); - signalDialInPumpHardStop(); - signalBloodPumpHardStop(); + signalDialOutPumpHardStop(); + signalDialInPumpHardStop(); + signalBloodPumpHardStop(); - primeStopRequested = FALSE; - primePauseStartTime = getMSTimerCount(); - previousPrimeState = currentPrimeState; - currentPrimeState = HD_PRIME_PAUSE; - } + primePauseStartTime = getMSTimerCount(); + previousPrimeState = currentPrimeState; } /*********************************************************************//** @@ -335,7 +316,6 @@ if ( ++primeStatusBroadcastTimerCounter >= PRIME_DATA_PUB_INTERVAL ) { PRIMING_DATA_PAYLOAD_T primeData; - primeData.currentPrimeState = currentPrimeState; primeData.totalTime = MAX_PRIME_TIME; primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; @@ -346,126 +326,6 @@ /*********************************************************************//** * @brief - * The execPrimeReservoirMgmt function executes the state machine for the - * reservoir management during pre-treatment prime sub-mode. - * @details Inputs: currentReservoirMgmtState - * @details Outputs: DG reservoirs' fills managed. - * @return none - *************************************************************************/ -static void execPrimeReservoirMgmt( void ) -{ - DG_CMD_RESPONSE_T dgCmdResp; - DG_OP_MODE_T dgOpMode = getDGOpMode(); - U32 dgSubMode = getDGSubMode(); - - // treatment reservoir mgmt. state machine - switch ( currentReservoirMgmtState ) - { - case PRIME_RESERVOIR_MGMT_START_STATE: - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; - break; - - case PRIME_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE: - if ( DG_MODE_CIRC == dgOpMode ) - { - if ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_WAIT_FOR_DRAIN_CMD_RESP; - cmdStartDGDrain( PRIME_DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE ); - } - } - else - { - // TODO Handle when DG mode is out of sync - } - break; - - case PRIME_RESERVOIR_MGMT_WAIT_FOR_DRAIN_CMD_RESP: - if ( ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejected ) ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; - } - - if ( DG_MODE_DRAI == dgOpMode ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_DRAIN_STATE; - } - break; - - case PRIME_RESERVOIR_MGMT_DRAIN_STATE: - if ( DG_MODE_CIRC == dgOpMode ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_START_FILL_STATE; - } - break; - - case PRIME_RESERVOIR_MGMT_START_FILL_STATE: - if ( ( DG_MODE_CIRC == dgOpMode ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == dgSubMode ) ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_WAIT_FOR_FILL_CMD_RESP; - - if ( DG_RESERVOIR_1 == getDGInactiveReservoir() ) - { - cmdStartDGFill( PRIME_FILL_RESERVOIR_ONE_VOLUME_ML ); - } - else - { - cmdStartDGFill( PRIME_FILL_RESERVOIR_TWO_VOLUME_ML ); - } - } - break; - - case PRIME_RESERVOIR_MGMT_WAIT_FOR_FILL_CMD_RESP: - if ( ( TRUE == getDGCommandResponse( DG_CMD_START_FILL, &dgCmdResp ) ) && ( DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE == dgCmdResp.rejected ) ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_START_FILL_STATE; - } - - if ( DG_MODE_FILL == dgOpMode ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FILL_STATE; - } - break; - - case PRIME_RESERVOIR_MGMT_FILL_STATE: - if ( DG_MODE_CIRC == dgOpMode ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FILL_COMPLETE_STATE; - } - break; - - case PRIME_RESERVOIR_MGMT_FILL_COMPLETE_STATE: - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FILL_COMPLETE_STATE; - - if ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) - { - reservoirFilledStatus[ DG_RESERVOIR_1 ] = TRUE; - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_WAIT_RESERVOIR_TWO_INACTIVE; - } - else if ( ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) && ( FALSE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) ) - { - reservoirFilledStatus[ DG_RESERVOIR_2 ] = TRUE; - } - break; - - case PRIME_RESERVOIR_MGMT_WAIT_RESERVOIR_TWO_INACTIVE: - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_WAIT_RESERVOIR_TWO_INACTIVE; - - if ( DG_RESERVOIR_2 == getDGInactiveReservoir() ) - { - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_FLUSH_DG_LINES_STATE; - } - break; - - default: - currentReservoirMgmtState = PRIME_RESERVOIR_MGMT_START_STATE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRIME_RESERVOIR_MGMT_INVALID_STATE, (U32)currentReservoirMgmtState ); - break; - } -} - -/*********************************************************************//** - * @brief * The purgeAirValvesBloodPumpControl function controls valves and blood pump * to purge air. * @details Inputs: none @@ -480,6 +340,8 @@ setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); setValveAirTrap( STATE_OPEN ); + signalDialOutPumpHardStop(); + signalDialInPumpHardStop(); setBloodPumpTargetFlowRate( BLOOD_PUMP_FLOW_RATE_PURGE_AIR, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); } @@ -495,7 +357,12 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_WAIT_FOR_USER_START_STATE; + // Keep updating start time until the user requested priming + primeStartTime = getMSTimerCount(); + +#ifndef SKIP_UI_INTERACTION if ( TRUE == primeStartRequested ) +#endif { primeStartRequested = FALSE; state = HD_PRIME_SALINE_SETUP_STATE; @@ -514,10 +381,18 @@ *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeSalineSetupState( void ) { + HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_SALINE_PURGE_AIR_STATE; + purgeAirValvesBloodPumpControl(); purgeAirTimeOutStartTime = getMSTimerCount(); - return HD_PRIME_SALINE_PURGE_AIR_STATE; + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + + return state; } /*********************************************************************//** @@ -550,6 +425,12 @@ state = HD_PRIME_SALINE_CIRC_BLOOD_CIRCUIT_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -579,6 +460,12 @@ state = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -594,30 +481,39 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_RESERVOIR_ONE_FILL_COMPLETE_STATE; - if ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) + if ( TRUE == getReservoirFillStatus( DG_RESERVOIR_1 ) ) { cmdSetDGActiveReservoir( DG_RESERVOIR_1 ); - setValvePosition( VDI, VALVE_POSITION_B_OPEN ); - setValvePosition( VDO, VALVE_POSITION_B_OPEN ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - setValveAirTrap( STATE_CLOSED ); + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); - setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - previousLoadCellReading = 0; - loadcellSteadyVolumeStartTime = getMSTimerCount(); - primeDialysateDialyzerStartTime = getMSTimerCount(); + previousLoadCellReading = 0; + loadcellSteadyVolumeStartTime = getMSTimerCount(); + primeDialysateDialyzerStartTime = getMSTimerCount(); -#ifdef SKIP_PRIMING - state = HD_PRIME_WET_SELF_TESTS_STATE; -#else - state = HD_PRIME_DIALYSATE_DIALYZER_STATE; -#endif + #ifdef SKIP_PRIMING + state = HD_PRIME_WET_SELF_TESTS_STATE; + #else + state = HD_PRIME_DIALYSATE_DIALYZER_STATE; + #endif + } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -640,7 +536,15 @@ { if ( TRUE == didTimeout( loadcellSteadyVolumeStartTime, MIN_LOAD_CELL_STEADY_VOLUME_TIME ) ) { - state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; + if ( TRUE == runBloodCircuitPrimeAgain ) + { + runBloodCircuitPrimeAgain = FALSE; + state = HD_PRIME_SALINE_SETUP_STATE; + } + else + { + state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; + } } } else @@ -654,6 +558,12 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRIME_DIALYSATE_DIALYZER_TIME_OUT, PRIME_DIALYSATE_DIALYZER_TIME_LIMIT ); } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -669,24 +579,34 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; - if ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) + if ( TRUE == getReservoirFillStatus( DG_RESERVOIR_2 ) ) { cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); - signalDialOutPumpHardStop(); - setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - setValveAirTrap( STATE_CLOSED ); + if ( TRUE == hasDGCompletedReservoirSwitch() ) + { + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - previousLoadCellReading = 0; - primeDialysateBypassStartTime = getMSTimerCount(); - loadcellSteadyVolumeStartTime = getMSTimerCount(); - state = HD_PRIME_DIALYSATE_BYPASS_STATE; + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + + previousLoadCellReading = 0; + primeDialysateBypassStartTime = getMSTimerCount(); + loadcellSteadyVolumeStartTime = getMSTimerCount(); + state = HD_PRIME_DIALYSATE_BYPASS_STATE; + } } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -723,6 +643,12 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRIME_DIALYSATE_BYPASS_TIME_OUT, PRIME_DIALYSATE_BYPASS_TIME_LIMIT ); } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } @@ -738,23 +664,26 @@ { HD_PRE_TREATMENT_PRIME_STATE_T state = HD_PRIME_WET_SELF_TESTS_STATE; - if ( TRUE == primeStopRequested ) + if ( TRUE == primeResumeRequested ) { signalResumeSelfTests(); } - if ( TRUE == primeResumeRequested ) - { - signalStopSelfTests(); - } - +#ifndef SKIP_WET_SELF_TESTS execWetSelfTests(); if ( TRUE == isWetSelfTestsPassed() ) +#endif { state = HD_PRIME_COMPLETE; } + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + setupForPrimePause(); + state = HD_PRIME_PAUSE; + } + return state; } Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -rc3cf7af051c1ee070df90a9c072df16be48f478f -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision c3cf7af051c1ee070df90a9c072df16be48f478f) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -81,7 +81,8 @@ BOOL noResume; ///< Treatment may not be resumed at this time BOOL noRinseback; ///< Rinseback may not be initiated at this time BOOL noEndTreatment; ///< Ending the treatment is not an option at this time - BOOL noNewTreatment; ///< No new treatments may be started even if current treatment is ended + BOOL noNewTreatment; ///< No new treatments may be started even if current treatment is ended + BOOL noDialRecirc; ///< No dialysate re-circulation allowed at this time BOOL usrACKRequired; ///< The user must acknowledge top alarm BOOL lampOn; ///< The alarm lamp is on } COMP_ALARM_STATUS_T; @@ -238,16 +239,23 @@ SW_FAULT_ID_MODE_PRE_TREATMENT_PRIME_INVALID_STATE, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, // 95 + SW_FAULT_ID_BLOOD_PRIME_INVALID_STATE, + SW_FAULT_ID_RINSEBACK_INVALID_STATE, + SW_FAULT_ID_TREATMENT_END_INVALID_STATE, + SW_FAULT_ID_TREATMENT_RECIRC_INVALID_STATE, + SW_FAULT_ID_TREATMENT_STOP_INVALID_STATE, // 100 + SW_FAULT_ID_MODE_PRIME_INVALID_ALARM_ACTION, + SW_FAULT_ID_INVALID_NVDATAMGMT_EXEC_CAL_STATE, SW_FAULT_ID_HD_INVALID_NO_CARTRIDGE_SELF_TEST_STATE, SW_FAULT_ID_HD_INVALID_DRY_SELF_TEST_STATE, - SW_FAULT_ID_HD_INVALID_WET_SELF_TEST_STATE, + SW_FAULT_ID_HD_INVALID_WET_SELF_TEST_STATE, // 105 SW_FAULT_ID_HD_INVALID_PRE_TREATMENT_RECIRC_STATE, - SW_FAULT_ID_HD_INVALID_COMMAND_RESPONSE_ID, // 100 + SW_FAULT_ID_HD_INVALID_COMMAND_RESPONSE_ID, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, SW_FAULT_ID_HD_INVALID_VALVE_SETTING_ID, - SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, + SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, // 110 SW_FAULT_ID_HD_SYRINGE_INVALID_CONT_CMD, - SW_FAULT_ID_HD_SYRINGE_INVALID_VREF, // 105 + SW_FAULT_ID_HD_SYRINGE_INVALID_VREF, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; @@ -263,10 +271,11 @@ void clearAlarm( ALARM_ID_T alarm ); void clearAlarmCondition( ALARM_ID_T alarm ); void setAlarmUserActionEnabled( ALARM_USER_ACTION_T action, BOOL enabled ); -void signalAlarmSilence( U32 cmd ); +void signalAlarmSilence( ALARM_SILENCE_CMD_T cmd ); void signalAlarmUserActionInitiated( ALARM_USER_ACTION_T action ); BOOL isAlarmActive( ALARM_ID_T alarm ); BOOL isAnyAlarmActive( void ); +BOOL isDialysateRecircBlocked( void ); BOOL doesAlarmStatusIndicateStop( void ); ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ); BOOL isAlarmRecoverable( ALARM_ID_T alarm ); Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r838df450f09668adbd73e61fadbff8c81fe7926e -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 838df450f09668adbd73e61fadbff8c81fe7926e) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -7,8 +7,8 @@ * * @file FPGA.c * -* @author (last) Sean Nash -* @date (last) 14-Oct-2020 +* @author (last) Peman Montazemi +* @date (last) 15-Feb-2021 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -81,6 +81,7 @@ #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. +#define FPGA_FLUIDLEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. #define FPGA_ADA_INPUT_STATUS_MASK 0x0001 ///< Bit mask for arterial air bubble detector input status. #define FPGA_ADV_INPUT_STATUS_MASK 0x0002 ///< Bit mask for venous air bubble detector input status. #define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector status. @@ -103,7 +104,7 @@ } FPGA_HEADER_T; // Read only on FPGA /// Record structure for FPGA continuous priority reads. -typedef struct // TODO - add all sensor readings to this structure per FPGA register map +typedef struct { U08 errorCountProcessor; ///< Reg 256. TBD. U08 errorCountPC; ///< Reg 257. TBD. @@ -191,7 +192,7 @@ } FPGA_SENSORS_T; /// Record structure for FPGA continuous priority writes. -typedef struct // TODO - add all actuator set points to this structure per FPGA register map +typedef struct { U08 fpgaSensorTest; ///< Reg 11. Blood leak and bubble detector sensor test register. U16 fpgaPIDControl; ///< Reg 12. Valve PID enables. @@ -214,7 +215,7 @@ // 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 +typedef struct { U16 fpgaDieTemp; ///< Reg 512. Internal FPGA die temperature. U16 fpgaADCVccVoltage; ///< Reg 514. Internal FPGA Vcc voltage. @@ -491,8 +492,6 @@ fpgaState = handleFPGAReceiveHeaderState(); break; - // TODO - sensor/ADC init/configuration states - case FPGA_STATE_RCV_ALL_SENSORS: fpgaState = handleFPGAReceiveAllSensorsState(); break; @@ -545,8 +544,6 @@ fpgaState = handleFPGAReadHeaderState(); break; - // TODO - sensor/ADC init/configuration states - case FPGA_STATE_WRITE_ALL_ACTUATORS: fpgaState = handleFPGAWriteAllActuatorsState(); break; @@ -1395,7 +1392,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpStatus function gets the latest syringe pump status - * register reading. + * register reading. Bit 0 indicates a fault. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump status reading @@ -1408,7 +1405,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpADCReadCounter function gets the latest syringe pump - * ADC read counter. + * ADC read counter. Counter is 8-bit and rolls over when exceeding 255. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC read counter @@ -1422,6 +1419,9 @@ * @brief * The getFPGASyringePumpADCandDACStatus function gets the latest syringe pump * ADC/DAC status register reading. + * Bit 7 = DAC write and read-back done + * Bit 6 = I2C error on DAC data transfer + * Bit 0..5 = count of I2C errors, rolls over after 63 * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC/DAC status reading @@ -1435,6 +1435,8 @@ * @brief * The getFPGASyringePumpEncoderStatus function gets the latest syringe pump * encoder status register reading. + * Bit 7 = direction (0=fwd, 1=rev) + * Bit 0..5 = direction error count (# of errors after power up, rolls over after 63) * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump encoder status reading @@ -1460,7 +1462,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpADCChannel0 function gets the latest syringe pump ADC - * channel 0 register reading. + * channel 0 register reading (syringe pump force sensor). * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC channel 0 reading @@ -1473,7 +1475,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpADCChannel1 function gets the latest syringe pump ADC - * channel 1 register reading. + * channel 1 register reading (syringe detection switch). * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC channel 1 reading @@ -1486,7 +1488,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpADCChannel2 function gets the latest syringe pump ADC - * channel 2 register reading. + * channel 2 register reading (syringe pump home position sensor). * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC channel 2 reading @@ -1680,6 +1682,21 @@ /*********************************************************************//** * @brief + * The noFluidLeakDetected function returns TRUE if no fluid leak has been + * detected (dry) and FALSE if a fluid leak has been detected (wet). + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return noFluidLeakDetected + *************************************************************************/ +BOOL noFPGAFluidLeakDetected( void ) +{ + U16 noFluidLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_FLUIDLEAK_STATE_MASK; + + return ( 0 == noFluidLeakDetected ? FALSE : TRUE ); +} + +/*********************************************************************//** + * @brief * The setValveDialyzerInletPosition function sets the position of VDi * in counts * @details Inputs: fpgaActuatorSetPoints Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rb8d74fc5b07d0e62d841b4c5a786b2be4e593c63 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision b8d74fc5b07d0e62d841b4c5a786b2be4e593c63) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -208,7 +208,7 @@ * @return none *************************************************************************/ void checkInFromUI( void ) -{ +{ if ( FALSE == uiDidCommunicate ) { // Start DG check-in timer when UI first communicates timeOfLastDGCheckIn = getMSTimerCount(); @@ -946,7 +946,7 @@ activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); dgIsCommunicating = FALSE; } - } + } } /*********************************************************************//** @@ -1243,6 +1243,18 @@ handleStartTreatmentRequest( message ); break; + case MSG_ID_UI_RINSEBACK_CMD: + handlRinsebackCmd( message ); + break; + + case MSG_ID_UI_RECIRC_CMD: + handleTreatmentRecircCmd( message ); + break; + + case MSG_ID_UI_TX_END_CMD: + handleTreatmentEndCmd( message ); + break; + case MSG_ID_DG_COMMAND_RESPONSE: handleDGCmdResp( message ); break; @@ -1251,8 +1263,32 @@ handleTesterLogInRequest( message ); break; + case MSG_ID_HD_SET_CALIBRATION_RECORD: + handleSetHDCalibrationRecord( message ); + break; + + case MSG_ID_HD_GET_CALIBRATION_RECORD: + handleGetHDCalibrationRecord( message ); + break; + + case MSG_ID_HD_SET_SYSTEM_RECORD: + handleSetHDSystemRecord( message ); + break; + + case MSG_ID_HD_GET_SYSTEM_RECORD: + handleGetHDSystemRecord( message ); + break; + + case MSG_ID_HD_GET_SERVICE_RECORD: + handleGetHDServiceRecord( message ); + break; + + case MSG_ID_HD_SET_SERVICE_RECORD: + handleSetHDServiceRecord( message ); + break; + default: - // TODO - unrecognized message ID received - ignore + // Unrecognized message ID received - ignore break; } @@ -1303,6 +1339,10 @@ case MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE: handleTestBloodFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: + handleTestTreatmentTimeRemainingOverrideRequest( message ); break; case MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE: @@ -1479,12 +1519,55 @@ handleTestDialOutPumpHomeRequest( message ); break; + case MSG_ID_HD_FLUID_LEAK_SEND_INTERVAL_OVERRIDE: + handleSetFluidLeakBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE: + handleSetFluidLeakStateDetectorOverrideRequest( message ); + + case MSG_ID_HD_SET_OP_MODE_REQUEST: + handleTestSetOpModeRequest( message ); + break; + case MSG_ID_SUPER_CLEAR_ALARMS_CMD: handleTestSuperClearAlarmsRequest( message ); break; + case MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: + handleTestSyringePumpDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_OPERATION_REQUEST: + handleTestSyringePumpOperationRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_RATE_OVERRIDE: + handleTestSyringePumpMeasuredRateOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_FORCE_OVERRIDE: + handleTestSyringePumpMeasuredForceOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_SYRINGE_DETECT_OVERRIDE: + handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_HOME_OVERRIDE: + handleTestSyringePumpMeasuredHomeOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_POSITION_OVERRIDE: + handleTestSyringePumpMeasuredPositionOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_VOLUME_OVERRIDE: + handleTestSyringePumpMeasuredVolumeOverrideRequest( message ); + break; + default: - // TODO - unrecognized message ID received - ignore + // Unrecognized message ID received - ignore break; } } Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rbaadbfda2c0b0a51ee830ec5de414604f9a3971e -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision baadbfda2c0b0a51ee830ec5de414604f9a3971e) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -28,15 +28,18 @@ #include "ModePreTreat.h" #include "ModeStandby.h" #include "ModeTreatment.h" -#include "ModeTreatmentParams.h" -#include "PresOccl.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PresOccl.h" #include "RTC.h" #include "SampleWater.h" #include "SafetyShutdown.h" #include "SystemComm.h" -#include "SystemCommMessages.h" +#include "SystemCommMessages.h" +#include "TreatmentEnd.h" +#include "TreatmentRecirc.h" #include "Utilities.h" -#include "Valves.h" +#include "Valves.h" #include "WatchdogMgmt.h" /** @@ -398,8 +401,8 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; -} - +} + /*********************************************************************//** * @brief * The sendChangeBloodDialysateRateChangeResponse function constructs a change @@ -1324,7 +1327,7 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); return result; -} +} /*********************************************************************//** * @brief @@ -1479,28 +1482,19 @@ * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: treatment state msg constructed and queued - * @param subMode Current state (sub-mode) of treatment - * @param uFState Current state of ultrafiltration - * @param salineBolusState 1=saline bolus in progress, 0=not, 2=max bolus volume reached + * @param payload Record with treatment state data * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL broadcastTreatmentState( U32 subMode, U32 uFState, U32 salineBolusState ) +BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; - TREATMENT_STATE_DATA_T payload; - // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_TREATMENT_STATE; msg.hdr.payloadLen = sizeof( TREATMENT_STATE_DATA_T ); - payload.treatmentSubMode = subMode; - payload.uFState = uFState; - payload.salineBolusState = salineBolusState; - payload.heparinState = 0; // TODO - add this later - memcpy( payloadPtr, &payload, sizeof( TREATMENT_STATE_DATA_T ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer @@ -1650,6 +1644,124 @@ /***********************************************************************//** * @brief + * The broadcastTreatmentStopData function constructs a treatment stop data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: treatment stop data msg constructed and queued + * @param timeout treatment stop timeout (in sec) + * @param countdown treatment stop timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TREATMENT_STOP_TIMER_DATA; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &timeout, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &countdown, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastRinsebackData function constructs a rinseback data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: rinseback data msg constructed and queued + * @param data rinseback data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RINSEBACK_PROGRESS; + msg.hdr.payloadLen = sizeof( RINSEBACK_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( RINSEBACK_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastRecircData function constructs a treatment re-circ data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: treatment re-circ data msg constructed and queued + * @param timeout re-circulation timeout (in sec) + * @param countdown re-circulation timeout count down (in sec) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRecircData( U32 timeout, U32 countdown ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RECIRC_PROGRESS; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + + memcpy( payloadPtr, &timeout, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &countdown, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastBloodPrimeData function constructs a blood prime data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: blood prime data msg constructed and queued + * @param data blood prime data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_BLOOD_PRIME_PROGRESS; + msg.hdr.payloadLen = sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( BLOOD_PRIME_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief * The broadcastAirTrapData function constructs an HD air trap data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none @@ -1744,10 +1856,39 @@ /***********************************************************************//** * @brief - * The broadcastPrimeData function constructs a priming status data msg to \n + * The broadcastFluidLeakState function constructs an HD fluid leak state msg to \n + * be broadcasted and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: fluid leak state msg constructed and queued + * @param state fluid leak state + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 leakState = (U32)state; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_FLUID_LEAK_STATE; + msg.hdr.payloadLen = sizeof( U32 ); + + memcpy( payloadPtr, &leakState, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/***********************************************************************//** + * @brief + * The broadcastPrimeData function constructs a prime data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none - * @details Outputs: priming data msg constructed and queued + * @details Outputs: prime data msg constructed and queued * @param primeDataPtr prime data record pointer * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ @@ -1770,6 +1911,124 @@ return result; } +/*********************************************************************//** + * @brief + * The sendHDCalibrationRecord function sends out the HD calibration + * record. + * @details Inputs: none + * @details Outputs: HD calibration record msg constructed and queued + * @param msgCurrNum: current payload number + * @param msgTotalNum: total number of payloads + * @param length: buffer length to be written + * @param calRcrdAddress: start address of the calibration record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHDCalibrationRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* calRcrdAddress ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SEND_CALIBRATION_RECORD; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + length; + + memcpy( payloadPtr, &payloadCurrNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &payloadTotalNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &length, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, calRcrdAddress, length ); + + // 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_PC, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The sendHDSystemRecord function sends out the HD system record. + * @details Inputs: none + * @details Outputs: HD system record msg constructed and queued + * @param msgCurrNum: current payload number + * @param msgTotalNum: total number of payloads + * @param length: buffer length to be written + * @param sysRcrdAddress: start address of the system record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHDSystemRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* sysRcrdAddress ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SEND_SYSTEM_RECORD; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + length; + + memcpy( payloadPtr, &payloadCurrNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &payloadTotalNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &length, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, sysRcrdAddress, length ); + + // 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_PC, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The sendHDServiceRecord function sends out the HD service record. + * @details Inputs: none + * @details Outputs: HD system record msg constructed and queued + * @param msgCurrNum: current payload number + * @param msgTotalNum: total number of payloads + * @param length: buffer length to be written + * @param srvcRcrdAddress: start address of the service record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHDServiceRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* srvcRcrdAddress ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SEND_SERVICE_RECORD; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + length; + + memcpy( payloadPtr, &payloadCurrNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &payloadTotalNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &length, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, srvcRcrdAddress, length ); + + // 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_PC, ACK_NOT_REQUIRED ); + + return result; +} + #ifdef EMC_TEST_BUILD BOOL broadcastCANErrorCount( U32 count ) { @@ -1896,7 +2155,7 @@ memcpy( &cmd, payloadPtr, sizeof( U32 ) ); - signalAlarmSilence( cmd ); + signalAlarmSilence( (ALARM_SILENCE_CMD_T)cmd ); } else { @@ -1970,8 +2229,6 @@ memcpy( &payload, message->payload, sizeof(LOAD_CELL_READINGS_PAYLOAD_T) ); setNewLoadCellReadings( payload.res1PrimaryLoadCell, payload.res1BackupLoadCell, payload.res2PrimaryLoadCell, payload.res2BackupLoadCell ); } - // TODO - what to do if invalid payload length? - // TODO - how to know if DG stops sending these? } /*********************************************************************//** @@ -2014,7 +2271,6 @@ memcpy( &payload, message->payload, sizeof(DG_RO_PUMP_DATA_PAYLOAD_T) ); setDGROPumpData( payload.setPtPSI, payload.measFlowRateMlMin ); } - // TODO - what to do if invalid payload length? } /*********************************************************************//** @@ -2035,7 +2291,6 @@ memcpy( &payload, message->payload, sizeof(DG_DRAIN_PUMP_DATA_PAYLOAD_T) ); setDGDrainPumpData( payload.setPtRPM ); } - // TODO - what to do if invalid payload length? } /*********************************************************************//** @@ -2056,7 +2311,6 @@ memcpy( &payload, message->payload, sizeof(DG_PRESSURES_DATA_PAYLOAD_T) ); setDGPressures( payload.roInPSI, payload.roOutPSI, payload.drainInPSI, payload.drainOutPSI ); } - // TODO - what to do if invalid payload length? } /*********************************************************************//** @@ -2077,7 +2331,6 @@ memcpy( &payload, message->payload, sizeof(DG_RESERVOIRS_DATA_PAYLOAD_T) ); setDGReservoirsData( (DG_RESERVOIR_ID_T)payload.resID, payload.setFillToVolumeMl, payload.setDrainToVolumeMl ); } - // TODO - what to do if invalid payload length? } /*********************************************************************//** @@ -2180,8 +2433,8 @@ /*********************************************************************//** * @brief - * The sendInitiateTreatmentResponseMsg function constructs a initiate treatment - * response message to the UI and queues the msg for transmit on + * The sendTreatmentStartResponseMsg function constructs a treatment start + * request response message to the UI and queues the msg for transmit on * the appropriate CAN channel. * @details Inputs: none * @details Outputs: Treatment start response msg constructed and queued. @@ -2256,12 +2509,12 @@ * response to the UI and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: Treatment parameters response msg constructed and queued. - * @param rejected T/F - are settings rejected? + * @param accepted T/F - are settings accepted? * @param rejectReasons reasons each parameter was rejected (if not accepted) * @param byteLength number of bytes that array of reject reasons takes * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendTreatmentParametersResponseMsg( BOOL rejected, U08 *rejectReasons, U32 byteLength ) +BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ) { BOOL result; MESSAGE_T msg; @@ -2272,7 +2525,7 @@ msg.hdr.msgID = MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE; msg.hdr.payloadLen = sizeof( BOOL ) + byteLength; - memcpy( payloadPtr, &rejected, sizeof( BOOL ) ); + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); payloadPtr += sizeof( BOOL ); memcpy( payloadPtr, rejectReasons, byteLength ); @@ -2416,7 +2669,7 @@ sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); } } - + /*********************************************************************//** * @brief * The handleChangeBloodDialysateRateChangeRequest function handles a blood @@ -2560,7 +2813,177 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); return result; +} + +/*********************************************************************//** + * @brief + * The handlRinsebackCmd function handles a rinseback user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handlRinsebackCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalRinsebackUserAction( (REQUESTED_RINSEBACK_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendRinsebackCmdResponse function constructs a rinseback user action + * response to the UI and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Rinseback command response msg constructed and queued. + * @param accepted T/F - was rinseback user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendRinsebackCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RINSEBACK_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleTreatmentRecircCmd function handles a treatment re-circ user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTreatmentRecircCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalTreatmentRecircUserAction( (REQUESTED_TREATMENT_RECIRC_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendTreatmentRecircCmdResponse function constructs a treatment re-circulation + * user action response to the UI and queues the msg for transmit on the appropriate + * CAN channel. + * @details Inputs: none + * @details Outputs: Treatment re-circ command response msg constructed and queued. + * @param accepted T/F - was re-circ user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentRecircCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RECIRC_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; } + +/*********************************************************************//** + * @brief + * The handleTreatmentEndCmd function handles a treatment end user action command + * message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTreatmentEndCmd( MESSAGE_T *message ) +{ + if ( sizeof(U32) == message->hdr.payloadLen ) + { + U32 cmd; + + memcpy( &cmd, &message->payload[0], sizeof(U32) ); + + signalTreatmentEndUserAction( (REQUESTED_TREATMENT_END_USER_ACTIONS_T)cmd ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief + * The sendTreatmentEndCmdResponse function constructs a treatment end + * user action response to the UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Treatment end command response msg constructed and queued. + * @param accepted T/F - was user action accepted? + * @param rejReason reason why action was rejected (or zero if accepted) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendTreatmentEndCmdResponse( BOOL accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_TX_END_CMD_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} /*********************************************************************//** * @brief @@ -3518,7 +3941,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetBloodPumpOcclusionOverride( payload.state.f32 ); + result = testSetBloodPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3550,7 +3973,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialInPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialInPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3582,7 +4005,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialOutPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialOutPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3916,6 +4339,31 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleTestTreatmentTimeRemainingOverrideRequest function handles a treatment + * time remaining override request message. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestTreatmentTimeRemainingOverrideRequest( MESSAGE_T *message ) +{ + U32 payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof(U32) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(U32) ); + result = testSetTreatmentTimeRemainingOverride( payload ); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /*********************************************************************//** * @brief * The handleTestHDSafetyShutdownOverrideRequest function handles a @@ -4046,84 +4494,6 @@ /*********************************************************************//** * @brief - * The handleSetAccelCalibration function handles a request to set - * accelerometer calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetAccelCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(ACCEL_CAL_PAYLOAD_T) ) - { - ACCEL_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(ACCEL_CAL_PAYLOAD_T) ); - result = setAccelCalibration( payload.xOffset, payload.yOffset, payload.zOffset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief - * The handleSetBloodFlowCalibration function handles a request to set - * blood flow calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetBloodFlowCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(LINEAR_F32_CAL_PAYLOAD_T) ) - { - LINEAR_F32_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(LINEAR_F32_CAL_PAYLOAD_T) ); - result = setBloodFlowCalibration( payload.gain, payload.offset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief - * The handleSetDialysateFlowCalibration function handles a request to set - * dialysate flow calibration factors. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetDialysateFlowCalibration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - // Verify payload length - if ( message->hdr.payloadLen == sizeof(LINEAR_F32_CAL_PAYLOAD_T) ) - { - LINEAR_F32_CAL_PAYLOAD_T payload; - - memcpy( &payload, message->payload, sizeof(LINEAR_F32_CAL_PAYLOAD_T) ); - result = setDialInFlowCalibration( payload.gain, payload.offset ); - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleTestSetTreatmentParameter function handles a request to set * a specific treatment parameter value. * @details Inputs: none @@ -4347,12 +4717,12 @@ BOOL result = FALSE; // Verify payload length - if ( sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) == message->hdr.payloadLen ) + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) { - memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); if ( FALSE == payload.reset ) { - result = testSetAirTrapLevelOverride( (AIR_TRAP_LEVEL_SENSORS_T)payload.index, (AIR_TRAP_LEVELS_T)(payload.state.u32) ); + result = testSetAirTrapLevelOverride( (AIR_TRAP_LEVEL_SENSORS_T)payload.index, (AIR_TRAP_LEVELS_T)( payload.state.u32 ) ); } else { @@ -4366,6 +4736,70 @@ /*********************************************************************//** * @brief + * The handleSetFluidLeakBroadcastIntervalOverrideRequest function handles a + * request to override the fluid leak state broadcast interval. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetFluidLeakBroadcastIntervalOverrideRequest( 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 = testSetFluidLeakStatePublishIntervalOverride( (U32)( payload.state.u32 ) ); + } + else + { + result = testResetFluidLeakStatePublishIntervalOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleSetFluidLeakStateDetectorOverrideRequest function handles a request to + * override the fluid leak detector state. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetFluidLeakStateDetectorOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) + { + result = testSetFluidLeakStateOverride( ( FLUID_LEAK_STATES_T)( payload.state.u32 ) ); + } + else + { + result = testResetFluidLeakStateOverride(); + } + } + + // 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 @@ -4398,9 +4832,8 @@ * @brief * The handleTestBloodPumpHomeRequest function handles a request to home * the blood pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -4421,9 +4854,8 @@ * @brief * The handleTestDialInPumpHomeRequest function handles a request to home * the dialysate inlet pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -4444,9 +4876,8 @@ * @brief * The handleTestDialOutPumpHomeRequest function handles a request to home * the dialysate outlet pump. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -4467,9 +4898,8 @@ * @brief * The handleTestSuperClearAlarmsRequest function handles a request to clear * all active alarms. - * @details - * Inputs : none - * Outputs : message handled + * @details Inputs: none + * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ @@ -4483,12 +4913,461 @@ memcpy( &key, message->payload, sizeof(U32) ); result = testClearAllAlarms( key ); + } - result = TRUE; + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSetOpModeRequest function handles a request to set the + * HD operation mode. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSetOpModeRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + U32 mode; + + memcpy( &mode, message->payload, sizeof(U32) ); + result = testSetOperationMode( (HD_OP_MODE_T)mode ); } // Respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** +* @brief +* The handleSetHDCalibrationRecord function handles a request to set the HD +* calibration data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleSetHDCalibrationRecord( MESSAGE_T *message ) +{ + BOOL status = FALSE; + U08* payloadPtr = message->payload; + U32 currentMessage; + U32 totalMessages; + U32 payloadLength; + + memcpy(¤tMessage, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&totalMessages, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&payloadLength, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + status = setCalibrationRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); +} + +/*********************************************************************//** +* @brief +* The handleGetHDCalibrationRecord function handles a request to get the HD +* calibration data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleGetHDCalibrationRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + // Tester must be logged in + if ( TRUE == isTestingActivated() ) + { + result = getCalibrationRecord(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpDataBroadcastIntervalOverrideRequest function handles a + * request to override the syringe pump data broadcast interval. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpDataBroadcastIntervalOverrideRequest( 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 = testSetSyringePumpDataPublishIntervalOverride( (U32)(payload.state.u32) ); + } + else + { + result = testResetSyringePumpDataPublishIntervalOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpOperationRequest function handles a + * request to initiate a syringe pump operation. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpOperationRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(SYRINGE_PUMP_OP_PAYLOAD_T) ) + { + SYRINGE_PUMP_OP_PAYLOAD_T payload; + + memcpy( &payload, message->payload, sizeof(SYRINGE_PUMP_OP_PAYLOAD_T) ); + result = testSyringePumpOperationRequest( payload ); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredRateOverrideRequest function handles a + * request to override the syringe pump measured rate. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredRateOverrideRequest( 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 = testSetSyringePumpMeasuredRateOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredRateOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** +* @brief +* The handleSetHDSystemRecord function handles a request to set the HD +* system data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleSetHDSystemRecord( MESSAGE_T *message ) +{ + BOOL status = FALSE; + U08* payloadPtr = message->payload; + U32 currentMessage; + U32 totalMessages; + U32 payloadLength; + + memcpy(¤tMessage, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&totalMessages, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&payloadLength, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + status = setSystemRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); +} + +/*********************************************************************//** +* @brief +* The handleGetHDSystemRecord function handles a request to get the HD +* system data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleGetHDSystemRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + // Tester must be logged in + if ( TRUE == isTestingActivated() ) + { + result = getSystemRecord(); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredForceOverrideRequest function handles a + * request to override the syringe pump measured force analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredForceOverrideRequest( 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 = testSetSyringePumpMeasuredForceOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredForceOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredSyringeDetectOverrideRequest function handles a + * request to override the syringe pump syringe detected analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( 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 = testSetSyringePumpMeasuredSyringeDetectOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredSyringeDetectOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** +* @brief +* The handleGetHDServiceRecord function handles a request to get the HD +* service data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleGetHDServiceRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + // Tester must be logged in + if ( TRUE == isTestingActivated() ) + { + result = getServiceRecord(); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredHomeOverrideRequest function handles a + * request to override the syringe pump measured home analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredHomeOverrideRequest( 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 = testSetSyringePumpMeasuredHomeOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredHomeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** +* @brief +* The handleSetHDServiceRecord function handles a request to set the HD +* service data record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleSetHDServiceRecord( MESSAGE_T *message ) +{ + BOOL status = FALSE; + U08* payloadPtr = message->payload; + U32 currentMessage; + U32 totalMessages; + U32 payloadLength; + + memcpy(¤tMessage, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&totalMessages, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&payloadLength, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + status = setServiceRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredPositionOverrideRequest function handles a + * request to override the syringe pump measured position. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredPositionOverrideRequest( 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 = testSetSyringePumpMeasuredPositionOverride( (S32)(payload.state.u32) ); + } + else + { + result = testResetSyringePumpMeasuredPositionOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredVolumeOverrideRequest function handles a + * request to override the syringe pump measured volume delivered. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredVolumeOverrideRequest( 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 = testSetSyringePumpMeasuredVolumeOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredVolumeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rbaadbfda2c0b0a51ee830ec5de414604f9a3971e -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision baadbfda2c0b0a51ee830ec5de414604f9a3971e) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -21,16 +21,19 @@ #include "HDCommon.h" #include "AirTrap.h" #include "BloodFlow.h" +#include "BloodPrime.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" +#include "FluidLeak.h" #include "Prime.h" #include "ModePreTreat.h" #include "ModeTreatment.h" #include "MsgQueues.h" #include "NVDataMgmt.h" #include "PresOccl.h" +#include "Rinseback.h" #include "SyringePump.h" #include "Valves.h" @@ -103,7 +106,7 @@ void handleTreatmentParametersFromUI( MESSAGE_T *message ); // MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE -BOOL sendTreatmentParametersResponseMsg( BOOL rejected, U08 *rejectReasons, U32 byteLength ); +BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ); // MSG_ID_UI_SET_UF_VOLUME_PARAMETER void handleUFVolumeSetRequest( MESSAGE_T *message ); @@ -138,9 +141,12 @@ // MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE BOOL sendChangeTreatmentDurationResponse( BOOL accepted, U32 reason, U32 time_min, F32 volume_mL ); +// MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: +void handleTestTreatmentTimeRemainingOverrideRequest( MESSAGE_T *message ); + // MSG_ID_TREATMENT_PARAM_CHANGE_RANGES BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, F32 minUFVol, F32 maxUFVol, U32 minDialRate, U32 maxDialRate ); - + // MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST void handleChangeBloodDialysateRateChangeRequest( MESSAGE_T *message ); @@ -204,6 +210,24 @@ // MSG_ID_HD_START_TREATMENT_RESPONSE BOOL sendStartTreatmentResponse( BOOL accepted, U32 reason ); +// MSG_ID_UI_RINSEBACK_CMD +void handlRinsebackCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RINSEBACK_CMD_RESPONSE +BOOL sendRinsebackCmdResponse( BOOL accepted, U32 rejReason ); + +// MSG_ID_UI_RECIRC_CMD +void handleTreatmentRecircCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RECIRC_CMD_RESPONSE +BOOL sendTreatmentRecircCmdResponse( BOOL accepted, U32 rejReason ); + +// MSG_ID_UI_TX_END_CMD: +void handleTreatmentEndCmd( MESSAGE_T *message ); + +// MSG_ID_HD_RECIRC_CMD_RESPONSE +BOOL sendTreatmentEndCmdResponse( BOOL accepted, U32 rejReason ); + // *********** public DG command functions ********** // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS @@ -263,13 +287,13 @@ BOOL broadcastDialInFlowData( DIALIN_PUMP_STATUS_PAYLOAD_T *dialInData ); // MSG_ID_DIALYSATE_OUT_FLOW_DATA -BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); +BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); // MSG_ID_HD_SYRINGE_PUMP_DATA BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ); // MSG_ID_HD_HEPARIN_DATA_BROADCAST -BOOL broadcastHeparinData( F32 volume ); +BOOL broadcastHeparinData( F32 volume ); // MSG_ID_PRESSURE_OCCLUSION_DATA BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ); @@ -281,7 +305,7 @@ BOOL broadcastTreatmentTime( U32 secsTotTreatment, U32 secsElapsed, U32 secsRemaining ); // MSG_ID_TREATMENT_STATE -BOOL broadcastTreatmentState( U32 subMode, U32 uFState, U32 salineBolusState ); +BOOL broadcastTreatmentState( TREATMENT_STATE_DATA_T payload ); // MSG_ID_PRE_TREATMENT_STATE BOOL broadcastPreTreatmentState( PRE_TREATMENT_STATE_DATA_T *preTreatmentDataPtr ); @@ -298,6 +322,18 @@ // MSG_ID_SALINE_BOLUS_DATA BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ); +// MSG_ID_HD_TREATMENT_STOP_TIMER_DATA +BOOL broadcastTreatmentStopData( U32 timeout, U32 countdown ); + +// MSG_ID_HD_RINSEBACK_PROGRESS +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ); + +// MSG_ID_HD_RECIRC_PROGRESS +BOOL broadcastRecircData( U32 timeout, U32 countdown ); + +// MSG_ID_HD_BLOOD_PRIME_PROGRESS +BOOL broadcastBloodPrimeData( BLOOD_PRIME_DATA_PAYLOAD_T data ); + // MSG_ID_HD_AIR_TRAP_DATA BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel ); @@ -307,9 +343,21 @@ // MSG_ID_HD_DRY_SELF_TEST_PROGRESS BOOL broadcastDrySelfTestTime( U32 timeout, U32 countdown ); +// MSG_ID_HD_FLUID_LEAK_STATE +BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state ); + // MSG_ID_HD_PRIMING_STATUS_DATA BOOL broadcastPrimeData( PRIMING_DATA_PAYLOAD_T *primeDataPtr ); +// MSG_ID_HD_SEND_CALIBRATION_RECORD +BOOL sendHDCalibrationRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* calRcrdAddress ); + +// MSG_ID_HD_SEND_SYSTEM_RECORD +BOOL sendHDSystemRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* sysRcrdAddress ); + +// MSG_ID_Hd_SEND_SERVICE_RECORD +BOOL sendHDServiceRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* srvcRcrdAddress ); + #ifdef EMC_TEST_BUILD // MSG_ID_CAN_ERROR_COUNT BOOL broadcastCANErrorCount( U32 count ); @@ -455,15 +503,6 @@ // MSG_ID_HD_ACCEL_SEND_INTERVAL_OVERRIDE: void handleTestHDAccelBroadcastIntervalOverrideRequest( MESSAGE_T *message ); -// MSG_ID_HD_ACCEL_SET_CALIBRATION: -void handleSetAccelCalibration( MESSAGE_T *message ); - -// MSG_ID_HD_BLOOD_FLOW_SET_CALIBRATION: -void handleSetBloodFlowCalibration( MESSAGE_T *message ); - -// MSG_ID_HD_DIALYSATE_FLOW_SET_CALIBRATION: -void handleSetDialysateFlowCalibration( MESSAGE_T *message ); - // MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER void handleTestSetTreatmentParameter( MESSAGE_T *message ); @@ -505,15 +544,63 @@ // MSG_ID_HD_AIR_TRAP_LEVEL_SENSOR_OVERRIDE void handleSetAirTrapLevelSensorOverrideRequest( MESSAGE_T *message ); +// MSG_ID_HD_FLUID_LEAK_SEND_INTERVAL_OVERRIDE +void handleSetFluidLeakBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE +void handleSetFluidLeakStateDetectorOverrideRequest( 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 ); +// MSG_ID_HD_SET_CALIBRATION_RECORD +void handleSetHDCalibrationRecord( MESSAGE_T *message ); +// MSG_ID_HD_GET_CALIBRATION_RECORD +void handleGetHDCalibrationRecord( MESSAGE_T *message ); + +// MSG_ID_HD_SET_SYSTEM_RECORD +void handleSetHDSystemRecord( MESSAGE_T *message ); + +// MSG_ID_HD_GET_SYSTEM_RECORD +void handleGetHDSystemRecord( MESSAGE_T *message ); + +// MSG_ID_HD_GET_SERVICE_RECORD +void handleGetHDServiceRecord( MESSAGE_T *message ); + +// MSG_ID_HD_SET_SERVICE_RECORD +void handleSetHDServiceRecord( MESSAGE_T *message ); + +// MSG_ID_HD_SET_OP_MODE_REQUEST +void handleTestSetOpModeRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: +void handleTestSyringePumpDataBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_OPERATION_REQUEST: +void handleTestSyringePumpOperationRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_RATE_OVERRIDE: +void handleTestSyringePumpMeasuredRateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_FORCE_OVERRIDE: +void handleTestSyringePumpMeasuredForceOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_SYRINGE_DETECT_OVERRIDE: +void handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_HOME_OVERRIDE: +void handleTestSyringePumpMeasuredHomeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_POSITION_OVERRIDE: +void handleTestSyringePumpMeasuredPositionOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_VOLUME_OVERRIDE: +void handleTestSyringePumpMeasuredVolumeOverrideRequest( MESSAGE_T *message ); + /**@}*/ #endif Index: firmware/App/Tasks/TaskBG.c =================================================================== diff -u -r569bc4e8119455be23c9d57353243e4479f4afcd -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 569bc4e8119455be23c9d57353243e4479f4afcd) +++ firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -57,15 +57,17 @@ { // Wait for UI to come up after power up if ( FALSE == uiCommunicated() ) - { + { +#ifndef BOARD_WITH_NO_HARDWARE #ifndef SIMULATE_UI if ( TRUE == didTimeout( startUICommTimeout, MAX_TIME_FOR_UI_TO_COMMUNICATE_MS ) ) { activateAlarmNoData( ALARM_ID_UI_COMM_POST_FAILED ); } +#endif #endif } - + // Manage the watchdog execWatchdogMgmt(); Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -raaee82db1f0d169e3a51ea8fdba7f57c16b0b986 -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision aaee82db1f0d169e3a51ea8fdba7f57c16b0b986) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -21,7 +21,8 @@ #include "CPLD.h" #include "DGInterface.h" #include "DialInFlow.h" -#include "DialOutFlow.h" +#include "DialOutFlow.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PresOccl.h" #include "SystemComm.h" @@ -61,18 +62,21 @@ // Prevent most processing until UI has started communicating #ifndef SIMULATE_UI - if ( TRUE == uiCommunicated() ) + if ( TRUE == uiCommunicated() ) #endif - { + { +#ifndef BOARD_WITH_NO_HARDWARE // Monitor DG execDGInterfaceMonitor(); // Monitor pressure/occlusion sensors - execPresOccl(); + execPresOccl(); +#endif // Run operation mode state machine execOperationModes(); +#ifndef BOARD_WITH_NO_HARDWARE // Control air trap valve execAirTrapController(); @@ -83,13 +87,19 @@ execDialInFlowController(); // Control dialysate outlet pump - execDialOutFlowController(); + execDialOutFlowController(); +#endif // Manage RTC - execRTC(); - + execRTC(); + + // Manage NVDataMgmt process record state machine + execNVDataMgmtProcessRecord(); + +#ifndef RM46_EVAL_BOARD_TARGET // Manage alarm state - execAlarmMgmt(); + execAlarmMgmt(); +#endif // Manage data to be transmitted to other sub-systems execSystemCommTx(); Index: firmware/source/sys_main.c =================================================================== diff -u -r569bc4e8119455be23c9d57353243e4479f4afcd -r6419179374edcd65da462de84e8aeaefb7e20320 --- firmware/source/sys_main.c (.../sys_main.c) (revision 569bc4e8119455be23c9d57353243e4479f4afcd) +++ firmware/source/sys_main.c (.../sys_main.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) @@ -73,6 +73,7 @@ #include "CPLD.h" #include "DialInFlow.h" #include "DialOutFlow.h" +#include "FluidLeak.h" #include "FPGA.h" #include "InternalADC.h" #include "Interrupts.h" @@ -82,6 +83,7 @@ #include "PresOccl.h" #include "RTC.h" #include "SafetyShutdown.h" +#include "SyringePump.h" #include "SystemComm.h" #include "TaskBG.h" #include "Timers.h" @@ -150,7 +152,6 @@ etpwmSetCmpA( etpwmREG7, etpwmREG7->TBPRD / 3 ); etpwmStartTBCLK(); canInit(); // CAN1 = CAN, re-purposing CAN2 and CAN3 Rx and Tx pins as GPIO - //canEnableloopback( canREG1, External_Lbk ); // TODO - debug code sciInit(); // SCI1 used for PC serial interface, SCI2 used for FPGA serial interface i2cInit(); // I2C used for battery charger interface. dmaEnable(); // Enable DMA @@ -175,6 +176,7 @@ initInternalADC(); initBattery(); initRTC(); + initNVDataMgmt(); // Initialize services initCommBuffers(); initFPGA(); @@ -192,7 +194,9 @@ initBloodFlow(); initDialInFlow(); initDialOutFlow(); + initSyringePump(); initValves(); + initFluidLeak(); // Initialize modes initOperationModes(); // Initialize async interrupt handlers