Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -26,6 +26,7 @@ #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PersistentAlarm.h" +#include "SystemComm.h" #include "SystemCommMessages.h" #include "Timers.h" @@ -41,30 +42,36 @@ #define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. -#define DIALYSATE_TEMP_PERSISTENCE_PERIOD ( 3 * MS_PER_SECOND ) ///< Persistence period for dialysate temperature alarm. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 2.0F ///< Dialysate temperature out of target tolerance C. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. +#define DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C 46.0F ///< Dialysate high safety temperature limit in C. +#define DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature high safety timeout in milliseconds. +#define DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C 42.0F ///< Dialysate low safety temperature limit in C. +#define DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature low safety timeout in milliseconds. -#define DIALYSATE_TEMP_RECOVERY_TOLERANCE_C 2.0F ///< Dialysate temperature recovery tolerance in degree C. -#define DIALYSATE_TEMP_TOLERANCE_C 4.0F ///< Dialysate temperature tolerance in degree C. -#define DIALYSATE_TEMP_HIGH_LIMIT_C 42.0F ///< Dialysate high temperature limit in degree C. -#define DIALYSATE_TEMP_LOW_LIMIT_C 33.0F ///< Dialysate low temperature limit in degree C. +#define LOAD_CELL_DATA_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Load cell freshness timeout (in ms). // ********** private data ********** +static const U32 DIP_LOAD_CELL_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +static const U32 DIP_TEMPERATURE_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +static const U32 DIP_RESERVOIRS_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +static const U32 DIP_DG_OP_MODE_DATA_MESSAGE_ALARM_THRESHOLD = ((2 * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); // 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 dgStartCommandSent = FALSE; ///< Flag indicates command to start DG has been sent. -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 DG_OP_MODE_T dgCurrentOpMode; ///< Current DG operation mode. +static U32 dgSubMode; ///< Current state (sub-mode) of current DG operation mode. +static BOOL dgStartCommandSent; ///< Flag indicates command to start DG has been sent. +static BOOL dgStarted; ///< Flag indicates whether we have commanded the DG to start or stop. +static BOOL dgTrimmerHeaterOn; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. // State machine states static U32 timeStartMS = 0; // TODO is this needed? // DG sensor data -static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. +static F32 dgDialysateTemp; ///< Dialysate temperature reported by the DG. static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. 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 dgTrimmerTempSet; ///< Trimmer heater target temperature commanded. static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. /// Measured weight from load cells. @@ -83,10 +90,18 @@ // DG Dialysate flow rate static F32 dgDialysateFlowRateMlMin = 0.0; ///< Latest dialysate flow rate reported by the DG. static BOOL dgDialysateFlowDataFreshFlag = FALSE; ///< Flag to signal the execDialInFlowMonitor() to process fresh flow rate data +static BOOL dgLoadCellDataFreshFlag = FALSE; ///< Flag to signal the handleLoadCellReadingsFromDG() to process fresh load cell data +static BOOL dgDialysateTemperatureDataFreshFlag = FALSE; ///< Flag to signal the handleTemperatureReadingsFromDG() to process fresh temperature data +static BOOL dgReservoirsDataFreshFlag = FALSE; ///< Flag to signal the handleDGReservoirData() to process fresh reservoirs data +static BOOL dgOpModeDataFreshFlag = FALSE; ///< Flag to signal the handleDGOpMode() to process fresh dg op mode data +static U32 loadcellDataMessageFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh load cell data message is received +static U32 temperatureDataMessageFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh temperature data message is received +static U32 reservoirsDataMessageFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh reservoirs data message is received +static U32 dgOpModeDataMessageFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh dg op mode data message is received // 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 DG_RESERVOIR_ID_T dgActiveReservoir; ///< Latest active reservoir reported by the DG. +static DG_RESERVOIR_ID_T dgActiveReservoirSet; ///< Active reservoir commanded. // TODO remove below variables static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. @@ -96,13 +111,15 @@ static DG_DISINFECT_UI_STATES_T disinfectsStatus; ///< DG disinfects status. static DG_MIXING_RATIOS_T dgMixingRatios; ///< DG mixing ratios. +static HEATERS_DATA_T dgHeatersData; ///< DG heaters data. // 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 ********** static void checkDGRestart( void ); +static void checkDGTrimmerHeaterStatus( void ); /*********************************************************************//** * @brief @@ -115,29 +132,37 @@ { U32 i, j; - dgStarted = FALSE; - dgTrimmerHeaterOn = FALSE; - dgTrimmerTempSet = 0.0; - dgActiveReservoirSet = DG_RESERVOIR_2; - dgReservoirFillVolumeTargetSet = 0; + dgStarted = FALSE; + dgTrimmerHeaterOn = FALSE; + dgTrimmerTempSet = 0.0F; + dgActiveReservoirSet = DG_RESERVOIR_2; + dgActiveReservoir = DG_RESERVOIR_2; + dgReservoirFillVolumeTargetSet = 0; dgReservoirDrainVolumeTargetSet = 0; + dgDialysateTemp = 0.0F; + dgCurrentOpMode = DG_MODE_INIT; + dgSubMode = 0; + dgStartCommandSent = FALSE; + dgDialysateFlowRateMlMin = 0.0F; + dgDialysateFlowDataFreshFlag = FALSE; // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { - loadCellWeightInGrams[ i ].data = 0.0; - loadCellWeightInGrams[ i ].ovInitData = 0.0; - loadCellWeightInGrams[ i ].ovData = 0.0; - loadCellWeightInGrams[ i ].override = 0; + loadCellWeightInGrams[ i ].data = 0.0F; + loadCellWeightInGrams[ i ].ovInitData = 0.0F; + loadCellWeightInGrams[ i ].ovData = 0.0F; + loadCellWeightInGrams[ i ].override = 0; } // initialize reservoirs weights for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) { - lgFilteredReservoirWeightInGrams[ i ] = 0.0; + lgFilteredReservoirWeightInGrams[ i ] = 0.0F; + for ( j = 0; j < SIZE_OF_LARGE_LOAD_CELL_AVG; j++ ) { - lgLoadCellReadings[ i ][ j ] = 0.0; - lgLoadCellBackupReadings[ i ][ j ] = 0.0; + lgLoadCellReadings[ i ][ j ] = 0.0F; + lgLoadCellBackupReadings[ i ][ j ] = 0.0F; } } @@ -149,15 +174,53 @@ dgCmdResp[ i ].rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; } - lgLoadCellReadingsIdx = 0; - lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; - lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; - lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; - lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + lgLoadCellReadingsIdx = 0; + lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0F; + lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0F; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0F; + lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0F; - initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, DIALYSATE_TEMP_PERSISTENCE_PERIOD, DIALYSATE_TEMP_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS, DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ); + + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); + + initPersistentAlarm( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, LOAD_CELL_DATA_TIMEOUT_MS, LOAD_CELL_DATA_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_NEW_DIALYSATE_TEMPERATURE_DATA_MESSAGE_NOT_RECEIVE, LOAD_CELL_DATA_TIMEOUT_MS, LOAD_CELL_DATA_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_NEW_RESERVOIRS_DATA_MESSAGE_NOT_RECEIVE, LOAD_CELL_DATA_TIMEOUT_MS, LOAD_CELL_DATA_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_HD_NEW_DG_OPERATION_MODE_MESSAGE_NOT_RECEIVE, LOAD_CELL_DATA_TIMEOUT_MS, LOAD_CELL_DATA_TIMEOUT_MS ); } + +/**********************************************************************//** + * @brief + * The checkDGDataFreshness function checks the condition + * for triggering an alarm if the DG fresh data is not received for 2 seconds. + * @details Inputs: none + * @details Outputs: an alarm is triggered or an alarm condition is cleared + * @param alarm ID of alarm to check + * @param flag to signal the fresh data processing + * @return None + *************************************************************************/ +void checkDGDataFreshness( ALARM_ID_T alarmID, BOOL *dgFreshDataFlag ) +{ + if ( TRUE == *dgFreshDataFlag ) + { + *dgFreshDataFlag = FALSE; + checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); + } + else + { // Alarm if not receiving DG fresh data message in timely manner + if ( TRUE == isDGCommunicating() ) + { + checkPersistentAlarm( alarmID, TRUE, 0.0, 0.0 ); + } + else + { + checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); + } + } +} /*********************************************************************//** * @brief @@ -169,10 +232,24 @@ *************************************************************************/ void execDGInterfaceMonitor( void ) { - // TODO - make sure DG sensor/state data is coming in timely manner (e.g. load cells s/b every 100 ms) + // Trigger alarm if not receiving new load cell data message in timely manner + /*checkDGDataFreshness( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, &dgLoadCellDataFreshFlag ); - // Check to see if DG has restarted + // Trigger alarm if not receiving new dialysate temperature data message in timely manner + checkDGDataFreshness( ALARM_ID_HD_NEW_DIALYSATE_TEMPERATURE_DATA_MESSAGE_NOT_RECEIVE, &dgDialysateTemperatureDataFreshFlag ); + + // Trigger alarm if not receiving new reservoirs data message in timely manner + checkDGDataFreshness( ALARM_ID_HD_NEW_RESERVOIRS_DATA_MESSAGE_NOT_RECEIVE, &dgReservoirsDataFreshFlag ); + + // Trigger alarm if not receiving new reservoirs data message in timely manner + checkDGDataFreshness( ALARM_ID_HD_NEW_DG_OPERATION_MODE_MESSAGE_NOT_RECEIVE, &dgOpModeDataFreshFlag ); + + // Check to see if DG has restarted*/ + checkDGRestart(); + + // Check the status of the trimmer heater + checkDGTrimmerHeaterStatus(); } /*********************************************************************//** @@ -282,6 +359,74 @@ return result; } + +/*********************************************************************//** + * @brief + * The getLoadCellDataFreshFlag function returns a flag to indicate + * if the load cell data message reported by the DG is fresh or stale data. + * @details Inputs: dgLoadCellDataFreshFlag + * @details Outputs: dgLoadCellDataFreshFlag + * @return T/F flag to indicate fresh/stale status of load cell data. + *************************************************************************/ +BOOL getLoadCellDataFreshFlag( void ) +{ + BOOL result = dgLoadCellDataFreshFlag; + + dgLoadCellDataFreshFlag = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief + * The getTemperatureDataFreshFlag function returns a flag to indicate + * if the temperature data message reported by the DG is fresh or stale data. + * @details Inputs: dgDialysateTemperatureDataFreshFlag + * @details Outputs: dgDialysateTemperatureDataFreshFlag + * @return T/F flag to indicate fresh/stale status of load cell data. + *************************************************************************/ +BOOL getTemperatureDataFreshFlag( void ) // DN-19AUG2022 +{ + BOOL result = dgDialysateTemperatureDataFreshFlag; + + dgDialysateTemperatureDataFreshFlag = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief + * The getReservoirsDataFreshFlag function returns a flag to indicate + * if the reservoirs data message reported by the DG is fresh or stale data. + * @details Inputs: dgReservoirsDataFreshFlag + * @details Outputs: dgReservoirsDataFreshFlag + * @return T/F flag to indicate fresh/stale status of load cell data. + *************************************************************************/ +BOOL getReservoirsDataFreshFlag( void ) // DN-22AUG2022 +{ + BOOL result = dgReservoirsDataFreshFlag; + + dgReservoirsDataFreshFlag = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief + * The getDGOpModeDataFreshFlag function returns a flag to indicate + * if the dg op mode data message reported by the DG is fresh or stale data. + * @details Inputs: dgOpModeDataFreshFlag + * @details Outputs: dgOpModeDataFreshFlag + * @return T/F flag to indicate fresh/stale status of load cell data. + *************************************************************************/ +BOOL getDgOpModeDataFreshFlag( void ) // DN-22AUG2022 +{ + BOOL result = dgOpModeDataFreshFlag; + + dgOpModeDataFreshFlag = FALSE; + + return result; +} /*********************************************************************//** * @brief @@ -358,26 +503,26 @@ /*********************************************************************//** * @brief - * The getDialysateTemperature function gets the latest dialysate temperature. - * @details Inputs: dgDialysateTemp + * The getDGDisinfectsStates function returns the DG disinfects readings. + * @details Inputs: none * @details Outputs: none - * @return the current dialysate temperature + * @return the current DG disinfects readings *************************************************************************/ -F32 getDialysateTemperature( void ) +DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) { - return dgDialysateTemp; + return disinfectsStatus; } /*********************************************************************//** * @brief - * The getDGDisinfectsStates function returns the DG disinfects readings. - * @details Inputs: none + * The getDialysateTemperature function gets the latest dialysate temperature. + * @details Inputs: dgDialysateTemp * @details Outputs: none - * @return the current DG disinfects readings + * @return the current dialysate temperature *************************************************************************/ -DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +F32 getDialysateTemperature( void ) { - return disinfectsStatus; + return dgDialysateTemp; } /*********************************************************************//** @@ -420,7 +565,7 @@ * @return none *************************************************************************/ void setDGOpMode( U32 opMode, U32 subMode ) -{ +{ if ( opMode < NUM_OF_DG_MODES ) { dgCurrentOpMode = (DG_OP_MODE_T)opMode; @@ -429,7 +574,9 @@ else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_OPERATING_MODE, opMode ); - } + } + + dgOpModeDataFreshFlag = TRUE; } /*********************************************************************//** @@ -443,9 +590,11 @@ * @return none *************************************************************************/ void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ) -{ - dgDialysateTemp = temp1; - dgRedundantDialysateTemp = temp2; +{ + dgDialysateTemp = temp1; + dgRedundantDialysateTemp = temp2; + + dgDialysateTemperatureDataFreshFlag = TRUE; } /*********************************************************************//** @@ -460,7 +609,7 @@ * @return none *************************************************************************/ void setDGReservoirsData( DG_RESERVOIR_ID_T resID, U32 fillVol, U32 drainVol ) -{ +{ if ( resID < NUM_OF_DG_RESERVOIRS ) { dgActiveReservoir = resID; @@ -470,7 +619,9 @@ else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_RESERVOIR_ID, resID ); - } + } + + dgReservoirsDataFreshFlag = TRUE; } /*********************************************************************//** @@ -538,6 +689,8 @@ // Update Dialysis sub-mode with new reservoir volumes updateReservoirVolumes( res1Primary, res2Primary ); + + dgLoadCellDataFreshFlag = TRUE; } /*********************************************************************//** @@ -565,9 +718,22 @@ *************************************************************************/ void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ) { - memcpy( &dgMixingRatios, &ratios, sizeof(DG_MIXING_RATIOS_T) ); + memcpy( &dgMixingRatios, &ratios, sizeof( DG_MIXING_RATIOS_T ) ); } +/*********************************************************************//** + * @brief + * The setDGHeatersData function sets heaters data that has been read from DG. + * @details Inputs: none + * @details Outputs: dgHeatersData + * @param data which is a pointer to the received heaters data + * @return none + *************************************************************************/ +void setDGHeatersData( HEATERS_DATA_T *data ) +{ + memcpy( &dgHeatersData, data, sizeof( HEATERS_DATA_T ) ); +} + /*********************************************************************//** * @brief * The cmdSetDGDialysateHeatingParams function sends the dialysate heating @@ -627,7 +793,7 @@ dgTrimmerHeaterOn = TRUE; dgCmdResp[ DG_CMD_START_TRIMMER_HEATER ].commandID = DG_CMD_NONE; - sendDGStartStopTrimmerHeaterCommand( START_DG_CMD, dgTrimmerTempSet ); + sendDGStartStopTrimmerHeaterCommand( START_DG_CMD ); } /*********************************************************************//** @@ -643,7 +809,7 @@ dgTrimmerHeaterOn = FALSE; dgCmdResp[ DG_CMD_STOP_TRIMMER_HEATER ].commandID = DG_CMD_NONE; - sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD, 0 ); + sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD ); } /*********************************************************************//** @@ -950,43 +1116,28 @@ * @brief * The checkDialysateTemperature function checks the dialysate temperature * reported by DG and alarm if temperature is out of range. - * @details Inputs: dgTrimmerTempSet, dgDialysateTemp, dgRedundantDialysateTemp - * @details Outputs: alarm if dialysate temperature is out of accepted range + * @details Inputs: dgTrimmerTempSet, dgDialysateTemp + * @details Outputs: none * @return none *************************************************************************/ void checkDialysateTemperature( void ) { - BOOL const dialysateHighTemp = ( ( ( dgDialysateTemp - dgTrimmerTempSet ) > DIALYSATE_TEMP_TOLERANCE_C ) || - ( dgDialysateTemp > DIALYSATE_TEMP_HIGH_LIMIT_C ) ); + BOOL isTDiTempAboveHighSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ? TRUE : FALSE ); + F32 TDiHigh = dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isTDiTempAboveDialysateTarget = ( TDiHigh >= dgDialysateTemp ? TRUE : FALSE ); + F32 TDiLow = dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; + BOOL isTDiTempBelowDialysateTarget = ( TDiLow >= dgDialysateTemp ? TRUE : FALSE ); - BOOL const dialysateLowTemp = ( ( ( dgTrimmerTempSet - dgDialysateTemp ) > DIALYSATE_TEMP_TOLERANCE_C ) || - ( dgDialysateTemp < DIALYSATE_TEMP_LOW_LIMIT_C ) ); - - BOOL const dialysateTempRecovered = fabs( dgDialysateTemp - dgTrimmerTempSet ) < DIALYSATE_TEMP_RECOVERY_TOLERANCE_C ? TRUE : FALSE; - #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dialysateHighTemp ) ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dgTrimmerTempSet, dgDialysateTemp ); - } + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_HIGH_SAFETY_RANGE, isTDiTempAboveHighSafety, dgDialysateTemp, DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C ); + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_OUT_OF_LOW_SAFETY_RANGE, isTDiTempAboveLowSafety, dgDialysateTemp, DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C ); - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dialysateLowTemp ) ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dgTrimmerTempSet, dgDialysateTemp ); - } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH, dialysateHighTemp ) ) - { - clearAlarmCondition( ALARM_ID_DIALYSATE_TEMPERATURE_HIGH ); - } - - if ( TRUE == isPersistentAlarmConditionCleared( ALARM_ID_DIALYSATE_TEMPERATURE_LOW, dialysateTempRecovered ) ) - { - clearAlarmCondition( ALARM_ID_DIALYSATE_TEMPERATURE_LOW ); - } + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTDiTempAboveDialysateTarget, dgDialysateTemp, TDiHigh ); + checkPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, isTDiTempBelowDialysateTarget, dgDialysateTemp, TDiLow ); } } @@ -1018,7 +1169,29 @@ } } +/*********************************************************************//** + * @brief + * The checkDGTrimmerHeaterStatus function checks to see the status of the + * trimmer heater and set them according to the status of the trimmer heater flag. + * @details Inputs: dgTrimmerHeaterOn + * @details Outputs: none + * @return none + *************************************************************************/ +static void checkDGTrimmerHeaterStatus( void ) +{ + U32 trimmerState = dgHeatersData.trimmerHeaterState; + if ( ( TRUE == dgTrimmerHeaterOn ) && ( HEATER_EXEC_STATE_OFF == trimmerState ) ) + { + cmdStartDGTrimmerHeater(); + } + else if ( ( FALSE == dgTrimmerHeaterOn ) && ( trimmerState != HEATER_EXEC_STATE_OFF ) ) + { + cmdStopDGTrimmerHeater(); + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -71,35 +71,6 @@ F32 tempRsrvrEndFillTrimmer; ///< Temperature reservoir end fill trimmer in C. } DG_RESERVOIRS_DATA_PAYLOAD_T; -/// Payload record structure for DG temperature sensors data message. -typedef struct -{ - F32 inletPrimaryHeater; ///< Inlet primary heater temperature sensor - F32 outletPrimaryHeater; ///< Outlet primary heater temperature sensor - F32 conductivitySensor1; ///< Conductivity sensor 1 temperature sensor - F32 conductivitySensor2; ///< Conductivity sensor 2 temperature sensor - F32 outletRedundant; ///< Outlet redundant temperature sensor - F32 inletDialysate; ///< Inlet dialysate temperature sensor - F32 primaryHeaterThermocouple; ///< Primary heaters thermocouple sensor - F32 trimmerHeaterThermocouple; ///< Trimmer heater thermocouple sensor - F32 priamyHeaterColdjunction; ///< Primary heaters cold junction temperature sensor - F32 trimmerHeaterColdjunction; ///< Trimmer heater cold junction temperature sensor - F32 primaryHeaterInternal; ///< Primary heaters internal temperature (calculated from thermocouple and cold junction) - F32 trimmerHeaterInternal; ///< Trimmer heater internal temperature (calculated from thermocouple and cold junction) - F32 fpgaBoard; ///< FPGA board temperature sensor - F32 loadCellA1B1; ///< Load cell A1/B1 temperature sensor - F32 loadCellA2B2; ///< Load cell A2/B2 temperature sensor - F32 internalTHDORTD; ///< THDo RTD channel temperature sensor - F32 internalTDIRTD; ///< TDI RTD channel temperature sensor - F32 internalCondSnsrTemp; ///< Conductivity Sensor internal temperature sensor - U32 primaryThermoCoupleRaw; ///< Primary heaters thermocouple raw ADC value - U32 primaryColdjuncRaw; ///< Primary heaters cold junction raw ADC value - U32 trimmerThermoCoupleRaw; ///< Trimmer heater thermocouple raw ADC value - U32 trimmerColdjuncRaw; ///< Trimmer heater cold junction raw ADC value - S32 cond1Raw; ///< Conductivity sensor 1 raw temperature ADC value - S32 cond2Raw; ///< Conductivity sensor 2 raw temperature ADC value -} TEMPERATURE_SENSORS_DATA_T; - /// Payload record structure for a drain reservoir command message. typedef struct { @@ -149,13 +120,15 @@ DG_RESERVOIR_ID_T getDGInactiveReservoir( void ); BOOL hasDGCompletedReservoirSwitch( void ); BOOL getDialysateFlowDataFreshFlag( void ); +BOOL getLoadCellDataFreshFlag( void ); F32 getDGDialysateFlowRateLMin( void ); F32 getLoadCellWeight( LOAD_CELL_ID_T loadCellID ); F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ); F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ); F32 getReservoirBackupWeightLargeFilter( DG_RESERVOIR_ID_T resID ); F32 getDialysateTemperature( void ); DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ); +F32 getDialysateTemperature( void ); DG_MIXING_RATIOS_T getDGMixingRatios( void ); void setDGOpMode( U32 opMode, U32 subMode ); @@ -165,6 +138,7 @@ void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); void setDGDisinfectsStates( DG_DISINFECT_UI_STATES_T states ); void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ); +void setDGHeatersData( HEATERS_DATA_T *data ); void cmdSetDGDialysateHeatingParams( DG_CMD_DIALYSATE_HEATING_PARAMS_T heatingParams ); void cmdStartDG( void ); Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r8d829681af297f6638bc7b0933094305fc9f2b8e -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 8d829681af297f6638bc7b0933094305fc9f2b8e) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -67,9 +67,11 @@ #define VENOUS_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_ND_MAX_MMHG ( 300.0F ) ///< Maximum venous pressure reading (in mmHg) when not dialyzing. +#define VENOUS_PRESSURE_OCCL_OFFSET_MMHG ( 50.0F ) ///< Venous pressure occlusion threshold offset from max alarm limit (in mmHg). #define PSI_TO_MMHG ( 51.7149F ) ///< Conversion factor for converting PSI to mmHg. +// The new arterial pressure sensor is the same as the venous pressure sensor #define VENOUS_PRESSURE_NORMAL_OP 0 ///< Venous pressure status bits indicate normal operation. #define VENOUS_PRESSURE_CMD_MODE 1 ///< Venous pressure status bits indicate sensor in command mode. #define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). @@ -92,7 +94,8 @@ #define EMPTY_SALINE_BAG_THRESHOLD_MMHG -300.0F ///< 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. -#define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. +#define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. +#define VEN_OCCL_ALARM_PERSISTENCE 100 ///< Alarm persistence period for venous occlusion alarm. /// Measured arterial pressure is filtered w/ 10 second moving average for pressure compensation of flow. #define SIZE_OF_LONG_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) @@ -129,7 +132,6 @@ /// Interval (in ms) at which to publish pressure/occlusion data to CAN bus. static OVERRIDE_U32_T presOcclDataPublishInterval = { PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL, 0, 0 }; static OVERRIDE_F32_T arterialPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured arterial pressure. -static OVERRIDE_F32_T arterialPressureOffset = {0.0, 0.0, 0.0, 0 }; ///< Calculated arterial pressure offset. static OVERRIDE_F32_T venousPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured venous pressure. static OVERRIDE_U32_T bloodPumpOcclusion = {0, 0, 0, 0 }; ///< Measured blood pump occlusion pressure. static F32 longFilteredArterialPressure; ///< Measured arterial pressure after long (10 s) filter. @@ -198,6 +200,7 @@ initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, 0, VEN_OCCL_ALARM_PERSISTENCE ); lastArterialPressureReadCtr = 0; lastVenousPressureReadCtr = 0; @@ -397,95 +400,44 @@ static void convertInlinePressures( void ) { F32 rawArterialPres = 0.0; - U08 artPresAlarm = 0; U08 artPresStatus = 0; F32 venPresPSI = 0.0; U16 fpgaVenPres = getFPGAVenousPressure(); U16 venPres = fpgaVenPres & 0x3FFF; // 14-bit data U08 venPresStatus = (U08)( fpgaVenPres >> SHIFT_14_BITS ); // High 2 bits is status code for venous pressure U08 venReadCtr = getFPGAVenousPressureReadCounter(); + U16 fpgaArtPres = getFPGADVTArterialPressure(); + U16 artPres = fpgaArtPres & 0x3FFF; + rawArterialPres = (F32)artPres; + artPresStatus = (U08)( fpgaArtPres >> SHIFT_14_BITS ); -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) ) - { - U16 fpgaArtPres = getFPGADVTArterialPressure(); - U16 artPres = fpgaArtPres & 0x3FFF; - rawArterialPres = (F32)artPres; - artPresStatus = (U08)( fpgaArtPres >> SHIFT_14_BITS ); - } - else -#endif - { - U32 fpgaArtPres = getFPGAArterialPressure(); - S32 artPres = (S32)( fpgaArtPres & MASK_OFF_U32_MSB ) - ARTERIAL_PRESSURE_CONVERSION_OFFSET; // Subtract 2^23 from low 24 bits to get signed reading - rawArterialPres = (F32)artPres; - artPresAlarm = (U08)( fpgaArtPres >> SHIFT_24_BITS ); // High byte is alarm code for arterial pressure - } -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) ) -#endif + if ( ARTERIAL_PRESSURE_NORMAL_OP == artPresStatus ) { - if ( ARTERIAL_PRESSURE_NORMAL_OP == artPresStatus ) - { - U08 artReadCtr = getFPGADVTArterialPressureReadCounter(); + U08 artReadCtr = getFPGADVTArterialPressureReadCounter(); - // Check for stale venous pressure reading - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr ) ) ) - { - activateAlarmNoData( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR ); - } - // Record arterial pressure sensor read counter for next time around - lastArterialPressureReadCtr = artReadCtr; - - arterialPressure.data = ( (F32)(rawArterialPres - ARTERIAL_PRESSURE_OFFSET) * - (ARTERIAL_PRESSURE_MAX_PSI - ARTERIAL_PRESSURE_MIN_PSI) / (F32)ARTERIAL_PRESSURE_SCALE ) + ARTERIAL_PRESSURE_MIN_PSI; - arterialPressure.data = arterialPressure.data * PSI_TO_MMHG; - } - else if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT, TRUE ) ) + // Check for stale venous pressure reading + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr ) ) ) { - activateAlarmNoData( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT ); + activateAlarmNoData( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR ); } - else - { - resetPersistentAlarmTimer( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT ); - } - } + // Record arterial pressure sensor read counter for next time around + lastArterialPressureReadCtr = artReadCtr; -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_DVT_ARTERIAL_PRESSURE_SENSOR ) != SW_CONFIG_ENABLE_VALUE ) -#endif + arterialPressure.data = ( (F32)(rawArterialPres - ARTERIAL_PRESSURE_OFFSET) * + (ARTERIAL_PRESSURE_MAX_PSI - ARTERIAL_PRESSURE_MIN_PSI) / (F32)ARTERIAL_PRESSURE_SCALE ) + ARTERIAL_PRESSURE_MIN_PSI; + arterialPressure.data = arterialPressure.data * PSI_TO_MMHG; + } + else if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT, TRUE ) ) { - if ( 0 == artPresAlarm ) - { - U08 artReadCtr = getFPGAArterialPressureReadCounter(); - U08 artErrorCtr = getFPGAArterialPressureErrorCounter(); - - // Check for stale arterial pressure reading - // TODO I think we should check the change of the error count not if it is greater than 0? - if ( FALSE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr || artErrorCtr > 0 ) ) ) - { - arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( rawArterialPres / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ) + - getF32OverrideValue( &arterialPressureOffset ); - } - else - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, (U32)artErrorCtr ); - } - // Record arterial pressure sensor read counter for next time around - lastArterialPressureReadCtr = artReadCtr; - } - else - { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT, (U32)artPresAlarm ) - } - } + activateAlarmNoData( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT ); } + else + { + resetPersistentAlarmTimer( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT ); + } + // Check for stale venous pressure reading if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, ( lastVenousPressureReadCtr == venReadCtr ) ) ) { @@ -495,7 +447,7 @@ lastVenousPressureReadCtr = venReadCtr; // Convert venous pressure to PSI and then mmHg - venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX_PSI - VENOUS_PRESSURE_MIN_PSI) / (F32)VENOUS_PRESSURE_SCALE ) + + venPresPSI = ( (F32)( venPres - VENOUS_PRESSURE_OFFSET ) * ( VENOUS_PRESSURE_MAX_PSI - VENOUS_PRESSURE_MIN_PSI ) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN_PSI; // Convert venous pressure from PSI to mmHg if sensor status is normal @@ -645,8 +597,7 @@ #endif { // Check venous pressure is in range - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres > VENOUS_PRESSURE_MAX_MMHG ) || - TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres < VENOUS_PRESSURE_MIN_MMHG ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, ( venPres > VENOUS_PRESSURE_MAX_MMHG || venPres < VENOUS_PRESSURE_MIN_MMHG ) ) ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); } @@ -690,6 +641,7 @@ { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, VENOUS_PRESSURE_ND_MAX_MMHG ); } + isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); } else { // Reset persistence if alarm is out of scope @@ -725,7 +677,13 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif { - // Range check occlusion sensor + F32 venPres = getMeasuredVenousPressure(); + HD_OP_MODE_T hdMode = getCurrentOperationMode(); + U32 hdSubMode = getCurrentSubMode(); + BOOL txMode = ( MODE_TREA == hdMode ? TRUE : FALSE ); + BOOL ptxMode = ( MODE_PRET == hdMode && hdSubMode > HD_PRE_TREATMENT_CART_INSTALL_STATE ? TRUE : FALSE ); + + // Range check occlusion sensor (OB) if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, outOfRange ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl ); @@ -735,8 +693,7 @@ // and setOcclusionInstallLevel has been called. if ( MODE_PRET == getCurrentOperationMode() ) { - - if ( getPreTreatmentSubState() > HD_PRE_TREATMENT_CART_INSTALL_STATE && getDrySelfTestsState() > DRY_SELF_TESTS_START_STATE ) + if( getPreTreatmentSubState() > HD_PRE_TREATMENT_CART_INSTALL_STATE && getDrySelfTestsState() > DRY_SELF_TESTS_START_STATE ) { // Check for occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) @@ -746,7 +703,6 @@ } } } - // Check for occlusion in Treatment modes where pumps are moving else if ( MODE_TREA == getCurrentOperationMode() ) { @@ -766,6 +722,21 @@ { clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); } + + // Check for venous occlusion + if ( ( TRUE == txMode || TRUE == ptxMode ) && + ( venPres > getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ) + VENOUS_PRESSURE_OCCL_OFFSET_MMHG ) ) + { + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, TRUE ) ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, venPres ); + } + } + else + { + clearAlarmCondition( ALARM_ID_HD_VENOUS_LINE_OCCLUSION ); + isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_LINE_OCCLUSION, FALSE ); + } } } @@ -1219,49 +1190,4 @@ return result; } -/*********************************************************************//** - * @brief - * The testSetBloodPumpOcclusionOverride function overrides the arterial - * pressure offset. - * @details Inputs: none - * @details Outputs: arterialPressureOffset - * @param value override arterial pressure offset with - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetArterialPressureOffsetOverride( F32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - arterialPressureOffset.ovData = value; - arterialPressureOffset.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetArterialPressureOffsetOverride function resets the override of the - * arterial pressure offset. - * @details Inputs: none - * @details Outputs: arterialPressureOffset - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetArterialPressureOffsetOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - arterialPressureOffset.override = OVERRIDE_RESET; - arterialPressureOffset.ovData = arterialPressureOffset.ovInitData; - } - - return result; -} - /**@}*/ Index: firmware/App/Drivers/Battery.c =================================================================== diff -u -rfb1673d2282822995ed233f3e9ea5dfb0567780d -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Drivers/Battery.c (.../Battery.c) (revision fb1673d2282822995ed233f3e9ea5dfb0567780d) +++ firmware/App/Drivers/Battery.c (.../Battery.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -7,8 +7,8 @@ * * @file Battery.c * -* @author (last) Dara Navaei -* @date (last) 24-May-2022 +* @author (last) Michael Garthwaite +* @date (last) 07-Sep-2022 * * @author (original) Quang Nguyen * @date (original) 24-Feb-2021 @@ -145,7 +145,15 @@ if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &relStateOfCharge_pct ) ) { - batteryRelStateOfCharge_pct = (U32)relStateOfCharge_pct; + batteryRelStateOfCharge_pct.data = (U32)relStateOfCharge_pct; + if ( getBatteryRemainingPercent() < BATTERY_PACK_MIN_CHARGE_PCT ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED, getBatteryRemainingPercent() ); + } + else + { + clearAlarmCondition( ALARM_ID_HD_BATTERY_PACK_ERROR_DETECTED ); + } } if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REM_CAPACITY_CMD, &remCapacity_mAh ) ) Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -rcd057da54a204e4577ed217a8325314f7e21dde1 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision cd057da54a204e4577ed217a8325314f7e21dde1) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -41,7 +41,7 @@ #define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. #define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. -#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 3 * MS_PER_SECOND ) ///< Delay 3 seconds then check for syringe pump prime occlusion. +#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay 3 seconds then check for syringe pump prime occlusion. #define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. #define NORMALIZED_PRESSURE_SELF_TEST_TIME ( 4 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize in ms. @@ -232,14 +232,14 @@ F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_ENABLE_VALUE ) + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) ) { - useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ? TRUE : FALSE ); + useHeparin = FALSE; } else #endif { - useHeparin = FALSE; + useHeparin = ( ( bolusVol > 0.0 ) || ( hepRate > 0.0 ) ? TRUE : FALSE ); } currentNoCartSelfTestsState = NO_CART_SELF_TESTS_START_STATE; @@ -340,7 +340,7 @@ } else { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CART_SELF_TEST_TIMEOUT, currentNoCartSelfTestsState ); +// SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_NO_CART_SELF_TEST_TIMEOUT, currentNoCartSelfTestsState ); } } } @@ -403,7 +403,6 @@ *************************************************************************/ void execDrySelfTests( void ) { - // execute dry self-tests state machine switch ( currentDrySelfTestsState ) { @@ -566,8 +565,6 @@ *************************************************************************/ void execWetSelfTests( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WET_SELF_TEST ) == SW_CONFIG_ENABLE_VALUE ) { @@ -637,11 +634,6 @@ // Self-tests flags should be handled by now, reset if flags not handled with current state resetSelfTestsFlags(); - - if ( SELF_TEST_STATUS_FAILED == result ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRE_TREATMENT_WET_LC_TEST_FAILURE, currentWetSelfTestsState ); - } } /*********************************************************************//** @@ -740,7 +732,7 @@ if ( TRUE == useHeparin ) { - if ( TRUE == isSyringePumpStopped() ) + if ( ( isSyringePumpHome() != TRUE ) && ( TRUE == isSyringePumpStopped() ) ) { retractSyringePump(); } @@ -915,10 +907,10 @@ { state = DRY_SELF_TESTS_OCCLUSION_SENSORS_STATE; } - else - { - activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); - } +// else +// { +// activateAlarmNoData( ALARM_ID_INSTALL_NEW_CARTRIDGE ); +// } if ( TRUE == doesAlarmStatusIndicateStop() ) { @@ -1171,8 +1163,8 @@ { if ( TRUE == isSyringePumpPrimed() ) { + syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 1 second has elapsed state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; - syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 3 seconds has elapsed } else { @@ -1185,6 +1177,10 @@ { seekSyringePlunger(); } + else + { + retractSyringePump(); + } } } } @@ -1401,7 +1397,6 @@ BUBBLE_STATUS_T const ADVBubbleStatus = getBubbleStatus( ADV ); - if ( BUBBLE_NOT_DETECTED == ADVBubbleStatus ) { #ifndef _RELEASE_ @@ -1539,8 +1534,8 @@ * @brief * The handleWetSelfTestFirstDisplacementVerifyState function checks the load cell * readings and FMD integrated volume after the first dialysate displacement. - * @details Inputs: settleStartTime, reservoirVolume[], reservoirs' weights - * @details Outputs: verify correctness of dialysate flow meter and load cell + * @details Inputs: settleStartTime, fmdIntegratedVolume + * @details Outputs: none * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementVerifyState( void ) @@ -1737,16 +1732,19 @@ * @brief * The handleWetSelfTestStoppedState function handles the stopped wet self-tests * operation. - * @details Inputs: none - * @details Outputs: none + * @details Inputs: selfTestsResumeRequested + * @details Outputs: selfTestsResumeRequested * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestStoppedState( void ) { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_STOPPED_STATE; + doorClosedRequired( FALSE, FALSE ); + if ( TRUE == selfTestsResumeRequested ) { + doorClosedRequired( TRUE, TRUE ); selfTestsResumeRequested = FALSE; state = WET_SELF_TESTS_START_STATE; } Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -78,7 +78,7 @@ #define SCI2_RECEIVE_DMA_REQUEST 28 ///< Serial port 2 receive DMA request line. #define SCI2_TRANSMIT_DMA_REQUEST 29 ///< Serial port 2 transmit DMA request line. -#define MAX_COMM_ERROR_RETRIES 5 ///< Maximum consecutive FPGA communication error retries. +#define MAX_COMM_ERROR_RETRIES 10 ///< Maximum consecutive FPGA communication error retries. #define FPGA_INPUT_VOLTAGE_SCALE 3.0F ///< FPGA source and aux voltage. #define FPGA_PVN_VOLTAGE_SCALE 1.0F ///< FPGA pvn voltage. Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -53,10 +53,9 @@ #define MSG_NOT_ACKED_TIMEOUT_MS 150 ///< Maximum time for a Denali message that requires ACK to be ACK'd -#define MSG_NOT_ACKED_TIMEOUT_MS_INIT 5000 ///< Maximum time for a Denali message that requires ACK to be ACK'd on the INIT state for the first (UI version request) message of the POST -#define MSG_NOT_ACKED_MAX_RETRIES 3 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm +#define MSG_NOT_ACKED_MAX_RETRIES 20 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm #define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time - + #pragma pack(push, 1) /// Record for transmitted message that is pending acknowledgment from receiver. @@ -96,6 +95,7 @@ COMM_BUFFER_IN_CAN_UI_BROADCAST, COMM_BUFFER_IN_CAN_PC, }; +//extern U32 loadcellDataMessageFreshStatusCounter = 0; ///< Counter use to trigger alarm if no fresh load cell data message is received - DN-22AUG2022 static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. @@ -111,10 +111,6 @@ static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in static volatile BOOL uiDidCommunicate = FALSE; ///< Has UI every sent a message -#ifdef EMC_TEST_BUILD - static U32 badCANCount; // Test code in support of EMC testing -#endif - // ********** private function prototypes ********** static void clearCANXmitBuffers( void ); @@ -227,12 +223,16 @@ /*********************************************************************//** * @brief * The uiCommunicated function determines whether the UI has communicated. - * @details Inputs: uiDidCommunicate + * @details Inputs: none * @details Outputs: none * @return TRUE if UI has communicated since power up, FALSE if not *************************************************************************/ BOOL uiCommunicated( void ) -{ +{ +#ifdef SIMULATE_UI + uiDidCommunicate = TRUE; +#endif + return uiDidCommunicate; } @@ -257,7 +257,7 @@ * @return none *************************************************************************/ void execSystemCommRx( void ) -{ +{ // Parse messages from comm buffers and queue them processIncomingData(); @@ -526,8 +526,9 @@ * @brief * The processIncomingData function parses out messages from the Input * Comm Buffers and adds them to the Received Message Queue. - * @details Inputs: Input Comm Buffers - * @details Outputs: Parsed message(s) added to Received Message Queue + * @details Inputs: none + * @details Outputs:hdIsOnlyCANNode, rcvMsg, dgIsCommunicating, + * timeOfLastDGCheckIn * @return none *************************************************************************/ static void processIncomingData( void ) @@ -572,8 +573,8 @@ // Blank the new message record blankMessageInWrapper( &rcvMsg ); // Copy message header portion of message data to the new message - memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); - dataPtr += sizeof(MESSAGE_HEADER_T); + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof( MESSAGE_HEADER_T ) ); + dataPtr += sizeof( MESSAGE_HEADER_T ); // Copy message payload portion of message data to the new message memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); dataPtr += rcvMsg.msg.hdr.payloadLen; @@ -591,10 +592,6 @@ else if ( -1 == msgSize ) // Candidate message with bad CRC found? { badCRCDetected = TRUE; -#ifdef EMC_TEST_BUILD - badCANCount++; - broadcastCANErrorCount( badCANCount ); -#endif getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // Consume sync byte so we can re-sync messagesInBuffer = TRUE; // Keep processing this buffer } // Looks like there is a complete message in the comm buffer @@ -702,7 +699,7 @@ { BOOL isThereMsgRcvd = TRUE; // Assume TRUE at first to get into while loop MESSAGE_WRAPPER_T message; - + while ( TRUE == isThereMsgRcvd ) { // See if any messages received @@ -729,10 +726,6 @@ } else // CRC failed { -#ifdef EMC_TEST_BUILD - badCANCount++; - broadcastCANErrorCount( badCANCount ); -#endif checkTooManyBadMsgCRCs(); } } @@ -750,7 +743,9 @@ static void checkForCommTimeouts( void ) { if ( TRUE == uiDidCommunicate ) - { + { + HD_OP_MODE_T opMode = getCurrentOperationMode(); + if ( TRUE == didTimeout( timeOfLastUICheckIn, UI_COMM_TIMEOUT_IN_MS ) ) { #ifndef _RELEASE_ @@ -761,13 +756,21 @@ } } - if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) + // Only alarm on DG comm loss while in the treatment workflow + if ( MODE_PRET == opMode || MODE_TREA == opMode || MODE_POST == opMode ) { + if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) + { #ifndef RUN_WITHOUT_DG - activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); - dgIsCommunicating = FALSE; + activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); + dgIsCommunicating = FALSE; #endif + } } + else // Otherwise clear the alarm + { + clearAlarm( ALARM_ID_DG_COMM_TIMEOUT ); + } } } @@ -878,13 +881,7 @@ // Find expired messages pending ACK for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) { // Pending ACK expired? - U32 timeoutPeriod = MSG_NOT_ACKED_TIMEOUT_MS; // set the timeout as default - - if ( MODE_INIT == getCurrentOperationMode() ) - { // change it to longer timeout if the HD is in INIT state - timeoutPeriod = MSG_NOT_ACKED_TIMEOUT_MS_INIT; - } - if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, timeoutPeriod ) ) ) + if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) { // If retries left, reset and resend pending message if ( pendingAckList[ i ].retries > 0 ) { // Re-queue message for transmit @@ -979,6 +976,10 @@ case MSG_ID_DG_VERSION: handleDGVersionResponse( message ); + break; + + case MSG_ID_DG_HEATERS_DATA: + handleDGHeatersData( message ); break; case MSG_ID_DG_TEMPERATURE_DATA: Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -43,7 +43,10 @@ #include "Valves.h" #include "WatchdogMgmt.h" #include "HDDefs.h" +#include "TaskPriority.h" +#include "TaskPriority.h" + /** * @addtogroup SystemCommMessages * @{ @@ -62,9 +65,9 @@ #pragma pack(pop) // ********** private data ********** - static BOOL testerLoggedIn = FALSE; ///< Flag indicates whether an external tester (connected PC) has sent a valid login message. static volatile U16 nextSeqNo = 1; ///< Value of sequence number to use for next transmitted message. + /// List of message IDs that are requested not to be transmitted. static BLOCKED_MSGS_DATA_T blockedMessagesForXmit = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1569,10 +1572,9 @@ * @details Inputs: none * @details Outputs: DG start/stop trimmer heater command msg constructed and queued. * @param start TRUE indicates start heater, FALSE indicates stop heater - * @param trimmerHtrTemp target temperature for trimmer heater * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start, F32 trimmerHtrTemp ) +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ) { BOOL result; MESSAGE_T msg; @@ -1581,11 +1583,9 @@ // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD; - msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( F32 ); + msg.hdr.payloadLen = sizeof( BOOL ); memcpy( payloadPtr, &start, sizeof( BOOL ) ); - payloadPtr += sizeof( BOOL ); - memcpy( payloadPtr, &trimmerHtrTemp, sizeof( F32 ) ); // 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_DG, ACK_REQUIRED ); @@ -2003,35 +2003,6 @@ } -#ifdef EMC_TEST_BUILD -/*********************************************************************//** - * @brief - * The broadcastCANErrorCount function handles the CAN error count - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -BOOL broadcastCANErrorCount( U32 count ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_CAN_ERROR_COUNT; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &count, 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; -} -#endif - // *********************************************************************** // **************** Message Handling Helper Functions ******************** // *********************************************************************** @@ -2270,7 +2241,6 @@ { BOOL result; MESSAGE_T msg; - U08 *payloadPtr = msg.payload; // Create a message record blankMessage( &msg ); @@ -2339,17 +2309,36 @@ *************************************************************************/ void handleLoadCellReadingsFromDG( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof(LOAD_CELL_READINGS_PAYLOAD_T) ) + if ( message->hdr.payloadLen == sizeof( LOAD_CELL_DATA_T ) ) { - LOAD_CELL_READINGS_PAYLOAD_T payload; + LOAD_CELL_DATA_T payload; - memcpy( &payload, message->payload, sizeof(LOAD_CELL_READINGS_PAYLOAD_T) ); - setNewLoadCellReadings( payload.res1PrimaryLoadCell, payload.res1BackupLoadCell, payload.res2PrimaryLoadCell, payload.res2BackupLoadCell ); + memcpy( &payload, message->payload, sizeof( LOAD_CELL_DATA_T ) ); + setNewLoadCellReadings( payload.loadCellA1inGram, payload.loadCellA2inGram, payload.loadCellB1inGram, payload.loadCellB2inGram ); } } /*********************************************************************//** * @brief + * The handleDGHeatersData function handles the heaters data reading from DG. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDGHeatersData( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof( HEATERS_DATA_T ) ) + { + HEATERS_DATA_T payload; + + memcpy( &payload, message->payload, sizeof( HEATERS_DATA_T ) ); + setDGHeatersData( &payload ); + } +} + +/*********************************************************************//** + * @brief * The handleDGTemperatureData function handles a temperature readings * broadcast message from the DG. * @details Inputs: none @@ -2363,13 +2352,13 @@ { TEMPERATURE_SENSORS_DATA_T payload; - memcpy( &payload, message->payload, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); - setDialysateTemperatureReadings( payload.inletDialysate, payload.outletRedundant ); - } - // TODO - what to do if invalid payload length? - // TODO - how to know if DG stops sending these? -} - + memcpy( &payload, message->payload, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); + setDialysateTemperatureReadings( payload.inletDialysate, payload.outletRedundant ); + } + // TODO - what to do if invalid payload length? + // TODO - how to know if DG stops sending these? +} + /*********************************************************************//** * @brief * The handleDialysateFlowData function handles dialysate flow data broadcast @@ -3624,38 +3613,6 @@ /*********************************************************************//** * @brief - * The handleHDSetArterialPressureOffsetRequest function handles a request to - * set the arterial pressure offset. - * @details Inputs: none - * @details Outputs: message handled - * @param message a pointer to the message to handle - * @return none - *************************************************************************/ -void handleHDSetArterialPressureOffsetRequest( 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 = testSetArterialPressureOffsetOverride( payload.state.f32 ); - } - else - { - result = testResetArterialPressureOffsetOverride(); - } - } - - // Respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/*********************************************************************//** - * @brief * The handleTestBloodPumpRotorMeasuredSpeedOverrideRequest function handles a request to * override the measured blood pump rotor speed (RPM). * @details Inputs: none @@ -5191,6 +5148,7 @@ if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) { memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + if ( FALSE == payload.reset ) { result = testSetBatteryRemainingPercentOverride( payload.state.u32 ); @@ -7131,6 +7089,30 @@ } /*********************************************************************//** + * @brief + * The sendRequestForDGResendAlarms function sends out the HD request for + * DG re-send all active alarms. + * @details Inputs: none + * @details Outputs: DG alarms re-send request msg constructed and queued + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendRequestForDGResendAlarms( void ) +{ + BOOL result; + MESSAGE_T msg; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_REQUEST_DG_ALARMS; + msg.hdr.payloadLen = 0; + + // 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_DG, ACK_REQUIRED ); + + return result; +} + +/*********************************************************************//** * @brief * The handleGetHDUsageInfoRecord function handles a request to get the HD * usage information record. @@ -7286,15 +7268,15 @@ /*********************************************************************//** * @brief - * The handleSendBloodLeakEmbeddedModeCommandResponse function sends out + * The sendBloodLeakEmbeddedModeCommandResponse function sends out * the blood leak embedded mode command response. * @details Inputs: none * @details Outputs: blood leak embedded mode command response msg constructed and queued * @param responseLen: the length of the buffer * @param response: pointer to the response buffer * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL handleSendBloodLeakEmbeddedModeCommandResponse( U32 responseLen, U08* response ) +BOOL sendBloodLeakEmbeddedModeCommandResponse( U32 responseLen, U08* response ) { BOOL result; MESSAGE_T msg; @@ -7316,6 +7298,30 @@ } /*********************************************************************//** +* @brief +* The handleResendAllAlarmsCommand function handles a request to re-send +* all active HD alarms. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleResendAllAlarmsCommand( MESSAGE_T* message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + handleResendActiveAlarmsRequest(); + result = TRUE; + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** * @brief * The sendDGServiceModeRequest function constructs a service mode request msg * to the DG and queues the msg for transmit on the appropriate CAN channel. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r94dab74a6432263dc4569e0cf8f9fa0b01bf1917 -r80a6638b362f5f613c0665200023d181f614d1bc --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 94dab74a6432263dc4569e0cf8f9fa0b01bf1917) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 80a6638b362f5f613c0665200023d181f614d1bc) @@ -139,7 +139,10 @@ void handleUIPOSTFinalResult( MESSAGE_T *message ); // MSG_ID_LOAD_CELL_READINGS -void handleLoadCellReadingsFromDG( MESSAGE_T *message ); +void handleLoadCellReadingsFromDG( MESSAGE_T *message ); + +// MSG_ID_DG_HEATERS_DATA +void handleDGHeatersData( MESSAGE_T *message ); // MSG_ID_DG_TEMPERATURE_DATA: void handleDGTemperatureData( MESSAGE_T *message ); @@ -372,7 +375,7 @@ BOOL sendDGStartStopCommand( BOOL start ); // MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD -BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start, F32 trimmerHtrTemp ); +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ); // MSG_ID_DG_SAMPLE_WATER_CMD BOOL sendDGSampleWaterCommand( SAMPLE_WATER_CMD_T cmd ); @@ -432,11 +435,9 @@ void handleSetHDSoftwareConfigRecord( MESSAGE_T *message ); -#ifdef EMC_TEST_BUILD -// MSG_ID_CAN_ERROR_COUNT -BOOL broadcastCANErrorCount( U32 count ); -#endif - +// MSG_ID_HD_REQUEST_DG_ALARMS +BOOL sendRequestForDGResendAlarms( void ); + // *********** public test support message functions ********** // MSG_TESTER_LOG_IN @@ -810,8 +811,11 @@ void handleSetBloodLeakEmbeddedModeCommand( MESSAGE_T* message ); // MSG_ID_HD_SEND_BLOOD_LEAK_EMB_MODE_RESPONSE -BOOL handleSendBloodLeakEmbeddedModeCommandResponse( U32 responseLen, U08* response ); +BOOL sendBloodLeakEmbeddedModeCommandResponse( U32 responseLen, U08* response ); +// MSG_ID_HD_SEND_ALARMS_COMMAND +void handleResendAllAlarmsCommand( MESSAGE_T* message ); + /**@}*/ #endif