Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -ra3d8f8dafc488730c316ae0a64d05cb69ec8bcc9 -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision a3d8f8dafc488730c316ae0a64d05cb69ec8bcc9) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -112,6 +112,8 @@ #define BP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * BP_GEAR_RATIO * BP_MOTOR_RPM_TO_PWM_DC_FACTOR + BP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. #define BP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - BP_PWM_ZERO_OFFSET) * 4000.0F ) +/// Conversion macro from mL/min to estimated PWM duty cycle %. +#define BP_ML_PER_MIN_FROM_PWM(pwm) ( ( ( pwm - BP_PWM_ZERO_OFFSET ) / ( BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * BP_GEAR_RATIO * BP_MOTOR_RPM_TO_PWM_DC_FACTOR ) ) ) /// Measured blood flow is filtered w/ moving average. #define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 1 ) @@ -1634,5 +1636,26 @@ return result; } + +/*********************************************************************//** + * @brief + * The testSetDialInPumpTargetDutyCycle function resets the override of the + * measured dialIn pump motor current. + * @details Inputs: none + * @details Outputs: adcDialInPumpMCCurrentmA + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testSetBloodPumpTargetDutyCycle( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + targetBloodFlowRate = (S32) BP_ML_PER_MIN_FROM_PWM( value ); + result = TRUE; + } + + return result; +} /**@}*/ Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -rfb1673d2282822995ed233f3e9ea5dfb0567780d -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision fb1673d2282822995ed233f3e9ea5dfb0567780d) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -110,6 +110,9 @@ #define DIP_PWM_FROM_ML_PER_MIN(rate) ( ( ( (rate) - 49.121F ) / 684.73F ) + DIP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. PWM range is 10% to 90%. RPM range is 0 to 3200. 3200 / 0.8 = 4000. #define DIP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - DIP_PWM_ZERO_OFFSET) * 4000.0F ) +// Macro converts PWM to estimate flow rate needed to achieve it. +#define DIP_ML_PER_MIN_FROM_PWM(pwm) ( (( pwm - DIP_PWM_ZERO_OFFSET) * 684.73 ) + 49.121 ) + /// Measured dialIn flow is filtered w/ moving average. #define SIZE_OF_ROLLING_AVG 10 @@ -1638,6 +1641,28 @@ } return result; -} +} +/*********************************************************************//** + * @brief + * The testSetDialInPumpTargetDutyCycle function resets the override of the + * measured dialIn pump motor current. + * @details Inputs: none + * @details Outputs: adcDialInPumpMCCurrentmA + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testSetDialInPumpTargetDutyCycle( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + targetDialInFlowRate = (S32) DIP_ML_PER_MIN_FROM_PWM( value ); + result = TRUE; + } + + return result; +} + + /**@}*/ Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -rfb1673d2282822995ed233f3e9ea5dfb0567780d -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision fb1673d2282822995ed233f3e9ea5dfb0567780d) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -105,9 +105,11 @@ #define DOP_PWM_ZERO_OFFSET 0.1F ///< 10% PWM duty cycle = zero speed. /// Macro converts a flow rate to an estimated PWM duty cycle %. -#define DOP_PWM_FROM_ML_PER_MIN(rate) ( ( (rate) * 0.0009 ) + 0.0972 + DOP_PWM_ZERO_OFFSET ) +#define DOP_PWM_FROM_ML_PER_MIN(rate) ( ( ( rate ) * 0.0009 ) + 0.0972 + DOP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. -#define DOP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - DOP_PWM_ZERO_OFFSET) * 4000.0F ) +#define DOP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ( ( pwm ) - DOP_PWM_ZERO_OFFSET) * 4000.0F ) +/// Macro converts a PWM to an estimated flow rate. +#define DOP_ML_PER_MIN_FROM_PWM(pwm) ( ( ( pwm - DOP_PWM_ZERO_OFFSET - 0.0972 ) / 0.0009 ) ) #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. #define DOP_MIN_DIR_CHECK_SPEED_RPM 10.0F ///< Minimum motor speed before we check pump direction. @@ -1643,4 +1645,26 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetDialInPumpTargetDutyCycle function resets the override of the + * measured dialIn pump motor current. + * @details Inputs: none + * @details Outputs: adcDialInPumpMCCurrentmA + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testSetDialOutPumpTargetDutyCycle( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + lastGivenRate = (U32) DOP_PWM_FROM_ML_PER_MIN( value ); + result = TRUE; + } + + return result; +} + + /**@}*/ Index: firmware/App/Controllers/DialOutFlow.h =================================================================== diff -u -r4fc093ea280a0bdb47c20d25efb7c840b9f9867a -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision 4fc093ea280a0bdb47c20d25efb7c840b9f9867a) +++ firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -90,6 +90,7 @@ BOOL testResetMeasuredDialOutPumpMCSpeedOverride( void ); BOOL testSetMeasuredDialOutPumpMCCurrentOverride( F32 value ); BOOL testResetMeasuredDialOutPumpMCCurrentOverride( void ); +BOOL testSetDialOutPumpTargetDutyCycle( F32 value ); /**@}*/ Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rce247681f11b5e164e00992fb73ba5c595d349aa -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision ce247681f11b5e164e00992fb73ba5c595d349aa) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -30,13 +30,14 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "RTC.h" +#include "Switches.h" +#include "SyringePump.h" #include "SystemComm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" -#ifdef EMC_TEST_BUILD // TODO - test code -#include "FPGA.h" -#endif +#include "Valves.h" /** * @addtogroup HDStandbyMode @@ -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,8 +63,11 @@ /// 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 ); static HD_STANDBY_STATE_T handleStandbyModeWaitForTreatmentState( void ); static HD_STANDBY_STATE_T handleStandbyModeWaitForDisinfectState( void ); @@ -79,6 +83,8 @@ static HD_STANDBY_STATE_T handleStandbyModeWaitForDGChemDisinfectStartState( void ); static HD_STANDBY_STATE_T handleStandbyModeDGChemDisininfectInProgressState( void ); +static BOOL isDGDisinfectValid( void ); +static BOOL haveHDDGServicesBeenExpired( void ); static void publishDisinfectData( void ); /*********************************************************************//** @@ -144,6 +150,9 @@ { currentStandbyState = STANDBY_WAIT_FOR_DISINFECT_STATE; } + // Request DG service record and usage information from DG + sendDGServiceRequestToDG(); + sendDGUsageInfoRequestToDG(); return currentStandbyState; } @@ -157,18 +166,14 @@ *************************************************************************/ U32 execStandbyMode( void ) { -#ifdef EMC_TEST_BUILD - static U32 toggle = 0; - static BOOL button_state = FALSE; -#endif BOOL stop = isStopButtonPressed(); #ifndef RUN_WITHOUT_DG // State machine to get DG to prep a reservoir so we can start a treatment switch ( currentStandbyState ) { case STANDBY_START_STATE: - currentStandbyState = STANDBY_WAIT_FOR_TREATMENT_STATE; + currentStandbyState = handleStandbyModeStartState(); break; case STANDBY_WAIT_FOR_TREATMENT_STATE: @@ -230,13 +235,6 @@ homeBloodPump(); homeDialInPump(); homeDialOutPump(); -#ifdef EMC_TEST_BUILD - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - startAirTrapControl(); -#endif break; case STANDBY_WAIT_FOR_TREATMENT_STATE: @@ -245,63 +243,6 @@ requestNewOperationMode( MODE_TPAR ); treatStartReqReceived = FALSE; } - // TODO - test code - if ( TRUE == stop ) - { -#ifndef EMC_TEST_BUILD - treatStartReqReceived = FALSE; - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - requestNewOperationMode( MODE_TPAR ); -#else - if ( stop != button_state ) - { - toggle = INC_WRAP( toggle, 0, 3 ); - switch ( toggle ) - { - case 0: // Pumps and valves off - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - break; - - case 1: // Pumps off, valves in pos A - setValvePosition( VDI, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); - setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); - break; - - case 2: // Pumps on, valves in pos A - setBloodPumpTargetFlowRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 500, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - break; - - - default: // Should not get here, reset if we do - toggle = 0; - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); - setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); - break; - } - } -#endif - } -#ifdef EMC_TEST_BUILD - button_state = stop; -#endif break; default: @@ -342,12 +283,10 @@ rejReason = REQUEST_REJECT_REASON_DG_NOT_IN_STANDBY_IDLE_STATE; } -#ifndef DISABLE_BATT_COMM if ( FALSE == isBatteryCharged() ) { rejReason = REQUEST_REJECT_REASON_BATTERY_IS_NOT_CHARGED; } -#endif if ( REQUEST_REJECT_REASON_NONE == rejReason ) { @@ -539,6 +478,57 @@ /*********************************************************************//** * @brief + * The handleStandbyModeStartState function handles the standby start state. + * This state waits for the door to be closed and then initiates homing of + * pumps and valves and transitions to the wait for treatment state. + * @details Inputs: + * @details Outputs: + * @return next state of the standby mode state machine + *************************************************************************/ +static HD_STANDBY_STATE_T handleStandbyModeStartState( void ) +{ + static BOOL homingInitiated = FALSE; + HD_STANDBY_STATE_T state = STANDBY_START_STATE; + + // Wait for door to be closed so we can home actuators + if ( ( homingInitiated != TRUE ) && ( STATE_CLOSED == getSwitchStatus( FRONT_DOOR ) ) ) + { + VALVE_T valve; + + // Home pumps and valves + for ( valve = VDI; valve < NUM_OF_VALVES; ++valve ) + { + homeValve( valve ); + } + homeBloodPump(); + homeDialInPump(); + homeDialOutPump(); + retractSyringePump(); + + homingInitiated = TRUE; + } + else + { + // Trigger door open alarm to prompt user to close the door + activateAlarmNoData( ALARM_ID_CARTRIDGE_DOOR_OPENED ); + homingInitiated = FALSE; + } + + // If homing has been initiated, wait for syringe pump to home and the verify force sensor calibration + if ( ( TRUE == homingInitiated ) && ( TRUE == isSyringePumpHome() ) ) + { + syringePumpVerifyForceSensorDACCalibration(); + homingInitiated = FALSE; // reset for next time + state = STANDBY_WAIT_FOR_TREATMENT_STATE; // Go to wait for treatment state after above check + } + + return state; +} +// Verify calibration + + +/*********************************************************************//** + * @brief * The handleStandbyModeWaitForTreatmentState function handles wait for * treatment state. * @details Inputs: treatStartReqReceived @@ -547,29 +537,45 @@ *************************************************************************/ 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 if ( DG_MODE_FILL == dgOperationMode ) { cmdStopDGFill(); } + // If DG is in idle generation state while we are in standby mode, transition DG to standby too if ( DG_MODE_GENE == dgOperationMode ) { cmdStopDG(); } + // 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; + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SERVICE_AND_DISINFECT_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + startTreatment = isDGDisinfectValid(); + startTreatment = haveHDDGServicesBeenExpired(); + } + + 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; @@ -847,6 +853,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 ) +{ + BOOL status = TRUE; + DG_SERVICE_AND_USAGE_DATA_T data; + + 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; + activateAlarmNoData( ALARM_ID_DG_DISINFECT_HAS_BEEN_EXPIRED ); + } + } + else + { + status = FALSE; + activateAlarmNoData( ALARM_ID_DG_DISINFECT_HAS_BEEN_EXPIRED ); + } + } + + 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 + * @return TRUE if the service time is still valid otherwise, FALSE + ***********************************************************************/ +static BOOL haveHDDGServicesBeenExpired( void ) +{ + 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; + activateAlarmNoData( ALARM_ID_DG_SERIVCE_TIME_INTERVAL_HAS_ELAPSED ); + } + if ( TRUE == hasHDSrvcBeenExpied ) + { + status = FALSE; + activateAlarmNoData( ALARM_ID_HD_SERVICE_TIME_INTERVAL_HAS_ELAPSED ); + } + } + + return status; +} + +/*********************************************************************//** + * @brief * The publishDisinfectData function publishes disinfects data at * the set interval. * @details Inputs: dataPublishCounter Index: firmware/App/Modes/ModeStandby.h =================================================================== diff -u -rce247681f11b5e164e00992fb73ba5c595d349aa -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision ce247681f11b5e164e00992fb73ba5c595d349aa) +++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -48,15 +48,11 @@ BOOL signalUserInitiateTreatment( void ); // User has initiated a treatment - go to treatment parameters mode void signalAlarmActionToStandbyMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for Standby mode +BOOL signalUserInitiateFlushMode( void ); // User has requested to start flush +BOOL signalUserInitiateHeatDisinfectMode( void ); // User has requested to start heat disinfection +BOOL signalUserInitiateChemicalDisinfectMode( void ); // User has requested to start chem disinfection +BOOL signalInitiateStandbyDisinfectSubmode( U32 cmd ); // UI has signaled user will be selecting a cleaning operation to perform -BOOL signalUserInitiateFlushMode( void ); - -BOOL signalUserInitiateHeatDisinfectMode( void ); - -BOOL signalUserInitiateChemicalDisinfectMode( void ); - -BOOL signalInitiateStandbyDisinfectSubmode( U32 cmd ); - BOOL testSetStandbyModePublishIntervalOverride( U32 ms ); BOOL testResetStandbyModePublishIntervalOverride( void ); Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -rce247681f11b5e164e00992fb73ba5c595d349aa -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision ce247681f11b5e164e00992fb73ba5c595d349aa) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -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 ); } } @@ -253,6 +253,18 @@ /*********************************************************************//** * @brief + * The getCurrentSubMode function gets the current operation sub-mode. + * @details Inputs: currentSubMode + * @details Outputs: none + * @return the current operation sub-mode + *************************************************************************/ +U32 getCurrentSubMode( void ) +{ + return currentSubMode; +} + +/*********************************************************************//** + * @brief * The initiateAlarmAction function initiate an alarm or alarm recovery * action according to the current operation mode. * @details Inputs: currentMode Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -raf2cd84d3319b1e298057fe2d329aa7824306507 -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision af2cd84d3319b1e298057fe2d329aa7824306507) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -46,17 +46,16 @@ #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 #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,13 +976,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; @@ -1145,6 +1146,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 -raf2cd84d3319b1e298057fe2d329aa7824306507 -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision af2cd84d3319b1e298057fe2d329aa7824306507) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -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 }; @@ -1571,10 +1574,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; @@ -1583,11 +1585,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 ); @@ -2005,35 +2005,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 ******************** // *********************************************************************** @@ -2272,7 +2243,6 @@ { BOOL result; MESSAGE_T msg; - U08 *payloadPtr = msg.payload; // Create a message record blankMessage( &msg ); @@ -2341,17 +2311,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 @@ -2365,13 +2354,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 @@ -2383,12 +2372,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 ); } } @@ -3219,23 +3208,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 ); @@ -3626,38 +3618,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 @@ -5193,6 +5153,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 ); @@ -7133,6 +7094,120 @@ } /*********************************************************************//** + * @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 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. @@ -7288,15 +7363,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; @@ -7318,6 +7393,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 -rf89cac0c61f0068c045411504925373c3731c874 -r5ce7985577e93071cd4c361efe2342cdcd7004dd --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision f89cac0c61f0068c045411504925373c3731c874) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5ce7985577e93071cd4c361efe2342cdcd7004dd) @@ -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: @@ -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,21 @@ 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 ); + +// 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 @@ -810,8 +823,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 ); + // MSG_ID_HD_BLOOD_PUMP_SET_PWM void handleTestBloodPumpSetPWM( MESSAGE_T* message );