Index: firmware/App/DGCommon.h =================================================================== diff -u -r2f3090feeb06eb738aefc8eae5f080070a0a8919 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 2f3090feeb06eb738aefc8eae5f080070a0a8919) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -90,6 +90,7 @@ U08 fpgaMajor; ///< DG FPGA major revision U08 fpgaMinor; ///< DG FPGA minor revision U08 fpgaLab; ///< DG FPGA lab revision + U32 compatibilityRev; ///< DG compatibility revision } DG_VERSIONS_T; #pragma pack(pop) Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r2f3090feeb06eb738aefc8eae5f080070a0a8919 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2f3090feeb06eb738aefc8eae5f080070a0a8919) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -31,6 +31,7 @@ #include "Reservoirs.h" #include "ROPump.h" #include "SystemComm.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" @@ -52,6 +53,7 @@ #define BICARB_PUMP_40_ML_PER_MIN 40.0 ///< Bicarb pump speed of 40.0 mL/minute. #define CONCENTRATE_PUMP_40_ML_PER_MIN 40.0 ///< Concentrate pump speed of 40.0 mL/minute. +#define FILL_MODE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the fill mode data is published on the CAN bus. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. #define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 1 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. @@ -97,6 +99,18 @@ BOOL isThisFirstFill; ///< Fill flag to indicate whether it is the first fill or not. } FILL_CONDITION_STATUS_T; +/// DG broadcast dialysate fill data structure. +typedef struct +{ + F32 averageBicardConductivity; ///< The average bicarb conductivity calculated in one fill. + F32 averageAcidConductivity; ///< The average acid conductivity calculated in one fill. + BOOL isThisTheFirstFill; ///< Indicate if this is the first fill. + F32 pctDiffInConductivity; ///< The percent difference between CD1 and CD2. + F32 usedAcidVolumeML; ///< The used acid volume in ML. + F32 usedBicarbVolumeML; ///< The used bicarb volume in ML. +} DG_FILL_DIALYSATE_DATA_T; + +static U32 fillModeDataPublicationTimerCounter; ///< Used to schedule dialysate fill data publication to CAN bus. static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. @@ -125,6 +139,9 @@ static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. static OVERRIDE_F32_T usedBicarbVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in mL. +static OVERRIDE_U32_T fillModeDataPublishInterval = { FILL_MODE_DATA_PUB_INTERVAL, + FILL_MODE_DATA_PUB_INTERVAL, + 0, 0 }; ///< Interval (in ms) at which to publish fill mode data to CAN bus. static F32 roPumpFlushBubblesSpeed[ RO_PUMP_LOOKUP_TABLE_SIZE ] = { RO_PUMP_400_ML_PER_MIN, ///< Lookup table to determine the desired RO speed in mL/min when flushing bubbles. RO_PUMP_800_ML_PER_MIN, @@ -149,6 +166,7 @@ static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); static void setFillInfoToRTCRAM( void ); static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ); +static void publishFillModeData( void ); /*********************************************************************//** * @brief @@ -164,6 +182,7 @@ { fillState = DG_FILL_MODE_STATE_START; dialysateFillStartTime = 0; + fillModeDataPublicationTimerCounter = 0; reservoirBaseWeight = 0.0; totalROFlowRateMLPM = 0.0; concentrateTestStartTime = 0; @@ -234,6 +253,7 @@ checkInletPressure(); checkRORejectionRatio(); checkDialysateTemperatureSensorsDrift(); + publishFillModeData(); // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir @@ -646,8 +666,9 @@ F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); - BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); + // Continuous conductivity testing will be implemented in the next phase + //BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); + //BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); // Set concentrate pumps speed based on the RO pump flow rate handleDialysateMixing( measuredROFlowRateMLPM ); @@ -677,9 +698,9 @@ #endif #ifndef DISABLE_MIXING - // Detect empty bottles using integrated volumes and conductivity sensors - if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 437 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) + // Detect empty bottles using integrated volumes // TODO: empty bottles detection using conductivity sensors + if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 437 + //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) { usedAcidVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -689,8 +710,8 @@ result = DG_FILL_MODE_STATE_PAUSED; } - if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 438 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) + if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) ) // || // SRSDG 438 + //( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) { usedBicarbVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -903,4 +924,177 @@ setHeatersInfoRecord( (U08*)&record ); } +/*********************************************************************//** + * @brief + * The publishFillModeData function publishes dialysate fill data + * at the set interval. + * @details Inputs: fillModeDataPublicationTimerCounter + * @details Outputs: fillModeDataPublicationTimerCounter + * @return none + *************************************************************************/ +static void publishFillModeData( void ) +{ + // publish Drain pump data on interval + if ( ++fillModeDataPublicationTimerCounter >= getU32OverrideValue( &fillModeDataPublishInterval ) ) + { + DG_FILL_DIALYSATE_DATA_T fillModeData; + + // Populate the data structure for publication + fillModeData.averageAcidConductivity = averageAcidConductivity; + fillModeData.averageBicardConductivity = averageBicardConductivity; + fillModeData.isThisTheFirstFill = isThisTheFirstFill(); + fillModeData.pctDiffInConductivity = pctDiffInConductivity; + fillModeData.usedAcidVolumeML = usedAcidVolumeML.data; + fillModeData.usedBicarbVolumeML = usedBicarbVolumeML.data; + + broadcastData( MSG_ID_DRAIN_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&fillModeData, sizeof( DG_FILL_DIALYSATE_DATA_T ) ); + + fillModeDataPublicationTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetUsedAcidVolumeMLOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedAcidVolumeML.ovInitData = usedAcidVolumeML.data; + usedAcidVolumeML.ovData = value; + usedAcidVolumeML.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetUsedAcidVolumeMLOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedAcidVolumeML.data = usedAcidVolumeML.ovInitData; + usedAcidVolumeML.override = OVERRIDE_RESET; + usedAcidVolumeML.ovInitData = 0.0; + usedAcidVolumeML.ovData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetUsedBicarbVolumeMLOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedBicarbVolumeML.ovInitData = usedBicarbVolumeML.data; + usedBicarbVolumeML.ovData = value; + usedBicarbVolumeML.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetUsedBicarbVolumeMLOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + usedBicarbVolumeML.data = usedBicarbVolumeML.ovInitData; + usedBicarbVolumeML.override = OVERRIDE_RESET; + usedBicarbVolumeML.ovInitData = 0.0; + usedBicarbVolumeML.ovData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetDialysateFlowDataPublishIntervalOverride function overrides the + * Dialysate flow data publish interval. + * @details Inputs: dialysateFlowDataPublishInterval + * @details Outputs: dialysateFlowDataPublishInterval + * @param: value override Dialysate flow data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFillModeDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_GENERAL_INTERVAL; + fillModeDataPublishInterval.ovData = intvl; + fillModeDataPublishInterval.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetDialysateFlowDataPublishIntervalOverride function resets the + * override of the dialysate flow data publish interval. + * @details Inputs: dialysateFlowDataPublishInterval + * @details Outputs: dialysateFlowDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetFillModeDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + fillModeDataPublishInterval.override = OVERRIDE_RESET; + fillModeDataPublishInterval.ovData = fillModeDataPublishInterval.ovInitData; + result = TRUE; + } + + return result; +} + /**@}*/ Index: firmware/App/Modes/ModeFill.h =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Modes/ModeFill.h (.../ModeFill.h) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -49,6 +49,12 @@ BOOL isThisTheFirstFill( void ); +BOOL testSetUsedAcidVolumeMLOverride( F32 value ); +BOOL testSetUsedBicarbVolumeMLOverride( F32 value ); + +BOOL testResetUsedAcidVolumeMLOverride( void ); +BOOL testResetUsedBicarbVolumeMLOverride( void ); + /**@}*/ #endif Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -1148,6 +1148,14 @@ handleTestFansRPMAlarmStartTimeOffsetOverrideRequest( message ); break; + case MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE: + handleTestUsedAcidVolumeMLOverrideRequest( message ); + break; + + case MSG_ID_DG_USED_BICARB_VOLUME_ML_OVERRIDE: + handleTestUsedBicarbVolumeMLOverrideRequest( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -25,6 +25,7 @@ #include "Fans.h" #include "FPGA.h" #include "Heaters.h" +#include "ModeFill.h" #include "ModeFlush.h" #include "ModeGenIdle.h" #include "ModeInitPOST.h" @@ -3202,4 +3203,68 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleTestUsedAcidVolumeMLOverrideRequest function handles a + * request to override the acid volume. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestUsedAcidVolumeMLOverrideRequest( 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 = testSetUsedAcidVolumeMLOverride( payload.state.f32 ); + } + else + { + result = testResetUsedAcidVolumeMLOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestUsedBicarbVolumeMLOverrideRequest function handles a + * request to override the used bicarb volume. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestUsedBicarbVolumeMLOverrideRequest( 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 = testSetUsedBicarbVolumeMLOverride( payload.state.f32 ); + } + else + { + result = testResetUsedBicarbVolumeMLOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -re28e96fba3f2293208e6d91673288acba2514cca --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision e28e96fba3f2293208e6d91673288acba2514cca) @@ -353,6 +353,11 @@ // MSG_ID_DG_FAN_RPM_ALARM_START_TIME_OFFSET_OVERRIDE void handleTestFansRPMAlarmStartTimeOffsetOverrideRequest( MESSAGE_T *message ); +// MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE +void handleTestUsedAcidVolumeMLOverrideRequest(MESSAGE_T *message); + +// MSG_ID_DG_USED_BICARB_VOLUME_ML_OVERRIDE +void handleTestUsedBicarbVolumeMLOverrideRequest(MESSAGE_T *message); /**@}*/ #endif