Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rd64ce68a34e7a2fc8cdc67cecb7269dec440305d -rc282822f36836a8127f447c8ac5b8a50e851be63 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision d64ce68a34e7a2fc8cdc67cecb7269dec440305d) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision c282822f36836a8127f447c8ac5b8a50e851be63) @@ -16,7 +16,8 @@ ***************************************************************************/ #include "DialInFlow.h" -#include "ModeInitPOST.h" +#include "DGDefs.h" +#include "ModeInitPOST.h" #include "ModeTreatment.h" #include "OperationModes.h" #include "SystemCommMessages.h" @@ -55,33 +56,34 @@ // ********** private data ********** // DG status -static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. -static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. -static BOOL dgStarted = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop. -static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop the trimmer heater. -static BOOL dgWaterSampled = FALSE; ///< Flag indicates whether we've commanded the DG to sample water. +static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. +static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. +static BOOL dgStarted = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop. +static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. +static BOOL dgWaterSampled = FALSE; ///< Flag indicates whether we have commanded the DG to sample water. -// state machine states +// State machine states /// Current state of treatment mode reservoir management. static TREATMENT_RESERVOIR_MGMT_STATE_T currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; -static U32 resMgmtTimer = 0; ///< used for keeping state time. +static U32 resMgmtTimer = 0; ///< Used for keeping state time. -// DG sensor data -static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. -static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. -static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. -static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. -static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. -static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. -static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. +// DG sensor data +static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. +static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. +static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. +static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. +static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. +static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. +static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. + /// 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 +// 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. @@ -96,15 +98,18 @@ static U32 dgROPumpPressureSetPtPSI = 0; ///< Latest RO pump target pressure reported by the DG. static U32 dgDrainPumpSpeedSetPtRPM = 0; ///< Latest Drain pump target speed reported by the DG. -// reservoir data -static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. -static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. -static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. -static U32 dgReservoirFillVolumeTargetSet = 0; ///< Fill-to volume commanded. -static U32 dgReservoirDrainVolumeTarget = 0; ///< Latest drain-to volume reported by the DG. -static U32 dgReservoirDrainVolumeTargetSet = 0; ///< Drain-to volume commanded. -static U32 resUseTimer = 0; ///< used to track time pumping from active reservoir (for volume used calculation). -static F32 resUseVolumeMl = 0.0; ///< Accumulated volume used from active reservoir. +// Reservoir data +static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. +static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. +static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. +static U32 dgReservoirFillVolumeTargetSet = 0; ///< Fill-to volume commanded. +static U32 dgReservoirDrainVolumeTarget = 0; ///< Latest drain-to volume reported by the DG. +static U32 dgReservoirDrainVolumeTargetSet = 0; ///< Drain-to volume commanded. +static U32 resUseTimer = 0; ///< Used to track time pumping from active reservoir (for volume used calculation). +static F32 resUseVolumeMl = 0.0; ///< Accumulated volume used from active reservoir. + +// DG command response +static DG_CMD_RESPONSE_T dgCmdResp; ///< Used to keep the latest DG command response. // ********** private function prototypes ********** @@ -151,6 +156,11 @@ lgLoadCellReadings[ i ][ j ] = 0.0; } } + + dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp.rejected = TRUE; + dgCmdResp.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + smLoadCellReadingsIdx = 0; smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; @@ -172,6 +182,7 @@ // TODO - make sure DG sensor/state data is coming in timely manner (e.g. load cells s/b every 100 ms) } + /*********************************************************************//** * @brief * The initTreatmentReservoirMgmt function initializes the treatment reservoir @@ -203,14 +214,14 @@ 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 + // 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? } resUseTimer = getMSTimerCount(); - // treatment reservoir mgmt. state machine + // Treatment reservoir mgmt. state machine switch ( currentTrtResMgmtState ) { case TREATMENT_RESERVOIR_MGMT_START_STATE: @@ -243,7 +254,7 @@ break; case TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE: - // delay fill start if we've paused treatment? + // Delay fill start if we have paused treatment? if ( getTreatmentState() == TREATMENT_DIALYSIS_STATE ) { if ( DG_MODE_CIRC == dgOpMode ) @@ -280,22 +291,22 @@ break; case TREATMENT_RESERVOIR_MGMT_WAIT_FOR_RES_SWITCH_STATE: - // reservoir switch during treatment should only occur in this state (i.e. when DG is ready). - // switch reservoirs when active reservoir is spent (i.e. we've pumped fill volume through dialyzer) and DG ready + // Reservoir switch during treatment should only occur in this state (i.e. when DG is ready). + // Switch reservoirs when active reservoir is spent (i.e. we have pumped fill volume through dialyzer) and DG ready if ( ( DG_MODE_CIRC == getDGOpMode() ) && ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getDGSubMode() ) && ( resUseVolumeMl >= (F32)dgReservoirFillVolumeTargetSet ) ) { DG_RESERVOIR_ID_T activeRes = dgActiveReservoirSet; DG_RESERVOIR_ID_T inactiveRes = ( activeRes == DG_RESERVOIR_1 ? DG_RESERVOIR_2 : DG_RESERVOIR_1 ); - // signal dialysis sub-mode to capture baseline volume for next reservoir. + // Signal dialysis sub-mode to capture baseline volume for next reservoir. setStartReservoirVolume(); - // command DG to switch reservoirs + // Command DG to switch reservoirs cmdSetDGActiveReservoir( inactiveRes ); - // signal dialysis sub-mode to switch reservoirs + // Signal dialysis sub-mode to switch reservoirs signalReservoirsSwitched(); resUseVolumeMl = 0.0; - // wait for used reservoir to settle + // Wait for used reservoir to settle resMgmtTimer = getMSTimerCount(); currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; } @@ -304,9 +315,9 @@ case TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE: if ( TRUE == didTimeout( resMgmtTimer, RESERVOIR_SETTLE_TIME_MS ) ) { - // signal dialysis sub-mode to capture final volume of prior reservoir after settling. + // Signal dialysis sub-mode to capture final volume of prior reservoir after settling. setFinalReservoirVolume(); - // reset to start state to restart drain, fill, switch process. + // Reset to start state to restart drain, fill, switch process. currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; } break; @@ -446,7 +457,7 @@ * @param loadCellID ID of load cell to get * @return the current load cell weight in grams *************************************************************************/ -F32 getLoadCellWeightInGrams( LOAD_CELL_T loadCellID ) +F32 getLoadCellWeightInGrams( LOAD_CELL_ID_T loadCellID ) { F32 result = 0.0; @@ -472,7 +483,7 @@ /*********************************************************************//** * @brief * The getReservoirWeightSmallFilter function gets the load cell weight - * of the given reservoir after large (8 sample) filter applied. + * 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 @@ -694,7 +705,7 @@ { dgPrimaryTempSet = primaryHtrTemp; dgTrimmerTempSet = trimmerHtrTemp; - sendDialysateTempTargetsToDG( primaryHtrTemp, trimmerHtrTemp ); + sendDialysateTempTargetsToDG( dgPrimaryTempSet, dgTrimmerTempSet ); } /*********************************************************************//** @@ -735,8 +746,9 @@ *************************************************************************/ void cmdStartDGTrimmerHeater( void ) { - dgTrimmerHeaterOn = TRUE; - sendDGStartStopTrimmerHeaterCommand( START_DG_CMD ); + dgTrimmerHeaterOn = TRUE; + dgCmdResp.commandID = DG_CMD_NONE; + sendDGStartStopTrimmerHeaterCommand( START_DG_CMD, dgTrimmerTempSet ); } /*********************************************************************//** @@ -749,8 +761,9 @@ *************************************************************************/ void cmdStopDGTrimmerHeater( void ) { - dgTrimmerHeaterOn = FALSE; - sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD ); + dgTrimmerHeaterOn = FALSE; + dgCmdResp.commandID = DG_CMD_NONE; + sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD, 0 ); } /*********************************************************************//** @@ -766,7 +779,8 @@ { if ( resID < NUM_OF_DG_RESERVOIRS ) { - dgActiveReservoirSet = resID; + dgActiveReservoirSet = resID; + dgCmdResp.commandID = DG_CMD_NONE; sendDGSwitchReservoirCommand( (U32)resID ); } else @@ -784,7 +798,8 @@ * @return none *************************************************************************/ void cmdStartDGFill( U32 fillToVolMl ) -{ +{ + dgCmdResp.commandID = DG_CMD_NONE; dgReservoirFillVolumeTargetSet = fillToVolMl; sendDGFillCommand( fillToVolMl ); } @@ -802,6 +817,7 @@ { DRAIN_RESERVOIR_CMD_PAYLOAD_T payload; + dgCmdResp.commandID = DG_CMD_NONE; payload.drainToVolumeML = drainToVolMl; payload.tareLoadCells = tareLoadCell; dgReservoirDrainVolumeTargetSet = drainToVolMl; @@ -821,7 +837,50 @@ sendDGSampleWaterCommand(); } +/*********************************************************************//** + * @brief + * The handleDGCommandResponse function processes the latest DG command response. + * @details Inputs: none + * @details Outputs: process command response from DG + * @param cmdRespPtr pointer to DG command response data record + * @return none + *************************************************************************/ +void handleDGCommandResponse( U08 *cmdRespPtr ) +{ + memcpy( &dgCmdResp, cmdRespPtr, sizeof( DG_CMD_RESPONSE_T ) ); + if ( TRUE == dgCmdResp.rejected ) + { + switch ( dgCmdResp.rejectCode ) + { + case DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER: + activateAlarmNoData( ALARM_ID_DG_COMMAND_INVALID_PARAMETER_FAULT ); + break; + + case DG_CMD_REQUEST_REJECT_REASON_NONE: + case DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE: + default: + // Our state machines will detect and handle DG mode out of sync + // TODO Consider a generic handler for all state machine + break; + } + } +} + +/*********************************************************************//** + * @brief + * The getDGCommandResponse function gets the latest command response from DG. + * @details Inputs: dgCmdResp + * @details Outputs: none + * @param cmdRespPtr pointer to data record to copy DG command response to + * @return none + *************************************************************************/ +void getDGCommandResponse( DG_CMD_RESPONSE_T *cmdRespPtr ) +{ + memcpy( &cmdRespPtr, &dgCmdResp, sizeof( DG_CMD_RESPONSE_T ) ); +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/