Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -26,6 +26,7 @@ #include "SystemCommMessages.h" #include "TaskPriority.h" #include "Timers.h" +#include "Utilities.h" /** * @addtogroup BloodLeak @@ -79,7 +80,9 @@ #define BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX 3 ///< Blood leak embedded mode stop write to FIFO index. #define BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX 4 ///< Blood leak embedded mode active high command index. #define BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX 0 ///< Blood leak embedded mode request Rx to read index. -#define BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE 10 ///< Blood leak embedded mode command queue maximum size. +#define BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE 12 ///< Blood leak embedded mode command queue maximum size. +#define BLOOD_LEAK_EMB_MODE_ZERO_CMD_RQRD_Q 5 ///< Blood leak embedded mode zero command required queue count. +#define BLOOD_LEAK_EMB_MODE_NUM_OF_RETRIES 3 ///< Blood leak embedded mode number of retries to enqueue. /// Defined states for the blood leak detector state machine. typedef enum BloodLeakStates @@ -163,6 +166,7 @@ static U08 bloodLeakEmbModeCmdQFrontIndex; ///< Blood leak embedded mode command queue front index. static U08 bloodLeakEmbModeCmdQCount; ///< Blood leak embedded mode command queue count. static BOOL bloodLeakEmbModeHasZeroBeenRqustd; ///< Blood leak embedded mode flag to indicate zero has been requested. +static U32 bloodLeakEmbModeCmdEnqueueCount; ///< Blood leak embedded mode command enqueue count. // ********** private function prototypes ********** @@ -184,6 +188,7 @@ static void enqueueEmbModeCmd( U08 cmd ); static U08 dequeueEmbModeCmd( void ); static BOOL isEmbModeCmdQueueEmpty( void ); +static U32 getAvailableEmbModeQueueCount( void ); /*********************************************************************//** * @brief @@ -192,7 +197,7 @@ * @details Outputs: bloodLeakState, bloodLeakStatus, bloodLeakSelfTestStatus, * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence * bloodLeakDataPublicationTimerCounter, bloodLeakEmbModeHasZeroBeenRqustd - * bloodLeakEmbModeSubstate + * bloodLeakEmbModeSubstate, bloodLeakEmbModeCmdEnqueueCount * bloodLeakPersistenceCtr, bloodLeakSignalEmbModeReq, * bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeOpsStartTime, bloodLeakEmbModeRespBuffer, * bloodLeakEmbModeRespIndex, bloodLeakExitNormalRequested, @@ -226,6 +231,7 @@ bloodLeakEmbModeCmdQRearIndex = 0; bloodLeakEmbModeCmdQCount = 0; bloodLeakEmbModeHasZeroBeenRqustd = FALSE; + bloodLeakEmbModeCmdEnqueueCount = 0; // Set the blood leak embedded mode command queue to zero memset( bloodLeakEmbModeCmdQ, 0x0, BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE ); @@ -322,20 +328,33 @@ * @brief * The zeroBloodLeak function requests that the Blood Leak Detector be * zeroed. - * @details Inputs: none - * @details Outputs: bloodLeakCmd.cmdZeroRequested, bloodLeakUARTCmdIndex - * @return none + * @details Inputs: bloodLeakEmbModeCmdEnqueueCount + * @details Outputs: bloodLeakCmd.cmdZeroRequested, bloodLeakUARTCmdIndex, + * bloodLeakEmbModeCmdEnqueueCount + * @return TRUE if the zero commands were successfully queued otherwise, FALSE *************************************************************************/ -void zeroBloodLeak( void ) +BOOL zeroBloodLeak( void ) { - bloodLeakEmbModeHasZeroBeenRqustd = TRUE; + BOOL status = TRUE; - // Enqueue the zero and self test sequence (Z->G->Z->Q->T) - enqueueEmbModeCmd( Z_EMB_MODE_CMD ); - enqueueEmbModeCmd( G_EMB_MODE_CMD ); - enqueueEmbModeCmd( Z_EMB_MODE_CMD ); - enqueueEmbModeCmd( Q_EMB_MODE_CMD ); - enqueueEmbModeCmd( T_EMB_MODE_CMD ); + if ( getAvailableEmbModeQueueCount() >= BLOOD_LEAK_EMB_MODE_ZERO_CMD_RQRD_Q ) + { + status = TRUE; + bloodLeakEmbModeHasZeroBeenRqustd = TRUE; + + // Enqueue the zero and self test sequence (Z->G->Z->Q->T) + enqueueEmbModeCmd( Z_EMB_MODE_CMD ); + enqueueEmbModeCmd( G_EMB_MODE_CMD ); + enqueueEmbModeCmd( Z_EMB_MODE_CMD ); + enqueueEmbModeCmd( Q_EMB_MODE_CMD ); + enqueueEmbModeCmd( T_EMB_MODE_CMD ); + } + else if ( ++bloodLeakEmbModeCmdEnqueueCount > BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_ENQUEUE_FAILURE ) + } + + return status; } /*********************************************************************//** @@ -401,15 +420,13 @@ } else if ( ( TRUE == bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].isCmdRespRdy ) && ( BLOOD_LEAK_EMB_MODE_FAIL_ASCII == cmdResp ) ) { - if ( bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + if ( ++bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { // Enqueue the commands to set the embedded mode and request the set point of the blood leak sensor // Since set point was requested in the init function as well, both are requested here because we have to be // in the embedded mode first enqueueEmbModeCmd( CS_EMB_MODE_CMD ); enqueueEmbModeCmd( D_EMB_MODE_CMD ); - - bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount++; } else { @@ -424,7 +441,8 @@ if ( ( getCurrentOperationMode() != MODE_INIT ) && ( TRUE == isEmbModeReady ) ) { - state = BLOOD_LEAK_CHECK_SET_POINT_STATE; + bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount = 0; + state = BLOOD_LEAK_CHECK_SET_POINT_STATE; } return state; @@ -446,11 +464,9 @@ if ( ( bloodLeakSetPoint != bloodLeakCalRecord.setPoint ) && ( TRUE == isCommandRespReady ) ) { - if ( bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + if ( ++bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { enqueueEmbModeCmd( D_EMB_MODE_CMD ); - - bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount++; } else { @@ -464,7 +480,8 @@ } else if ( TRUE == isCommandRespReady ) { - state = BLOOD_LEAK_INIT_STATE; + bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount = 0; + state = BLOOD_LEAK_INIT_STATE; } return state; @@ -551,19 +568,30 @@ if ( FALSE == hasCmdSqncFailed ) { - state = BLOOD_LEAK_NORMAL_STATE; + // Done with zero sequence, transition to other states + bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount = 0; + bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; + state = BLOOD_LEAK_NORMAL_STATE; } else if ( bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { - // Zero sequence failed, try again - zeroBloodLeak(); + if ( TRUE == zeroBloodLeak() ) + { + // Check if the zero sequence has been successfully enqueued + // If the command retry of one of the commands in the zero sequence failed, it means all of them have failed + // So in this condition only the Z command is checked + bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount++; + } } else { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { + bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; + state = BLOOD_LEAK_INIT_STATE; + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED, failedCmd ); } } @@ -748,6 +776,10 @@ // Clear the response buffer to able to receive fresh data memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_INVALID_EMB_MODE_CMD_SELECTED, bloodLeakEmbModeRqstedCmd ) + break; } } @@ -807,6 +839,10 @@ } bloodLeakUARTCmdIndex++; break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_INVALID_EMB_MODE_CMD_SELECTED, bloodLeakEmbModeRqstedCmd ) + break; } if ( ( bloodLeakEmbModeRqstedCmd != CS_EMB_MODE_CMD ) && ( bloodLeakUARTCmdIndex - 1 > BLOOD_LEAK_EMB_MODE_RESET_INDEX ) && @@ -1163,19 +1199,23 @@ { BLOOD_LEAK_DATA_T data; - data.bloodLeakStatus = (U32)getBloodLeakStatus(); - data.bloodLeakState = (U32)bloodLeakState; - data.bloodLeakZeroStatusCounter = (U32)getFPGABloodLeakZeroStatusCounter(); - data.bloodLeakCounter = (U32)getFPGABloodLeakCounter(); - data.bloodLeakZeroedStatus = (U32)getFPGABloodLeakZeroedStatus(); - data.bloodLeakDetectSetPoint = (U32)getFPGABloodLeakDetectSetPoint(); - data.bloodLeakDetectLevel = (U32)getFPGABloodLeakDetectLevel(); - data.bloodLeakStCount = (U32)getFPGABloodLeakStCount(); - data.bloodLeakLEDIntesity = (U32)getFPGABloodLeakLEDIntensity(); - data.bloodLeakRegisterCounter = (U32)getFPGABloodLeakRegisterCounter(); + data.bloodLeakStatus = (U32)getBloodLeakStatus(); + data.bloodLeakState = (U32)bloodLeakState; + data.bloodLeakDetectSetPoint = bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandResp; + data.bloodLeakDetectLevel = bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].commandResp; + data.bloodLeakLEDIntesity = bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].commandResp; broadcastData( MSG_ID_HD_BLOOD_LEAK_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( BLOOD_LEAK_DATA_T ) ); bloodLeakDataPublicationTimerCounter = 0; + + if ( ( bloodLeakState >= BLOOD_LEAK_INIT_STATE ) && ( FALSE == bloodLeakEmbModeHasZeroBeenRqustd ) ) + { + // Once the previous data was broadcast, and the system is not in init and blood leak zero request has not been set, enqueue the data + // to be queried and read again. The data is queried here to make sure there is a second of time in between the queries for I, V, and D + enqueueEmbModeCmd( I_EMB_MODE_CMD ); + enqueueEmbModeCmd( V_EMB_MODE_CMD ); + enqueueEmbModeCmd( D_EMB_MODE_CMD ); + } } } @@ -1353,7 +1393,20 @@ return isEmpty; } +/*********************************************************************//** + * @brief + * The getAvailableEmbModeQueueCount function returns the available embedded + * mode queue count. + * @details Inputs: bloodLeakEmbModeCmdQCount + * @details Outputs: none + * @return Current available embedded mode queue count + *************************************************************************/ +static U32 getAvailableEmbModeQueueCount( void ) +{ + return BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE - bloodLeakEmbModeCmdQCount; +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/BloodLeak.h =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -46,29 +46,24 @@ { U32 bloodLeakStatus; ///< Blood leak detector status U32 bloodLeakState; ///< Blood leak detector state - U32 bloodLeakZeroStatusCounter; ///< Blood leak zero status counter - U32 bloodLeakCounter; ///< Blood leak counter - U32 bloodLeakZeroedStatus; ///< Blood leak zeroed status U32 bloodLeakDetectSetPoint; ///< Blood leak detect set point U32 bloodLeakDetectLevel; ///< Blood leak detect level - U32 bloodLeakStCount; ///< Blood leak st count U32 bloodLeakLEDIntesity; ///< Blood leak LED intensity - U32 bloodLeakRegisterCounter; ///< Blood leak register counter } BLOOD_LEAK_DATA_T; // ********** public function prototypes ********** void initBloodLeak( void ); void execBloodLeak( void ); void execBloodLeakEmbModeCommand( void ); -void zeroBloodLeak( void ); +BOOL zeroBloodLeak( void ); void exitBloodLeakNormalState( void ); SELF_TEST_STATUS_T execBloodLeakSelfTest( void ); BLOOD_LEAK_STATUS_T getBloodLeakStatus( void ); -SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ); +SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ); BOOL testSetBloodLeakDataPublishIntervalOverride( U32 value ); BOOL testResetBloodLeakDataPublishIntervalOverride( void ); Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rcd9254008b61520e5c62059329f80a84efc0366d -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision cd9254008b61520e5c62059329f80a84efc0366d) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -24,7 +24,7 @@ #include "ModeInitPOST.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" -#include "OperationModes.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemComm.h" #include "SystemCommMessages.h" @@ -57,13 +57,13 @@ 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. - +// DG status +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? @@ -107,13 +107,16 @@ 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. +static DG_SERVICE_AND_USAGE_DATA_T dgServiceAndUsageData; ///< DG service and usage 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 @@ -229,7 +232,7 @@ void execDGInterfaceMonitor( void ) { // 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 ); + /*checkDGDataFreshness( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, &dgLoadCellDataFreshFlag ); // 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 ); @@ -240,8 +243,12 @@ // Trigger alarm if not receiving new DG op mode message in timely manner checkDGDataFreshness( ALARM_ID_HD_NEW_DG_OPERATION_MODE_MESSAGE_NOT_RECEIVE, &dgOpModeDataFreshFlag ); - // Check to see if DG has restarted + // Check to see if DG has restarted*/ + checkDGRestart(); + + // Check the status of the trimmer heater + checkDGTrimmerHeaterStatus(); } /*********************************************************************//** @@ -406,6 +413,22 @@ /*********************************************************************//** * @brief + * The getReservoirWeight function gets the load cell weight of a given reservoir. + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get weight for + * @return the current weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ) +{ + LOAD_CELL_ID_T lc = ( DG_RESERVOIR_1 == resID ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); + F32 wt = getLoadCellWeight( lc ); + + return wt; +} + +/*********************************************************************//** + * @brief * The getReservoirBackupWeightLargeFilter function gets the backup load cell weight * of the given reservoir after large (32 sample) filter applied. * @details Inputs: lgFilteredReservoirWeightInGrams[] @@ -427,26 +450,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; } /*********************************************************************//** @@ -464,18 +487,17 @@ /*********************************************************************//** * @brief - * The getReservoirWeight function gets the load cell weight of a given reservoir. - * @details Inputs: loadCellWeightInGrams[] + * The getHDVersionDGServiceAndUsageData function copies the HD version of + * the DG service and usage data into the provided buffer. + * @details Inputs: dgServiceAndUsageData * @details Outputs: none - * @param resID ID of reservoir to get weight for - * @return the current weight of the given reservoir in grams + * @param data which is a pointer of type DG_SERVICE_AND_USAGE_DATA_T that + * is the provided buffer + * @return none *************************************************************************/ -F32 getReservoirWeight( DG_RESERVOIR_ID_T resID ) +void getHDVersionDGServiceAndUsageData( DG_SERVICE_AND_USAGE_DATA_T* data ) { - LOAD_CELL_ID_T lc = ( DG_RESERVOIR_1 == resID ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); - F32 wt = getLoadCellWeight( lc ); - - return wt; + memcpy( data, &dgServiceAndUsageData, sizeof( DG_SERVICE_AND_USAGE_DATA_T ) ); } /*********************************************************************//** @@ -642,11 +664,56 @@ *************************************************************************/ 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 setHDVersionDGServiceRecord function sets the HD version of the DG + * service record. + * @details Inputs: none + * @details Outputs: dgServiceAndUsageData + * @param data which is a pointer to the received HD version of the DG service + * record + * @return none + *************************************************************************/ +void setHDVersionDGServiceRecord( HD_VERSION_DG_SERVICE_RECORD_T* data ) +{ + dgServiceAndUsageData.isDGServiceRecordAvailable = TRUE; + memcpy( &dgServiceAndUsageData.dgServiceRecord, data, sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ); +} + +/*********************************************************************//** + * @brief + * The setHDVersionDGUsageInfo function sets the HD version of the DG + * usage information. + * @details Inputs: none + * @details Outputs: dgServiceAndUsageData + * @param data which is a pointer to the received HD version of the DG usage + * info + * @return none + *************************************************************************/ +void setHDVersionDGUsageInfo( HD_VERSION_DG_USAGE_INFO_T* data ) +{ + dgServiceAndUsageData.isDGUsageInfoAviable = TRUE; + memcpy( &dgServiceAndUsageData.dgUsageInfo, data, sizeof( HD_VERSION_DG_USAGE_INFO_T ) ); +} + +/*********************************************************************//** + * @brief * The cmdSetDGDialysateHeatingParams function sends the dialysate heating * parameters to DG. * @details Inputs: none @@ -1044,6 +1111,7 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { + // Per PRS 377, PRS 124 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 ); @@ -1080,7 +1148,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 -rcd9254008b61520e5c62059329f80a84efc0366d -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision cd9254008b61520e5c62059329f80a84efc0366d) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -32,80 +32,98 @@ // ********** public definitions ********** -#define DEFAULT_TARGET_FILL_FLOW_RATE_LPM 0.8F ///< Default target fill flow rate in L/min. -#define DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during treatment. -#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 10.0F ///< Reservoir load cell drift difference allowed -#define LOAD_CELL_ILLEGAL_WEIGHT_VALUE -10000.0F ///< Initial value for Load Cells, known bad value +#define DEFAULT_TARGET_FILL_FLOW_RATE_LPM 0.8F ///< Default target fill flow rate in L/min. +#define DRAIN_RESERVOIR_TO_VOLUME_ML 0 ///< Drain reservoir to this volume (in mL) during treatment. +#define LOAD_CELL_PRIMARY_BACKUP_MAX_ALLOWED_DRIFT_GRAMS 10.0F ///< Reservoir load cell drift difference allowed +#define LOAD_CELL_ILLEGAL_WEIGHT_VALUE -10000.0F ///< Initial value for Load Cells, known bad value /// DG Concentrate ratios data structure. typedef struct { - F32 acidMixingRatio; ///< Acid mixing ratio - F32 bicarbMixingRatio; ///< Bicarb mixing ratio - U32 timeFillPrepMS; ///< Fill prepare time in milliseconds + F32 acidMixingRatio; ///< Acid mixing ratio + F32 bicarbMixingRatio; ///< Bicarb mixing ratio + U32 timeFillPrepMS; ///< Fill prepare time in milliseconds } DG_MIXING_RATIOS_T; -/// Dialysate flow meter data structure. -typedef struct -{ - F32 measuredDialysateFlowRate; ///< Dialysate flow meter rate average measurement -} DIALYSATE_FLOW_METER_DATA_T; - /// Payload record structure for a reservoirs data message. typedef struct { - U32 resID; ///< Active reservoir ID - U32 setFillToVolumeMl; ///< Reservoir set fill to target volume in ml - U32 setDrainToVolumeMl; ///< Reservoir set drain to target volume in ml - U32 timeReservoirCycleMS; ///< Reservoir time cycle in milliseconds - U32 timeReservoirFill2SwitchMS; ///< Reservoir time fill to switch in milliseconds - F32 timeUFDecayMS; ///< Ultrafilter decay time in milliseconds - F32 tempUFFill; ///< Ultrafilter fill temperature in C - F32 tempReservoirUseActual; ///< Reservoir actual use temperature in C - F32 tempReservoirEndFill; ///< Reservoir end of the fill temperature in C - F32 tempAvgFill; ///< Average fill temperature in C - F32 tempLastFill; ///< Last fill temperature in C - F32 timereservoirFillMS; ///< Reservoir fill time in milliseconds - F32 tempRsrvr0ActualTrimmer; ///< Temperature actual reservoir in C. - F32 tempFillMixAvgTrimmer; ///< Temperature fill mix average trimmer in C. - F32 tempRsrvrEndFillTrimmer; ///< Temperature reservoir end fill trimmer in C. + U32 resID; ///< Active reservoir ID + U32 setFillToVolumeMl; ///< Reservoir set fill to target volume in ml + U32 setDrainToVolumeMl; ///< Reservoir set drain to target volume in ml + U32 timeReservoirCycleMS; ///< Reservoir time cycle in milliseconds + U32 timeReservoirFill2SwitchMS; ///< Reservoir time fill to switch in milliseconds + F32 timeUFDecayMS; ///< Ultrafilter decay time in milliseconds + F32 tempUFFill; ///< Ultrafilter fill temperature in C + F32 tempReservoirUseActual; ///< Reservoir actual use temperature in C + F32 tempReservoirEndFill; ///< Reservoir end of the fill temperature in C + F32 tempAvgFill; ///< Average fill temperature in C + F32 tempLastFill; ///< Last fill temperature in C + F32 timereservoirFillMS; ///< Reservoir fill time in milliseconds + F32 tempRsrvr0ActualTrimmer; ///< Temperature actual reservoir in C. + F32 tempFillMixAvgTrimmer; ///< Temperature fill mix average trimmer in C. + F32 tempRsrvrEndFillTrimmer; ///< Temperature reservoir end fill trimmer in C. } DG_RESERVOIRS_DATA_PAYLOAD_T; /// Payload record structure for a drain reservoir command message. typedef struct { - U32 drainToVolumeML; ///< Drain to target volume in ml - BOOL tareLoadCells; ///< Flag indicates to tare load cells or not - BOOL rinseConcentrateLines; ///< Flag indicates to rinse concentrate lines or not - BOOL cmd; ///< Flag indicates to start or stop the drain mode + U32 drainToVolumeML; ///< Drain to target volume in ml + BOOL tareLoadCells; ///< Flag indicates to tare load cells or not + BOOL rinseConcentrateLines; ///< Flag indicates to rinse concentrate lines or not + BOOL cmd; ///< Flag indicates to start or stop the drain mode } DRAIN_RESERVOIR_CMD_PAYLOAD_T; /// DG command response data record structure. typedef struct { - U32 commandID; ///< The command DG is responding to - BOOL rejected; ///< Flag indicates if the command has been rejected - U32 rejectCode; ///< Reason code for rejecting the command + U32 commandID; ///< The command DG is responding to + BOOL rejected; ///< Flag indicates if the command has been rejected + U32 rejectCode; ///< Reason code for rejecting the command } DG_CMD_RESPONSE_T; /// DG heat/chemical disinfects and flush state for UI structure. typedef struct DG_Disinfects { - U32 chemDisinfectUIState; ///< DG chemical disinfect UI state - U32 heatDisinfectUIState; ///< DG heat disinfect UI state - U32 flushUIState; ///< DG flush UI state + U32 chemDisinfectUIState; ///< DG chemical disinfect UI state + U32 heatDisinfectUIState; ///< DG heat disinfect UI state + U32 flushUIState; ///< DG flush UI state } DG_DISINFECT_UI_STATES_T; /// Dialysate heating parameters typedef struct { - F32 trimmerTargetTemperature; ///< Trimmer target temperature - U32 timeReservoirCycleMS; ///< Reservoir cycle time in milliseconds - F32 timeReservoirFillMS; ///< Reservoir fill time in milliseconds - U32 timeReservoirWait2SwitchMS; ///< Reservoir wait to switch time in milliseconds - F32 dialysateFlowLPM; ///< Dialysate flow in L/min + F32 trimmerTargetTemperature; ///< Trimmer target temperature + U32 timeReservoirCycleMS; ///< Reservoir cycle time in milliseconds + F32 timeReservoirFillMS; ///< Reservoir fill time in milliseconds + U32 timeReservoirWait2SwitchMS; ///< Reservoir wait to switch time in milliseconds + F32 dialysateFlowLPM; ///< Dialysate flow in L/min } DG_CMD_DIALYSATE_HEATING_PARAMS_T; +/// HD version of DG service record +typedef struct +{ + U32 lastServiceDateEpoch; ///< Last service date in epoch + U32 serviceIntervalSeconds; ///< Service interval in seconds +} HD_VERSION_DG_SERVICE_RECORD_T ; + +/// HD version of DG usage info +typedef struct +{ + U32 lastHeatDisDateEpoch; ///< Last heat disinfect date in epoch + U32 lastChemicalDisDateEpoch; ///< Last chemical disinfect date in epoch + BOOL isDisinfected; ///< Flag to indicate whether DG is disinfected or not +} HD_VERSION_DG_USAGE_INFO_T; + +/// HD version of the DG service record +typedef struct +{ + HD_VERSION_DG_SERVICE_RECORD_T dgServiceRecord; ///< HD version of the DG service record. + HD_VERSION_DG_USAGE_INFO_T dgUsageInfo; ///< HD version of the DG usage info. + BOOL isDGServiceRecordAvailable; ///< Flag to indicate DG service record is available. + BOOL isDGUsageInfoAviable; ///< Flag to indicate DG usage info is available. +} DG_SERVICE_AND_USAGE_DATA_T; + // ********** public function prototypes ********** void initDGInterface( void ); @@ -127,7 +145,9 @@ 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 getHDVersionDGServiceAndUsageData( DG_SERVICE_AND_USAGE_DATA_T* data ); void setDGOpMode( U32 opMode, U32 subMode ); void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ); @@ -136,6 +156,9 @@ 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 setHDVersionDGServiceRecord( HD_VERSION_DG_SERVICE_RECORD_T* data ); +void setHDVersionDGUsageInfo( HD_VERSION_DG_USAGE_INFO_T* data ); void cmdSetDGDialysateHeatingParams( DG_CMD_DIALYSATE_HEATING_PARAMS_T heatingParams ); void cmdStartDG( void ); Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -71,6 +71,7 @@ #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). @@ -663,6 +664,15 @@ U32 bpOccl = getMeasuredBloodPumpOcclusion(); BOOL outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS || bpOccl > MAX_OCCLUSION_COUNTS ? TRUE : FALSE ); +#ifndef _RELEASE + if( getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) == SW_CONFIG_ENABLE_VALUE) + { + U32 minOcclusionCountV3 = 1500; + outOfRange = (( bpOccl < minOcclusionCountV3 || bpOccl > MAX_OCCLUSION_COUNTS ? TRUE : FALSE )); + } +#endif + + #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -683,7 +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 ) ) @@ -693,7 +703,6 @@ } } } - // Check for occlusion in Treatment modes where pumps are moving else if ( MODE_TREA == getCurrentOperationMode() ) { Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -92,6 +92,7 @@ /// Expected position of empty in relation to home position. #define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 10.84F ) + /// Margin of error for empty position determination. #define SYRINGE_PUMP_EMPTY_POS_MARGIN ( SYRINGE_ENCODER_COUNTS_PER_ML * 0.5F ) /// Minimum retract position. Index: firmware/App/Controllers/Temperatures.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Controllers/Temperatures.c (.../Temperatures.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -287,9 +287,10 @@ if ( ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ) ) { - isTempOutOfRange |= TRUE; - lastFaultSensor = sensor; + isTempOutOfRange = TRUE; + lastFaultSensor = sensor; } + } checkPersistentAlarm( ALARM_ID_HD_TEMPERATURES_OUT_OF_RANGE, isTempOutOfRange, lastFaultSensor, MAX_ALLOWED_TEMPERATURE ); Index: firmware/App/Drivers/Battery.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Drivers/Battery.c (.../Battery.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Drivers/Battery.c (.../Battery.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -56,7 +56,7 @@ // ********** private data ********** static U16 batteryStatus = 0; ///< Battery current status. -static U32 batteryRelStateOfCharge_pct; ///< Battery pack relative state of charge. +static U32 batteryRelStateOfCharge_pct = 0; ///< Battery pack relative state of charge. static OVERRIDE_F32_T batteryRemCapacity_mAh = { 0.0, 0.0, 0.0, 0 }; ///< Battery pack remaining capacity (in mAh). static U16 batteryPackStatus = 0; ///< Battery pack current status. static U32 lastBatteryMonitorTime = 0; ///< Previous battery monitor time. @@ -143,9 +143,9 @@ { hasBatteryChargerStatus = FALSE; - if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REL_STATE_OF_CHARGE_CMD, &relStateOfCharge_pct ) ) + if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REM_CAPACITY_CMD, &remCapacity_mAh ) ) { - batteryRelStateOfCharge_pct = (U32)relStateOfCharge_pct; + batteryRemCapacity_mAh.data = (F32)remCapacity_mAh * BATTERY_MAH_2_MWH_FACTOR; } if ( TRUE == getBatteryData( BATTERY_PACK_SLAVE_ADDRESS, BATTERY_PACK_REM_CAPACITY_CMD, &remCapacity_mAh ) ) Index: firmware/App/Drivers/SafetyShutdown.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Drivers/SafetyShutdown.c (.../SafetyShutdown.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Drivers/SafetyShutdown.c (.../SafetyShutdown.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -130,14 +130,15 @@ case SAFETY_SHUTDOWN_SELF_TEST_STATE_START: safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_IN_PROGRESS; #ifndef DISABLE_WD_AND_SFTY_POST_TESTS + { F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); - // Verify 24V is up if ( v24 < MIN_24V_LEVEL_ON_SAFETY_RECOVER ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SAFETY_SHUTDOWN_POST_TEST_FAILED, (F32)SAFETY_POST_24V_INITIAL, v24 ); safetyShutdownSelfTestStatus = SELF_TEST_STATUS_FAILED; } + } #endif safetyShutdownSelfTestTimerCount = getMSTimerCount(); activateSafetyShutdown(); Index: firmware/App/HDCommon.h =================================================================== diff -u -r0b31c212189fc6c9bf3d2ae8d93a18cf1c213b5c -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 0b31c212189fc6c9bf3d2ae8d93a18cf1c213b5c) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -10,8 +10,8 @@ * @author (last) Dara Navaei * @date (last) 22-Sep-2022 * -* @author (original) Sean -* @date (original) 27-Feb-2020 +* @author (original) Sean +* @date (original) 27-Feb-2020 * ***************************************************************************/ @@ -25,7 +25,7 @@ #define HD_VERSION_MAJOR 0 #define HD_VERSION_MINOR 6 #define HD_VERSION_MICRO 0 -#define HD_VERSION_BUILD 54 +#define HD_VERSION_BUILD 350 // ********** development build switches ********** @@ -43,12 +43,12 @@ // #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters // #define EMC_TEST_BUILD 1 // EMC test build - HD/DG run separately but connected, HD pumps toggle on/off w/ stop button #define DISABLE_WD_AND_SFTY_POST_TESTS 1 // Disable watchdog and safety shutdown POST tests -// #define DISABLE_UI_POST_TEST 1 // Disable the UI POST + #define DISABLE_UI_POST_TEST 1 // Disable the UI POST // TODO stays as a build switch until the calibration structure is updated with the build - #define SKIP_CAL_CHECK 1 // Implement software configuration + #define SKIP_CAL_CHECK 1 // Implement software configuration once the build switch is done - #include +#include #include #endif #endif Index: firmware/App/Modes/BloodPrime.c =================================================================== diff -u -rd28280f1054fc9ddf9304a11373dc9ee963425e3 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision d28280f1054fc9ddf9304a11373dc9ee963425e3) +++ firmware/App/Modes/BloodPrime.c (.../BloodPrime.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -7,8 +7,8 @@ * * @file BloodPrime.c * -* @author (last) Sean Nash -* @date (last) 13-Jul-2022 +* @author (last) Dara Navaei +* @date (last) 01-Sep-2022 * * @author (original) Sean Nash * @date (original) 06-Feb-2021 @@ -143,7 +143,7 @@ // start blood and dialysate inlet pumps setBloodPumpTargetFlowRate( (U32)bloodPrimeRampFlowRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP, 0.0F ); + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); cmdStartDGTrimmerHeater(); // Start air trap control Index: firmware/App/Modes/ModeFault.c =================================================================== diff -u -r0bce81180c0ba2b25f5d501ed6aa6b2f9a8b2500 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision 0bce81180c0ba2b25f5d501ed6aa6b2f9a8b2500) +++ firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -7,8 +7,8 @@ * * @file ModeFault.c * -* @author (last) Sean Nash -* @date (last) 13-Jul-2022 +* @author (last) Dara Navaei +* @date (last) 01-Sep-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -rb20421d84b9049977c04f4752f4fc5697425f25c -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision b20421d84b9049977c04f4752f4fc5697425f25c) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -44,7 +44,7 @@ /// 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 DIP_PATIENT_CONNECTION_FLOW_RATE_ML_MIN 250 ///< Patient connection sub-mode dialysate inlet pump flow rate in mL/min. #define PRE_TREATMENT_FLUSH_RESERVOIR_VOLUME_ML 500 ///< Fill reservoir to this volume (in mL) to flush filter and lines. #define PRE_TREATMENT_FILL_RESERVOIR_ONE_VOLUME_ML 1300 ///< Fill reservoir one to this volume (in mL) during pre-treatment mode. Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -30,6 +30,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "RTC.h" #include "Switches.h" #include "SyringePump.h" #include "SystemComm.h" @@ -46,7 +47,7 @@ // ********** private definitions ********** #define DISINFECTS_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Disinfects data publish interval in counts. -#define SERVICE_TIME_INTERVAL_MS ( 6 * 30 * SECONDS_IN_A_DAY * MS_PER_SECOND ) ///< HD/DG 6-month service interval in milliseconds. +#define DISINFECTS_TIME_INTERVAL_S ( 2 * SECONDS_IN_A_DAY ) ///< HD/DG 2-day service interval in seconds. // ********** private data ********** @@ -62,6 +63,8 @@ /// Interval (in task intervals) at which to publish standby mode data to CAN bus. static OVERRIDE_U32_T standbyModePublishInterval = { DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, DISINFECTS_DATA_PUB_INTERVAL, 0 }; +static const U32 SERVICE_TIME_INTERVAL_S = (U32)( 365 * 0.5 * SECONDS_IN_A_DAY ); ///< HD/DG 6-month service interval in seconds. + // ********** private function prototypes ********** static HD_STANDBY_STATE_T handleStandbyModeStartState( void ); @@ -80,6 +83,8 @@ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ); +static BOOL isDGDisinfectValid( void ); +static BOOL haveHDDGServicesBeenExpired( REQUEST_REJECT_REASON_CODE_T* rejReason ); static void publishDisinfectData( void ); /*********************************************************************//** @@ -145,6 +150,9 @@ { currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; } + // Request DG service record and usage information from DG + sendDGServiceRequestToDG(); + sendDGUsageInfoRequestToDG(); return currentStandbyState; } @@ -165,7 +173,7 @@ switch ( currentStandbyState ) { case STANDBY_START_STATE: - currentStandbyState = handleStandbyModeStartState();; + currentStandbyState = handleStandbyModeStartState(); break; case STANDBY_WAIT_FOR_TREATMENT_STATE: @@ -280,9 +288,22 @@ rejReason = REQUEST_REJECT_REASON_BATTERY_IS_NOT_CHARGED; } +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SERVICE_AND_DISINFECT_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // This function checks both HD and DG service records and if any of them has failed, it fills the provided reject reason buffer + haveHDDGServicesBeenExpired( &rejReason ); + + if ( FALSE == isDGDisinfectValid() ) + { + rejReason = REQUEST_REJECT_REASON_DG_DISINFECT_HAS_BEEN_EXPIRED; + } + } + if ( REQUEST_REJECT_REASON_NONE == rejReason ) { - result = TRUE; + result = TRUE; treatStartReqReceived = TRUE; } @@ -529,7 +550,7 @@ *************************************************************************/ static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ) { - HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; + HD_STANDBY_STATE_T state = STANDBY_WAIT_FOR_TREATMENT_STATE; DG_OP_MODE_T dgOperationMode = getDGOpMode(); // If DG is filling while we are in standby mode, abort the fill @@ -544,17 +565,22 @@ cmdStopDG(); } - // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). TODO - check required conditions before allowing treatment start, reject if necessary. + // If treatment start is requested by user, initiate treatment workflow (transition to treatment params mode). 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; + BOOL startTreatment = TRUE; + + if ( TRUE == startTreatment ) + { + // Initialize treatment modes before starting a new treatment + initTreatParamsMode(); + initPreTreatmentMode(); + initTreatmentMode(); + initPostTreatmentMode(); + // Start treatment workflow with treatment parameters mode + requestNewOperationMode( MODE_TPAR ); + treatStartReqReceived = FALSE; + } } return state; @@ -832,6 +858,85 @@ /*********************************************************************//** * @brief + * The isDGDisinfectValid function checks whether the DG disinfects is + * acceptable to start another treatment. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if the disinfect is valid otherwise, FALSE + ***********************************************************************/ +static BOOL isDGDisinfectValid( void ) +{ + DG_SERVICE_AND_USAGE_DATA_T data; + BOOL status = TRUE; + + getHDVersionDGServiceAndUsageData( &data ); + + if ( TRUE == data.isDGUsageInfoAviable ) + { + if ( TRUE == data.dgUsageInfo.isDisinfected ) + { + U32 chemDisElapsedTimeS = getRTCTimestamp() - data.dgUsageInfo.lastChemicalDisDateEpoch; + BOOL hasChemDisBeenExpired = ( chemDisElapsedTimeS > DISINFECTS_TIME_INTERVAL_S ? TRUE : FALSE ); + U32 heatDisElapsedTimeS = getRTCTimestamp() - data.dgUsageInfo.lastHeatDisDateEpoch; + BOOL hasHeatDisBeenExpired = ( heatDisElapsedTimeS > DISINFECTS_TIME_INTERVAL_S ? TRUE : FALSE ); + + if ( ( TRUE == hasChemDisBeenExpired ) && ( TRUE == hasHeatDisBeenExpired ) ) + { + status = FALSE; + } + } + else + { + status = FALSE; + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The haveHDDGServicesBeenExpired function checks whether the last DG/HD + * service time is still within the interval or not. + * @details Inputs: none + * @details Outputs: none + * @param rejReason pointer to the provided reject reason buffer to be send to UI + * @return TRUE if the service time is still valid otherwise, FALSE + ***********************************************************************/ +static BOOL haveHDDGServicesBeenExpired( REQUEST_REJECT_REASON_CODE_T* rejReason ) +{ + BOOL status = TRUE; + DG_SERVICE_AND_USAGE_DATA_T dgData; + HD_SERVICE_RECORD_T hdServiceRecord; + + getHDVersionDGServiceAndUsageData( &dgData ); + getNVRecord2Driver( GET_SRV_RECORD, (U08*)&hdServiceRecord, sizeof( HD_SERVICE_RECORD_T ), 0, ALARM_ID_NO_ALARM ); + + if ( TRUE == dgData.isDGServiceRecordAvailable ) + { + U32 dgSrvcElapsedTimeS = getRTCTimestamp() - dgData.dgServiceRecord.lastServiceDateEpoch; + BOOL hasDGSrvcBeenExpired = ( dgSrvcElapsedTimeS > SERVICE_TIME_INTERVAL_S ? TRUE : FALSE ); + U32 hdSrvcElapsedTimeS = getRTCTimestamp() - hdServiceRecord.lastServiceEpochDate; + BOOL hasHDSrvcBeenExpied = ( hdSrvcElapsedTimeS > SERVICE_TIME_INTERVAL_S ? TRUE : FALSE ); + + if ( TRUE == hasDGSrvcBeenExpired ) + { + status = FALSE; + *rejReason = REQUEST_REJECT_REASON_DG_SERVICE_IS_DUE; + } + + if ( TRUE == hasHDSrvcBeenExpied ) + { + status = FALSE; + *rejReason = REQUEST_REJECT_REASON_HD_SERVICE_IS_DUE; + } + } + + return status; +} + +/*********************************************************************//** + * @brief * The publishDisinfectData function publishes disinfects data at * the set interval. * @details Inputs: dataPublishCounter Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -140,14 +140,14 @@ transitionToNewOperationMode( newMode ); currentMode = newMode; - if ( MODE_TREA == lastMode ) + if ( ( MODE_TREA == lastMode ) && ( currentMode != MODE_TREA ) ) { - // If the current mode is treatment but transitioning to another mode has been requested (including transitioning to fault mode) + // If the last mode is treatment but the new mode is not treatment // it means the treatment is done. Get the elapsed time since the beginning of the treatment and convert it to hours to be written U32 txElapsedTimeMS = calcTimeSince( getTreatmentStartTimeStamp() ); F32 txElapsedTimeHrs = (F32)txElapsedTimeMS / ( MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ); // Write the treatment hours and set the service to be false so the treatment hours is not reset - setTxTimeHours( txElapsedTimeHrs, FALSE ); + setTxTimeHours( txElapsedTimeHrs ); } } Index: firmware/App/Modes/PreTreatmentRecirc.c =================================================================== diff -u -rb20421d84b9049977c04f4752f4fc5697425f25c -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision b20421d84b9049977c04f4752f4fc5697425f25c) +++ firmware/App/Modes/PreTreatmentRecirc.c (.../PreTreatmentRecirc.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -32,7 +32,7 @@ // ********** private definitions ********** #define BLOOD_PUMP_RECIRC_FLOW_RATE 100 ///< Blood pump flow rate during recirculation in mL/min. -#define DIALYSATE_PUMP_RECIRC_FLOW_RATE 100 ///< Dialysate pump flow rate during recirculation in mL/min. +#define DIALYSATE_PUMP_RECIRC_FLOW_RATE 250 ///< Dialysate pump flow rate during recirculation in mL/min. // ********** private data ********** Index: firmware/App/Modes/Prime.c =================================================================== diff -u -rb20421d84b9049977c04f4752f4fc5697425f25c -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision b20421d84b9049977c04f4752f4fc5697425f25c) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -38,7 +38,7 @@ #define MAX_PRIME_TIME ( 15 * 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_FAST_FLOW_RATE_PURGE_AIR_ML_MIN 150 ///< Blood pump fast flow rate to fill fluid. +#define BLOOD_PUMP_FAST_FLOW_RATE_PURGE_AIR_ML_MIN 300 ///< Blood pump fast flow rate to fill fluid. #define BLOOD_PUMP_SLOW_FLOW_RATE_PURGE_AIR_ML_MIN 150 ///< Blood pump slow flow rate after fluid reach lower level of air trap sensor. #define BLOOD_PUMP_SALINE_FLOW_RATE_PURGE_AIR_ML_MIN 200 ///< Blood pump very slow flow rate during prime saline dialyzer state #define BLOOD_PUMP_FLOW_RATE_CIRC_BLOOD_CIRCUIT_ML_MIN 150 ///< Blood pump flow rate during prime recirculate blood circuit state. @@ -50,9 +50,9 @@ #define DIALYZER_DVI_PATH_VOLUME_ML 17 ///< Path volume from the dialyzer to the VDI valve in mL. #define DIALYZER_VOLUME_SCALE_FACTOR 0.5F ///< Half of the dialyzer total volume. -#define NO_AIR_DETECTED_COUNT ( 20 * MS_PER_SECOND ) ///< No air detected time period count. +#define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. +#define PURGE_AIR_TIME_OUT_COUNT ( 120 * MS_PER_SECOND ) ///< Time period count for purge air time out. #define PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for prime saline dialyzer time out. -#define PURGE_AIR_TIME_OUT_COUNT ( 120 * MS_PER_SECOND ) ///< Time period count for purge air time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 15 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. @@ -102,6 +102,7 @@ static BOOL primeStartRequested; ///< Flag indicates user requesting to start prime. static BOOL primeResumeRequested; ///< Flag indicates user requesting prime resume. +static BOOL primeFirstPurgePass; ///< Flag indicates to transition to a faster purge speed. static U32 noAirDetectedStartTime; ///< starting time when detecting no air. static U32 purgeAirTimeOutStartTime; ///< Starting time for purge air state time out. @@ -162,6 +163,7 @@ void transitionToPrime( void ) { primeStartTime = getMSTimerCount(); + primeFirstPurgePass = TRUE; setAlarmUserActionEnabled( ALARM_USER_ACTION_RESUME, TRUE ); setAlarmUserActionEnabled( ALARM_USER_ACTION_RINSEBACK, FALSE ); @@ -427,7 +429,14 @@ signalDialOutPumpHardStop(); signalDialInPumpHardStop(); - setBloodPumpTargetFlowRate( BLOOD_PUMP_FAST_FLOW_RATE_PURGE_AIR_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + if (FALSE == primeFirstPurgePass ) + { + setBloodPumpTargetFlowRate( BLOOD_PUMP_FAST_FLOW_RATE_PURGE_AIR_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + else + { + setBloodPumpTargetFlowRate( BLOOD_PUMP_SLOW_FLOW_RATE_PURGE_AIR_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } } /*********************************************************************//** @@ -547,7 +556,12 @@ { purgeAirValvesBloodPumpControl(); purgeAirTimeOutStartTime = getMSTimerCount(); + if ( TRUE == primeFirstPurgePass ) + { + primeFirstPurgePass = FALSE; + } state = HD_PRIME_SALINE_PURGE_AIR_STATE; + } if ( TRUE == didTimeout( noAirDetectedStartTime, NO_AIR_DETECTED_COUNT ) ) Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -rb20421d84b9049977c04f4752f4fc5697425f25c -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision b20421d84b9049977c04f4752f4fc5697425f25c) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -41,18 +41,18 @@ #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. #define STABILTY_PRESSURE_SELF_TEST_TIME ( 4 * MS_PER_SECOND ) ///< Time to wait for pressure to stabilize in ms. #define DECAY_PRESSURE_SELF_TEST_TIME ( 2 * MS_PER_SECOND ) ///< time to wait for pressure to decay in ms. -#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -50.0F ///< Arterial pressure low limit after running blood pump. -#define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 400 ///< Venous pressure high limit after running blood pump. +#define ARTERIAL_PRESSURE_SELF_TEST_LOW_LIMIT_MMHG -80.0F ///< Arterial pressure low limit after running blood pump. +#define VENOUS_PRESSURE_SELF_TEST_HIGH_LIMIT_MMHG 40.0F ///< Venous pressure high limit after running blood pump. -#define DECAY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in pressure readings after the pump stops (in mmHg). -#define STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 2.0F ///< Difference in pressure readings while in a stable pressured state (in mmHg). +#define DECAY_PRESSURE_DIFF_TOLERANCE_MMHG 5.0F ///< Difference in pressure readings after the pump stops (in mmHg). +#define STABILITY_PRESSURE_DIFF_TOLERANCE_MMHG 2.0F ///< Difference in pressure readings while in a stable pressured state (in mmHg). #define NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG 10.0F ///< Difference in pressure readings after return to normal state tolerance (in mmHg). #define DIP_FLOW_RATE_SETUP_ML_MIN 150 ///< Dialysate inlet pump flow rate during the setup for wet self-test. @@ -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 ); } } } @@ -907,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() ) { @@ -1026,6 +1026,18 @@ F32 arterialDecayDiff = 0; F32 venousDecayDiff = 0; + // update peak pressure value from pressurized state + // if pressure continues to increase due to filter lag + if (arterialPressure > peakArterialPressure ) + { + peakArterialPressure = arterialPressure; + } + + if ( venousPressure > peakVenousPressure ) + { + peakVenousPressure = venousPressure; + } + if ( ( TRUE == didTimeout( pressureSelfTestDecayStartTime, DECAY_PRESSURE_SELF_TEST_TIME ) ) ) { arterialDecayDiff = fabs( arterialPressure - peakArterialPressure ); @@ -1044,7 +1056,6 @@ } } - if ( TRUE == doesAlarmStatusIndicateStop() ) { state = DRY_SELF_TESTS_STOPPED_STATE; @@ -1152,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 { @@ -1382,22 +1393,21 @@ *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ) { - WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_PRIME_CHECK_STATE; + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_PRIME_CHECK_STATE; + BUBBLE_STATUS_T ADVBubbleStatus = getBubbleStatus( ADV ); - BUBBLE_STATUS_T const ADVBubbleStatus = getBubbleStatus( ADV ); - if ( BUBBLE_NOT_DETECTED == ADVBubbleStatus ) { #ifndef _RELEASE_ - // TODO do we need both of these? if ( ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) != SW_CONFIG_ENABLE_VALUE ) && ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SELF_TESTS_AIR_BUBBLE_CHECK ) != SW_CONFIG_ENABLE_VALUE ) ) #endif { - zeroBloodLeak(); + if ( TRUE == zeroBloodLeak() ) + { + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + } } - - state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; } else { Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r46b163d19c65e8c21db7b0247bbb1af0dba1ece5 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 46b163d19c65e8c21db7b0247bbb1af0dba1ece5) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -170,7 +170,10 @@ SW_FAULT_ID_DG_INVALID_FILL_COMMAND_REJECTED, SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, // 140 SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, - SW_FAULT_ID_INVALID_FPGA_ERROR_GROUP_SELECTED, + SW_FAULT_ID_WRITE_USAGE_INFO_TO_NV_FAILURE, + SW_FAULT_ID_INVALID_NV_RECORD_SELECTED, + SW_FAULT_ID_BLOOD_LEAK_ENQUEUE_FAILURE, + SW_FAULT_ID_BLOOD_LEAK_INVALID_EMB_MODE_CMD_SELECTED, // 145 NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rcd9254008b61520e5c62059329f80a84efc0366d -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision cd9254008b61520e5c62059329f80a84efc0366d) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -1972,87 +1972,6 @@ /*********************************************************************//** * @brief - * The noFPGABloodLeakDetected function returns TRUE if no blood leak has been - * detected and FALSE if a blood leak has been detected. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return noFPGABloodLeakDetected - *************************************************************************/ -BOOL noFPGABloodLeakDetected( void ) -{ - U16 noFPGABloodLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_STATUS_MASK; - - return ( 0 == noFPGABloodLeakDetected ? TRUE : FALSE ); -} - -/*********************************************************************//** - * @brief - * The setFPGABloodLeakZero function sets the Blood Leak detector into - * zeroing mode via the FPGA. - * @details Inputs: none - * @details Outputs: fpgaActuatorSetPoints - * @return none - *************************************************************************/ -void setFPGABloodLeakZero( void ) -{ - fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_ZERO_CMD; -} - -/*********************************************************************//** - * @brief - * The clearFPGABloodLeakZero function clears the Blood Leak detector from - * zeroing mode via the FPGA. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return none - *************************************************************************/ -void clearFPGABloodLeakZero( void ) -{ - fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_ZERO_CMD; -} - -/*********************************************************************//** - * @brief - * The setFPGABloodLeakSelfTest function sets the Blood Leak detector into - * self-test mode via the FPGA. - * @details Inputs: none - * @details Outputs: fpgaActuatorSetPoints - * @return: none - *************************************************************************/ -void setFPGABloodLeakSelfTest( void ) -{ - fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_SELF_TEST_CMD; -} - -/*********************************************************************//** - * @brief - * The clearFPGABloodLeakSelfTest function clears the Blood Leak detector from - * self-test mode via the FPGA. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return none - *************************************************************************/ -void clearFPGABloodLeakSelfTest( void ) -{ - fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_SELF_TEST_CMD; -} - -/*********************************************************************//** - * @brief - * The getFPGABloodLeakZeroStatus function returns the blood leak sensor's - * zero status bit. - * @details Inputs: fpgaSensorReadings - * @details Outputs: none - * @return blood leak sensor zero status bit - *************************************************************************/ -U08 getFPGABloodLeakZeroStatus( void ) -{ - U08 zeroStatus = (U08)( ( fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_ZERO_STATE_MASK ) >> FPAG_BLOOD_LEAK_ZERO_BIT_INDEX ); - return zeroStatus; -} - -/*********************************************************************//** - * @brief * The getFPGABloodLeakStatus function returns the blood leak sensor's * blood detection status bit. * @details Inputs: fpgaSensorReadings Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rd4bc221d9817b488c2dcd00868386d7036a5c9a1 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision d4bc221d9817b488c2dcd00868386d7036a5c9a1) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -46,7 +46,7 @@ #define MAX_XMIT_RETRIES 5 ///< Maximum number of retries on no transmit complete interrupt timeout #define UI_COMM_TIMEOUT_IN_MS 5000 ///< UI has not checked in for this much time -#define DG_COMM_TIMEOUT_IN_MS 2000 ///< DG has not checked in for this much time +#define DG_COMM_TIMEOUT_IN_MS 1000 ///< DG has not checked in for this much time #define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm #define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window @@ -981,13 +981,17 @@ case MSG_ID_DG_VERSION: handleDGVersionResponse( message ); + break; + + case MSG_ID_DG_HEATERS_DATA: + handleDGHeatersData( message ); break; case MSG_ID_DG_TEMPERATURE_DATA: handleDGTemperatureData( message ); break; - case MSG_ID_DG_DIALYSATE_FLOW_METER_DATA: + case MSG_ID_DG_FLOW_SENSORS_DATA: handleDialysateFlowData( message ); break; @@ -1147,6 +1151,14 @@ handleUIServiceModeRequest( message ); break; + case MSG_ID_DG_SERVICE_SCHEDULE_DATA: + handleDGServiceScheduleData( message ); + break; + + case MSG_ID_DG_USAGE_DATA: + handleDGUsageInfoData( message ); + break; + // NOTE: this always must be the last case case MSG_ID_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rd4bc221d9817b488c2dcd00868386d7036a5c9a1 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision d4bc221d9817b488c2dcd00868386d7036a5c9a1) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -2309,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 @@ -2349,12 +2368,12 @@ *************************************************************************/ void handleDialysateFlowData( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof( DIALYSATE_FLOW_METER_DATA_T ) ) + if ( message->hdr.payloadLen == sizeof( FLOW_SENSORS_DATA_T ) ) { - DIALYSATE_FLOW_METER_DATA_T payload; + FLOW_SENSORS_DATA_T payload; - memcpy( &payload, message->payload, sizeof( DIALYSATE_FLOW_METER_DATA_T ) ); - setDialysateFlowData( payload.measuredDialysateFlowRate ); + memcpy( &payload, message->payload, sizeof( FLOW_SENSORS_DATA_T ) ); + setDialysateFlowData( payload.dialysateFlowRateLPM ); } } @@ -3185,23 +3204,26 @@ { MESSAGE_T msg; HD_SERVICE_RECORD_T service; + DG_SERVICE_AND_USAGE_DATA_T dgData; getNVRecord2Driver( GET_SRV_RECORD, (U08*)&service, sizeof( HD_SERVICE_RECORD_T ), 0, ALARM_ID_NO_ALARM ); + getHDVersionDGServiceAndUsageData( &dgData ); U08 *payloadPtr = msg.payload; - if ( message->hdr.payloadLen == sizeof( U32 ) + sizeof( U32 ) ) - { - // Create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_HD_SERVICE_SCHEDULE_DATA; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SERVICE_SCHEDULE_DATA; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - // Fill message payload - memcpy( payloadPtr, &service.lastServiceEpochDate, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &service.serviceIntervalSeconds, sizeof( U32 ) ); - } + // Fill message payload + memcpy( payloadPtr, &service.lastServiceEpochDate, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &service.serviceIntervalSeconds, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &dgData.dgServiceRecord.lastServiceDateEpoch, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &dgData.dgServiceRecord.serviceIntervalSeconds, sizeof( U32 ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); @@ -5127,6 +5149,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 ); @@ -7091,6 +7114,96 @@ } /*********************************************************************//** + * @brief + * The sendDGUsageInfoRequestToDG function constructs a request msg + * to the DG to request the DG usage info and queues the msg for transmit + * on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG usage info result request msg constructed and queued. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendDGUsageInfoRequestToDG( void ) +{ + BOOL result; + MESSAGE_T msg; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_REQUEST_DG_USAGE_INFO; + 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 sendDGServiceRequestToDG function constructs a request msg + * to the DG to request the DG service record and queues the msg for transmit + * on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG usage info result request msg constructed and queued. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendDGServiceRequestToDG( void ) +{ + BOOL result; + MESSAGE_T msg; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_REQUEST_DG_SERVICE_RECORD; + 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 handleDGServiceScheduleData function receives the HD version of the + * DG service record. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDGServiceScheduleData( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ) + { + HD_VERSION_DG_SERVICE_RECORD_T payload; + + memcpy( &payload, message->payload, sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ); + setHDVersionDGServiceRecord( &payload ); + } +} + +/*********************************************************************//** + * @brief + * The handleDGUsageInfoData function receives the HD version of the + * DG usage info. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDGUsageInfoData( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof( HD_VERSION_DG_USAGE_INFO_T ) ) + { + HD_VERSION_DG_USAGE_INFO_T payload; + + memcpy( &payload, message->payload, sizeof( HD_VERSION_DG_USAGE_INFO_T ) ); + setHDVersionDGUsageInfo( &payload ); + } +} + +/*********************************************************************//** * @brief * The handleGetHDUsageInfoRecord function handles a request to get the HD * usage information record. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rd4bc221d9817b488c2dcd00868386d7036a5c9a1 -r9a96522e0a94724a13c2c9c8f60cf8d18ebde218 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision d4bc221d9817b488c2dcd00868386d7036a5c9a1) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 9a96522e0a94724a13c2c9c8f60cf8d18ebde218) @@ -139,15 +139,18 @@ 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 ); // MSG_ID_RO_PUMP_DATA: void handleROPumpData( MESSAGE_T *message ); -// MSG_ID_DG_DIALYSATE_FLOW_METER_DATA: +// MSG_ID_DG_FLOW_SENSORS_DATA void handleDialysateFlowData( MESSAGE_T *message ); // MSG_ID_DRAIN_PUMP_DATA: @@ -435,6 +438,18 @@ // MSG_ID_HD_REQUEST_DG_ALARMS BOOL sendRequestForDGResendAlarms( void ); +// MSG_ID_HD_REQUEST_DG_USAGE_INFO +BOOL sendDGUsageInfoRequestToDG( void ); + +// MSG_ID_HD_REQUEST_DG_SERVICE_INFO +BOOL sendDGServiceRequestToDG( void ); + +// MSG_ID_DG_SERVICE_SCHEDULE_DATA +void handleDGServiceScheduleData( MESSAGE_T *message ); + +// MSG_ID_DG_USAGE_DATA +void handleDGUsageInfoData( MESSAGE_T *message ); + // *********** public test support message functions ********** // MSG_TESTER_LOG_IN