Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r3e24cbff2cbf0ce9af2e998e6a9a2ed4733bbe27 -r981de1f5228152ec6877aceae3d66ebf5efc7101 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 3e24cbff2cbf0ce9af2e998e6a9a2ed4733bbe27) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 981de1f5228152ec6877aceae3d66ebf5efc7101) @@ -14,9 +14,10 @@ * @date (original) 08-Apr-2020 * ***************************************************************************/ - -#include "DialInFlow.h" + +#include "DialInFlow.h" #include "DGDefs.h" +#include "ModeInitPOST.h" #include "ModeTreatment.h" #include "OperationModes.h" #include "SystemCommMessages.h" @@ -36,8 +37,8 @@ #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. - +#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. + /// States of the treatment reservoir management state machine. typedef enum TreatmentReservoirMgmt_States { @@ -83,14 +84,14 @@ static F32 lgFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; // Load cell filtering data -/// Holds load cell samples for small load cell moving average +/// 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 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 -static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< rolling total - used to calc large load cell moving average +static U32 lgLoadCellReadingsIdx = 0; ///< Index for next sample in large load cell rolling average sample array. +static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< Rolling total - used to calc large load cell moving average. // DG pumps data static F32 dgROPumpFlowRateMlMin = 0.0; ///< Latest RO water flow rate reported by the DG. @@ -108,7 +109,7 @@ 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. +static DG_CMD_RESPONSE_T dgCmdResp[ NUM_OF_DG_COMMANDS ]; ///< Keep the latest DG command response for each command. // ********** private function prototypes ********** @@ -156,9 +157,13 @@ } } - dgCmdResp.commandID = DG_CMD_NONE; - dgCmdResp.rejected = TRUE; - dgCmdResp.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + // initialize DG command response + for ( i = 0; i < NUM_OF_DG_COMMANDS; i++ ) + { + dgCmdResp[ i ].commandID = DG_CMD_NONE; + dgCmdResp[ i ].rejected = TRUE; + dgCmdResp[ i ].rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + } smLoadCellReadingsIdx = 0; smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; @@ -295,11 +300,10 @@ 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 ); + DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); // Signal dialysis sub-mode to capture baseline volume for next reservoir. - setStartReservoirVolume(); + setStartReservoirVolume( inactiveRes ); // Command DG to switch reservoirs cmdSetDGActiveReservoir( inactiveRes ); // Signal dialysis sub-mode to switch reservoirs @@ -456,7 +460,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; @@ -665,6 +669,8 @@ void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ) { DG_RESERVOIR_ID_T res; + DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + BOOL inTreatment = ( MODE_TREA == getCurrentOperationMode() ? TRUE : FALSE ); loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_PRIMARY ].data = res1Primary; loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_BACKUP ].data = res1Backup; @@ -674,8 +680,7 @@ // feed new weight samples into filters and update moving averages for ( res = DG_RESERVOIR_1; res < NUM_OF_DG_RESERVOIRS; res++ ) { - F32 wt = ( res == DG_RESERVOIR_1 ? res1Primary : res2Primary ); - + F32 wt = ( res == DG_RESERVOIR_1 ? res1Primary : res2Primary ); smLoadCellReadingsTotal[ res ] -= smLoadCellReadings[ res ][ smLoadCellReadingsIdx ]; lgLoadCellReadingsTotal[ res ] -= lgLoadCellReadings[ res ][ lgLoadCellReadingsIdx ]; smLoadCellReadings[ res ][ smLoadCellReadingsIdx ] = wt; @@ -745,7 +750,7 @@ void cmdStartDGTrimmerHeater( void ) { dgTrimmerHeaterOn = TRUE; - dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_START_TRIMMER_HEATER ].commandID = DG_CMD_NONE; sendDGStartStopTrimmerHeaterCommand( START_DG_CMD, dgTrimmerTempSet ); } @@ -760,7 +765,7 @@ void cmdStopDGTrimmerHeater( void ) { dgTrimmerHeaterOn = FALSE; - dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_STOP_TRIMMER_HEATER ].commandID = DG_CMD_NONE; sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD, 0 ); } @@ -778,14 +783,36 @@ if ( resID < NUM_OF_DG_RESERVOIRS ) { dgActiveReservoirSet = resID; - dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_SWITCH_RESERVOIR ].commandID = DG_CMD_NONE; sendDGSwitchReservoirCommand( (U32)resID ); } else { - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, (U32)resID ); } } + +/*********************************************************************//** + * @brief + * The cmdChangeDGValveSetting function sends a change valve setting command + * message to the DG. + * @details Inputs: none + * @details Outputs: change valve setting command sent to DG. + * @param valveSettingID ID of valve setting to change to + * @return none + *************************************************************************/ +void cmdChangeDGValveSetting( DG_VALVE_SETTING_ID_T valveSettingID ) +{ + if ( valveSettingID < NUM_OF_DG_VALVE_SETTTINGS ) + { + dgCmdResp[ DG_CMD_VALVE_SETTING ].commandID = DG_CMD_NONE; + sendDGChangeValveSettingCommand( (U32)valveSettingID ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_VALVE_SETTING_ID, (U32)valveSettingID ); + } +} /*********************************************************************//** * @brief @@ -797,7 +824,7 @@ *************************************************************************/ void cmdStartDGFill( U32 fillToVolMl ) { - dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_START_FILL ].commandID = DG_CMD_NONE; dgReservoirFillVolumeTargetSet = fillToVolMl; sendDGFillCommand( fillToVolMl ); } @@ -815,7 +842,7 @@ { DRAIN_RESERVOIR_CMD_PAYLOAD_T payload; - dgCmdResp.commandID = DG_CMD_NONE; + dgCmdResp[ DG_CMD_START_DRAIN ].commandID = DG_CMD_NONE; payload.drainToVolumeML = drainToVolMl; payload.tareLoadCells = tareLoadCell; dgReservoirDrainVolumeTargetSet = drainToVolMl; @@ -840,16 +867,26 @@ * 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 + * @param dgCmdRespPtr pointer to DG command response data record * @return none *************************************************************************/ -void handleDGCommandResponse( U08 *cmdRespPtr ) +void handleDGCommandResponse( DG_CMD_RESPONSE_T *dgCmdRespPtr ) { - memcpy( &dgCmdResp, cmdRespPtr, sizeof( DG_CMD_RESPONSE_T ) ); + if ( dgCmdRespPtr->commandID < NUM_OF_DG_COMMANDS ) + { + if ( DG_CMD_NONE != dgCmdRespPtr->commandID ) + { + memcpy( &dgCmdResp[ dgCmdRespPtr->commandID ], dgCmdRespPtr, sizeof( DG_CMD_RESPONSE_T ) ); + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_COMMAND_RESPONSE_ID, dgCmdRespPtr->commandID ); + } - if ( TRUE == dgCmdResp.rejected ) + if ( TRUE == dgCmdRespPtr->rejected ) { - switch ( dgCmdResp.rejectCode ) + switch ( dgCmdRespPtr->rejectCode ) { case DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER: activateAlarmNoData( ALARM_ID_DG_COMMAND_INVALID_PARAMETER_FAULT ); @@ -870,12 +907,22 @@ * The getDGCommandResponse function gets the latest command response from DG. * @details Inputs: dgCmdResp * @details Outputs: none + * @param commandID id of specific interested command response * @param cmdRespPtr pointer to data record to copy DG command response to - * @return none + * @return TRUE if a specific command response has been received, otherwise FALSE *************************************************************************/ -void getDGCommandResponse( DG_CMD_RESPONSE_T *cmdRespPtr ) +BOOL getDGCommandResponse( U32 commandID, DG_CMD_RESPONSE_T *cmdRespPtr ) { - memcpy( &cmdRespPtr, &dgCmdResp, sizeof( DG_CMD_RESPONSE_T ) ); + BOOL hasCommandResp = FALSE; + + if ( commandID == dgCmdResp[ commandID ].commandID ) + { + hasCommandResp = TRUE; + memcpy( cmdRespPtr, &dgCmdResp[ commandID ], sizeof( DG_CMD_RESPONSE_T ) ); + dgCmdResp[ commandID ].commandID = DG_CMD_NONE; + } + + return hasCommandResp; }