Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r19476759e215857babf7ae7a69b32fdc08aef3d4 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 19476759e215857babf7ae7a69b32fdc08aef3d4) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -285,26 +285,26 @@ /*********************************************************************//** * @brief - * The signalRinsebackToStopped function signals that user wants to return + * The signalRinsebackToTreatmentStopped function signals that user wants to return * to treatment from rinseback workflow. * @details Inputs: none * @details Outputs: rinsebackToStoppedRequest * @return none *************************************************************************/ -void signalRinsebackToStopped( void ) +void signalRinsebackToTreatmentStopped( void ) { rinsebackToStoppedRequest = TRUE; } /*********************************************************************//** * @brief - * The signalRinsebackToEnd function signals that user wants to end the + * The signalRinsebackToTreatmentEnd function signals that user wants to end the * treatment from rinseback workflow. * @details Inputs: none * @details Outputs: rinsebackToEndTreatmentRequest * @return none *************************************************************************/ -void signalRinsebackToEnd( void ) +void signalRinsebackToTreatmentEnd( void ) { rinsebackToEndTreatmentRequest = TRUE; } Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -r0b8a93215a073650631911d190767b7642f09a43 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 0b8a93215a073650631911d190767b7642f09a43) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -84,8 +84,8 @@ void transitionToTreatmentMode( void ); // Prepares for transition to treatment mode U32 execTreatmentMode( void ); // Execute the treatment mode state machine (call from OperationModes) void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for Treatment mode -void signalRinsebackToStopped( void ); // Rinseback or Re-circ sub-mode is signaling to return to treatment stopped sub-mode -void signalRinsebackToEnd( void ); // Rinseback or Re-circ sub-mode is signaling to end treatment +void signalRinsebackToTreatmentStopped( void ); // Rinseback or Re-circ sub-mode is signaling to return to treatment stopped sub-mode +void signalRinsebackToTreatmentEnd( void ); // Rinseback or Re-circ sub-mode is signaling to end treatment void signalRinsebackToRecirc( void ); // Rinseback sub-mode is signaling to move on to re-circ sub-mode TREATMENT_STATE_T getTreatmentState( void ); // Determine the current treatment sub-mode (state) Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r5b859b160a55d1a9d8b732822a63dc570cc46072 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 5b859b160a55d1a9d8b732822a63dc570cc46072) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -43,8 +43,10 @@ #define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. #define MIN_RINSEBACK_FLOW_RATE_ML_MIN 50 ///< Minimum rinseback flow rate (in mL/min). #define MAX_RINSEBACK_FLOW_RATE_ML_MIN 150 ///< Maximum rinseback flow rate (in mL/min). -#define MAX_RINSEBACK_VOLUME_PCT 1.2 ///< Maximum rinseback volume measured by independent means (as % of target). +#define MAX_RINSEBACK_SAFETY_VOLUME_MARGIN_PCT 1.2 ///< Maximum rinseback volume measured by independent means (as % of target). +/// Interval at which rinseback progress is to be published to UI. +#define RINSEBACK_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Maximum time allowed for rinseback operation (including additional rinseback volumes). #define MAX_RINSEBACK_TIME ( 7 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ) /// Maximum time allowed for each additional rinseback volume delivery. @@ -55,6 +57,7 @@ // ********** private data ********** static RINSEBACK_STATE_T rinsebackState; ///< Current state of the rinseback sub-mode. +static U32 rinsebackRate_mL_min; ///< Rinseback rate to use/adjust for this current rinseback only. static U32 rinsebackTimerCtr; ///< Timer counter for time spent in rinseback sub-mode. static F32 cumulativeRinsebackVolume_mL; ///< Total cumulative rinseback volume (in mL). @@ -63,6 +66,7 @@ static U32 rinsebackLastMotorCount; ///< The last BP motor encoder count read for independent rinseback volume check. static F32 rinsebackVolumeDelivered_Safety; ///< The cumulative independent rinseback volume (in mL) calculated so far. static U32 rinsebackAdditionalTimerCtr; ///< Timer counter for duration of an additional rinseback delivery. +static U32 rinsebackPublishTimerCtr; ///< Timer counter for determining interval for rinseback status to be published. static BOOL rinsebackStopRequested; ///< Flag indicates alarm requesting to stop rinseback. static BOOL startRinsebackRequested; ///< Flag indicates user requesting rinseback start (confirming saline bag move to arterial line end). @@ -100,6 +104,8 @@ static BOOL handleBackToTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); static BOOL handleEndTreatmentUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ); +static void publishRinsebackData( void ); + /*********************************************************************//** * @brief * The initRinseback function initializes the Rinseback sub-mode module. @@ -110,13 +116,15 @@ void initRinseback( void ) { rinsebackState = RINSEBACK_STOP_INIT_STATE; + rinsebackRate_mL_min = getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); rinsebackTimerCtr = 0; cumulativeRinsebackVolume_mL = 0.0; additionalRinsebackVolume_mL = 0.0; rinsebackMotorCount = 0; rinsebackLastMotorCount = 0; rinsebackVolumeDelivered_Safety = 0.0; rinsebackAdditionalTimerCtr = 0; + rinsebackPublishTimerCtr = 0; resetRinsebackFlags(); } @@ -270,6 +278,9 @@ // Rinseback flags should be handled by now - reset in case not handled by current state resetRinsebackFlags(); + + // Publish rinseback progress while in rinseback sub-mode + publishRinsebackData(); } /*********************************************************************//** @@ -288,25 +299,25 @@ if ( TRUE == startRinsebackRequested ) { startRinsebackRequested = FALSE; - setupForRinsebackDelivery( getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ) ); + setupForRinsebackDelivery( rinsebackRate_mL_min ); // From moment we start rinseback, we consider blood side of dialyzer no longer fully primed setBloodIsPrimed( FALSE ); result = RINSEBACK_RUN_STATE; } // Has user requested to return to treatment? else if ( TRUE == backToTreatmentRequested ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); } // Has user requested to end the treatment? else if ( TRUE == endTreatmentRequested ) { - signalRinsebackToEnd(); + signalRinsebackToTreatmentEnd(); } // Has rinseback operation exceeded max time? else if ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); } @@ -348,7 +359,7 @@ // Has rinseback operation exceeded max time? else if ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); } // Has user or alarm requested rinseback pause? @@ -360,7 +371,7 @@ result = RINSEBACK_PAUSED_STATE; } // Has independent safety volume exceeded safety limit? - else if ( rinsebackVolumeDelivered_Safety > ( TARGET_RINSEBACK_VOLUME_ML * MAX_RINSEBACK_VOLUME_PCT ) ) + else if ( rinsebackVolumeDelivered_Safety > ( TARGET_RINSEBACK_VOLUME_ML * MAX_RINSEBACK_SAFETY_VOLUME_MARGIN_PCT ) ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); @@ -371,7 +382,7 @@ { // Has user requested rate change? if ( ( TRUE == incrRinsebackFlowRateRequested ) || ( TRUE == decrRinsebackFlowRateRequested ) ) { - U32 rbRate = getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); + U32 rbRate = rinsebackRate_mL_min; if ( TRUE == incrRinsebackFlowRateRequested ) { @@ -385,12 +396,10 @@ decrRinsebackFlowRateRequested = FALSE; if ( ( rbRate >= MIN_RINSEBACK_FLOW_RATE_ML_MIN ) && ( rbRate <= MAX_RINSEBACK_FLOW_RATE_ML_MIN ) ) { - setTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE, rbRate ); - setBloodPumpTargetFlowRate( rbRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + rinsebackRate_mL_min = rbRate; + setBloodPumpTargetFlowRate( rinsebackRate_mL_min, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } } - - // TODO - monitor max time or independent volume as safety check for rinseback operation } return result; @@ -411,13 +420,13 @@ // Has rinseback operation exceeded max time? if ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); } else if ( TRUE == resumeRinsebackRequested ) { resumeRinsebackRequested = FALSE; - setupForRinsebackDelivery( getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ) ); + setupForRinsebackDelivery( rinsebackRate_mL_min ); result = RINSEBACK_RUN_STATE; } // Has user requested to end rinseback? @@ -462,11 +471,11 @@ } else if ( TRUE == backToTreatmentRequested ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); } else if ( TRUE == endTreatmentRequested ) { - signalRinsebackToEnd(); + signalRinsebackToTreatmentEnd(); } return result; @@ -491,7 +500,9 @@ rinsebackAdditionalTimerCtr++; // Has additional rinseback completed or timed out? - if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) + if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || + ( cumulativeRinsebackVolume_mL >= MAX_TOTAL_RINSEBACK_VOLUME_ML ) || + ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) { setupForRinsebackStopOrPause(); result = RINSEBACK_STOP_STATE; @@ -633,9 +644,8 @@ static BOOL handleIncrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; - U32 rbRate = getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); - if ( ( rbRate + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) <= MAX_RINSEBACK_FLOW_RATE_ML_MIN ) + if ( ( rinsebackRate_mL_min + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) <= MAX_RINSEBACK_FLOW_RATE_ML_MIN ) { if ( RINSEBACK_RUN_STATE == rinsebackState ) { @@ -668,9 +678,8 @@ static BOOL handleDecrRinsebackUserAction( REQUEST_REJECT_REASON_CODE_T *rejReason ) { BOOL result = FALSE; - F32 rbRate = (F32)getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); - if ( ( rbRate + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) >= MIN_RINSEBACK_FLOW_RATE_ML_MIN ) + if ( ( rinsebackRate_mL_min + RINSEBACK_FLOW_RATE_ADJ_ML_MIN ) >= MIN_RINSEBACK_FLOW_RATE_ML_MIN ) { if ( RINSEBACK_RUN_STATE == rinsebackState ) { @@ -886,4 +895,25 @@ return result; } +/*********************************************************************//** + * @brief + * The publishRinsebackData function publishes rinseback progress to UI + * at 1 Hz interval. + * @details Inputs: rinsebackPublishTimerCtr + * @details Outputs: rinseback data published + * @return none + *************************************************************************/ +static void publishRinsebackData( void ) +{ + if ( ++rinsebackPublishTimerCtr >= RINSEBACK_DATA_PUBLISH_INTERVAL ) + { + RINSEBACK_DATA_PAYLOAD_T data; + + rinsebackPublishTimerCtr = 0; + data.targetRinsebackVolumeMl = TARGET_RINSEBACK_VOLUME_ML; + data.deliveredRinsebackVolumeMl = cumulativeRinsebackVolume_mL; + broadcastRinsebackData( data ); + } +} + /**@}*/ Index: firmware/App/Modes/Rinseback.h =================================================================== diff -u -r49dba1e95bb3763b4c150e7a80b84a65264a7ca8 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Modes/Rinseback.h (.../Rinseback.h) (revision 49dba1e95bb3763b4c150e7a80b84a65264a7ca8) +++ firmware/App/Modes/Rinseback.h (.../Rinseback.h) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -32,8 +32,21 @@ * @{ */ -// ********** private function prototypes ********** +// ********** public definitions ****************** +#pragma pack(push,1) + +/// Payload record structure for a rinseback data broadcast message. +typedef struct +{ + F32 targetRinsebackVolumeMl; + F32 deliveredRinsebackVolumeMl; +} RINSEBACK_DATA_PAYLOAD_T; + +#pragma pack(pop) + +// ********** public function prototypes ********** + void initRinseback( void ); void transitionToRinseback( void ); void execRinseback( void ); Index: firmware/App/Modes/TreatmentRecirc.c =================================================================== diff -u -r0b8a93215a073650631911d190767b7642f09a43 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 0b8a93215a073650631911d190767b7642f09a43) +++ firmware/App/Modes/TreatmentRecirc.c (.../TreatmentRecirc.c) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -222,12 +222,12 @@ else if ( TRUE == recircEndTreatmentRequested ) { setupForRecirculationStopState(); - signalRinsebackToEnd(); // signal end Tx sub-mode + signalRinsebackToTreatmentEnd(); // signal end Tx sub-mode } // Has max time in re-circ sub-mode been exceeded? else if ( recircTimerCtr > RECIRC_TIMEOUT_MS ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); } @@ -249,12 +249,12 @@ // Is back to treatment requested? if ( TRUE == recircBackToTreatmenRequested ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); } // Is end treatment requested? else if ( TRUE == recircEndTreatmentRequested ) { - signalRinsebackToEnd(); + signalRinsebackToTreatmentEnd(); } // Is re-circ resume requested? else if ( TRUE == recircResumeRequested ) @@ -265,7 +265,7 @@ // Has max time in re-circ sub-mode been exceeded? else if ( recircTimerCtr > RECIRC_TIMEOUT_MS ) { - signalRinsebackToStopped(); + signalRinsebackToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RECIRC_TIMEOUT_ALARM ); } Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r19476759e215857babf7ae7a69b32fdc08aef3d4 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 19476759e215857babf7ae7a69b32fdc08aef3d4) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -29,7 +29,6 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "PresOccl.h" -#include "Rinseback.h" #include "RTC.h" #include "SafetyShutdown.h" #include "SystemComm.h" @@ -1164,6 +1163,7 @@ * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: saline bolus data msg constructed and queued + * @param data saline bolus data record * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ) @@ -1187,6 +1187,34 @@ /***********************************************************************//** * @brief + * The broadcastRinsebackData function constructs a rinseback data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: rinseback data msg constructed and queued + * @param data rinseback data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_RINSEBACK_PROGRESS; + msg.hdr.payloadLen = sizeof( RINSEBACK_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( RINSEBACK_DATA_PAYLOAD_T ) ); + + // 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; +} + +/***********************************************************************//** + * @brief * The broadcastAirTrapData function constructs an HD air trap data msg to \n * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r49dba1e95bb3763b4c150e7a80b84a65264a7ca8 -r1b27784f400d03678a1441cd70ab1c4111bbfa04 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 49dba1e95bb3763b4c150e7a80b84a65264a7ca8) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 1b27784f400d03678a1441cd70ab1c4111bbfa04) @@ -29,6 +29,7 @@ #include "MsgQueues.h" #include "NVDataMgmt.h" #include "PresOccl.h" +#include "Rinseback.h" #include "Valves.h" /** @@ -240,6 +241,9 @@ // MSG_ID_SALINE_BOLUS_DATA BOOL broadcastSalineBolusData( SALINE_BOLUS_DATA_PAYLOAD_T data ); +// MSG_ID_HD_RINSEBACK_PROGRESS +BOOL broadcastRinsebackData( RINSEBACK_DATA_PAYLOAD_T data ); + // MSG_ID_HD_AIR_TRAP_DATA BOOL broadcastAirTrapData( AIR_TRAP_LEVELS_T lowerLevel, AIR_TRAP_LEVELS_T upperLevel );