Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r67697eb4ca0296ad472b19b4534bea0aea1e759a -r9be15d1bdc8753e159388edd75499f837c148da2 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 67697eb4ca0296ad472b19b4534bea0aea1e759a) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 9be15d1bdc8753e159388edd75499f837c148da2) @@ -7,8 +7,8 @@ * * @file ModeTreatment.c * -* @author (last) Sean Nash -* @date (last) 30-Sep-2023 +* @author (last) Vinayakam Mani +* @date (last) 12-Oct-2023 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -59,6 +59,8 @@ #define TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which the treatment state data is published on the CAN bus. #define TREATMENT_STATE_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) +/// Interval (ms/task time) at which the treatment state data is published on the CAN bus. +#define TDI_TEMPERATURE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which updated, valid treatment setting ranges are published on the CAN bus. #define TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) /// Interval (ms) at which the treatment periodic data is published on the CAN bus. @@ -88,6 +90,7 @@ static U32 lastTreatmentTimeStamp; ///< Last time elapsed treatment time was recorded (a timestamp in ms). static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment time data broadcast timer counter used to schedule when to transmit data. static U32 treatmentStateBroadcastTimerCtr; ///< Treatment state data broadcast timer counter used to schedule when to transmit data. +static U32 tdiTempCounterBroadcastTimerCtr; ///< TDI temperature data broadcast timer counter used to schedule when to transmit data. static U32 treatmentParamsRangesBroadcastTimerCtr; ///< Treatment parameter ranges broadcast timer counter used to schedule when to transmit updated ranges. /// Interval (in task intervals) at which to publish alarm status to CAN bus. @@ -96,6 +99,8 @@ static OVERRIDE_U32_T treatmentStatePublishInterval = { TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, 0 }; /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T treatmentParamRangesPublishInterval = { TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, 0 }; +/// Interval (in task intervals) at which to publish alarm status to CAN bus. +static OVERRIDE_U32_T tdiTemperatureCounterPublishInterval = { TDI_TEMPERATURE_DATA_PUB_INTERVAL, TDI_TEMPERATURE_DATA_PUB_INTERVAL, TDI_TEMPERATURE_DATA_PUB_INTERVAL, 0 }; static BOOL resumeTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment resume. static BOOL initiateRinsebackAlarmResponseRequest; ///< Flag indicates user has requested rinseback. @@ -166,13 +171,15 @@ treatmentTimeBroadcastTimerCtr = TREATMENT_TIME_DATA_PUB_INTERVAL; // So we send time data immediately when we begin treatment mode treatmentStateBroadcastTimerCtr = TREATMENT_STATE_DATA_PUB_INTERVAL; // So we send state data immediately when we begin treatment mode treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode + tdiTempCounterBroadcastTimerCtr = TDI_TEMPERATURE_DATA_PUB_INTERVAL; // So we send state data immediately when we begin treatment mode presTreatmentTimeSecs = 0; presMaxUFVolumeML = 0.0; presUFRate = 0.0; resetSignalFlags(); resetAlarmSignalFlags(); + resetTdiTempCounters(); pendingParamChangesTimer = 0; pendingUFVolumeChange = 0.0; @@ -676,6 +683,7 @@ broadcastTreatmentTimeAndState(); broadcastTreatmentSettingsRanges(); broadcastTreatmentPeriodicData(); + broadcastTdiTemperatureCounters(); // Manage air trap control execAirTrapMonitorTreatment(); @@ -713,7 +721,7 @@ * @brief * The handleTreatmentBloodPrimeState function handles the blood prime state of * the Treatment Mode state machine. - * @details Inputs: none + * @details Inputs: presUFRate * @details Outputs: none * @return next treatment mode state *************************************************************************/ @@ -738,9 +746,13 @@ { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off - setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), - presMaxUFVolumeML, presUFRate ); - sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0, presUFRate ); + setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); + setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); + + if ( presUFRate > 0.0 ) + { + sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0, presUFRate ); + } transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } @@ -1034,7 +1046,7 @@ presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, ( presTreatmentTimeSecs / SEC_PER_MIN ) ); - setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); + setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } else @@ -1119,9 +1131,8 @@ DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); F32 remUFVol = uFVolume - colUFVol; // What would remaining UF volume be after subtracting UF volume already taken - F32 remUFVolCap = RANGE( remUFVol, 0.0F, (F32)MAX_UF_VOLUME_ML ); // Enforce valid range on remaining UF volume - F32 uFRate = remUFVolCap / txMinRem; // What UF rate would be if user selected to adjust it - U32 trtTime = ( fabs( presUFRate ) < NEARLY_ZERO ? txMinEla + 1 : (S32)( remUFVolCap / presUFRate ) + txMinEla + 1 ); // What the treatment duration would be if user selected to adjust it + F32 uFRate = remUFVol / txMinRem; // What UF rate would be if user selected to adjust it + U32 trtTime = ( fabs( presUFRate ) < NEARLY_ZERO ? txMinEla + 1 : (S32)( remUFVol / presUFRate ) + txMinEla + 1 ); // What the treatment duration would be if user selected to adjust it U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * trtTime; // What dialysate volume would be if user selected to adjust time // UF should already be paused but let's make sure. @@ -1136,7 +1147,7 @@ pendingParamChangesTimer = getMSTimerCount(); // Verify UF rate change would be valid (leave zero if not valid - UI will disable option) - if ( ( uFRate <= (F32)MAX_UF_RATE_ML_MIN ) && ( uFRate >= MIN_UF_RATE_ML_MIN ) ) + if ( uFRate <= (F32)MAX_UF_RATE_ML_MIN ) { result = TRUE; pendingUFVolumeChange = uFVolume; @@ -1219,8 +1230,7 @@ presUFRate = pendingUFRateChange; signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } - setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), - presMaxUFVolumeML, presUFRate ); + setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); // If UF paused, resume with new settings if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && @@ -1279,18 +1289,25 @@ ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; - sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); - sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); - if ( ( bloodRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ) || - ( dialRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) ) + // handle blood pump flow rate change + if ( bloodRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ) { + sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Set to new rate + setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); + setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); } - // Set to new rates - setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); - setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); - setDialysisParams( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), - presMaxUFVolumeML, presUFRate ); + + // Handle dialysate flow rate changes + if ( dialRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) + { + sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + // Set to new rate + setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); + setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); + } } else { @@ -1459,6 +1476,43 @@ /*********************************************************************//** * @brief + * The broadcastTdiTemperatureCounters function broadcasts tdi temperature high and low + * counter variables. + * @details Inputs: tdiTempCounterBroadcastTimerCtr,dgDialysateTemp + * @details Outputs: tdiTempCounterBroadcastTimerCtr. + * @return none + *************************************************************************/ +void broadcastTdiTemperatureCounters( void ) +{ + DG_TDI_TEMP_COUNTER_T tdiTempCounter; + + // get Tdi temperature counter variables + tdiTempCounter = getDGTdiTempCounter(); + + // Broadcast treatment state data at interval + if ( ++tdiTempCounterBroadcastTimerCtr >= getU32OverrideValue( &tdiTemperatureCounterPublishInterval ) ) + { + TDI_TEMP_COUNTER_T payload; + + payload.tdiHighTempUpCntr = tdiTempCounter.tdiHighTempUpCounter; + payload.tdiHighTempDownCntr = tdiTempCounter.tdiHighTempDownCounter; + payload.prevTdiHighTempUpCntr = tdiTempCounter.prevTdiHighTempUpCounter; + payload.prevTdiHighTempDownCntr = tdiTempCounter.prevTdiHighTempDownCounter; + payload.tdiLowTempUpCntr = tdiTempCounter.tdiLowTempUpCounter; + payload.tdiLowTempDownCntr = tdiTempCounter.tdiLowTempDownCounter; + payload.prevTdiLowTempUpCntr = tdiTempCounter.prevTdiLowTempUpCounter; + payload.prevTdiLowTempDownCntr = tdiTempCounter.prevTdiLowTempDownCounter; + payload.dgCurrentActiveReservoir = (U32)tdiTempCounter.dgCurrentActiveReservoir; + payload.dgPrevActiveReservoir = (U32)tdiTempCounter.dgPrevActiveReservoir; + payload.dgTdiTemp = getDGTdiTempetraure(); + + broadcastData( MSG_ID_HD_TDI_TEMP_COUNTER_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TDI_TEMP_COUNTER_T ) ); + tdiTempCounterBroadcastTimerCtr = 0; + } +} + +/*********************************************************************//** + * @brief * The broadcastTreatmentSettingsRanges function computes and broadcasts * updated treatment parameter ranges that the user may change during treatment. * It is assumed that prescription settings have already been set prior to calling @@ -1535,22 +1589,26 @@ if ( ( timeElapsedSinceLastPublish_ms >= TREATMENT_PERIODIC_DATA_PUB_INTERVAL ) || ( TRUE == sendLastTreatmentPeriodicData ) ) { TREATMENT_LOG_DATA_PERIODIC_T periodTreatmentData; + F32 const uFVolumeCollected = getUltrafiltrationVolumeCollected(); U32 const numberOfDataPoint = timeElapsedSinceLastPublish_ms / TREATMENT_PERIODIC_DATA_LOG_INTERVAL; - periodTreatmentData.avgUFRate = ( getUltrafiltrationVolumeCollected() - lastUltraFiltrationVolume_mL ) / ( numberOfDataPoint / SEC_PER_MIN ); - periodTreatmentData.avgBloodFlowRate = bloodFlowRateSum_mL_min / numberOfDataPoint; - periodTreatmentData.avgDialysateFlowRate = dialysateFlowRateSum_mL_min / numberOfDataPoint; - periodTreatmentData.avgArterialPressure = arterialPressureSum_mmHg / numberOfDataPoint; - periodTreatmentData.avgVenousPressure = venousPressureSum_mmHg / numberOfDataPoint; - + if ( numberOfDataPoint > 0 ) + { // don't send data if no data since last publish + periodTreatmentData.avgUFRate = ( uFVolumeCollected - lastUltraFiltrationVolume_mL ) / ( numberOfDataPoint / SEC_PER_MIN ); + periodTreatmentData.avgBloodFlowRate = bloodFlowRateSum_mL_min / numberOfDataPoint; + periodTreatmentData.avgDialysateFlowRate = dialysateFlowRateSum_mL_min / numberOfDataPoint; + periodTreatmentData.avgArterialPressure = arterialPressureSum_mmHg / numberOfDataPoint; + periodTreatmentData.avgVenousPressure = venousPressureSum_mmHg / numberOfDataPoint; + sendTreatmentPeriodicDataToUI( &periodTreatmentData ); + } + // reset for next round to publish sendLastTreatmentPeriodicData = FALSE; lastTreatmentPeriodicDataPublishTimeStamp = treatmentTimeMS; - lastUltraFiltrationVolume_mL = getUltrafiltrationVolumeCollected(); + lastUltraFiltrationVolume_mL = uFVolumeCollected; bloodFlowRateSum_mL_min = 0.0; dialysateFlowRateSum_mL_min = 0.0; arterialPressureSum_mmHg = 0.0; venousPressureSum_mmHg = 0.0; - sendTreatmentPeriodicDataToUI( &periodTreatmentData ); } }