Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -r775fc673109760677ca4c3ed6e95af9324b02169 -r747c714d2b4f80b598a66326d62a179aeefda390 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 775fc673109760677ca4c3ed6e95af9324b02169) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 747c714d2b4f80b598a66326d62a179aeefda390) @@ -90,6 +90,7 @@ static BOOL treatParamsConfirmed = FALSE; ///< Flag indicates user has confirmed the treatment parameters. static BOOL treatParamsRejected = FALSE; ///< Flag indicates user has rejected the treatment parameters. static BOOL treatmentCancelled = FALSE; ///< Flag indicates user has cancelled the treatment. +static HD_INSTITUTIONAL_RECORD_T hdInstitutionalRecord; ///< Institutional record. // ********** private function prototypes ********** @@ -100,6 +101,8 @@ static BOOL checkTreatmentParamsDependencies( U32 *reasons ); static void extractTreatmentParamsFromPayload( TREATMENT_PARAMS_DATA_PAYLOAD_T payload ); static void sendTreatmentParamsResponse( BOOL rejected, U32 *reasons ); +static void checkPressureParamsRange( TREATMENT_PARAMS_DATA_PAYLOAD_T* txParams ); +static void getInstitutionalRecordEdgeValue( TREATMENT_PARAM_T param, CRITICAL_DATAS_T* value, BOOL isMin ); /*********************************************************************//** * @brief @@ -146,6 +149,9 @@ // Request the concentrate pumps mixing ratios and the DG fill mode prepare time cmdRequestDGMixingRatios(); + // Get the institutional record upon transitioning to treatment parameters + getNVRecord2Driver( GET_INSTITUTIONAL_RECORD, (U08*)&hdInstitutionalRecord, sizeof( HD_INSTITUTIONAL_RECORD_T ), 0, ALARM_ID_NO_ALARM ); + return currentTreatmentParamsState; } @@ -482,6 +488,10 @@ params.heparinType = 0; } + // Check the received arterial and venous pressure values from the UI to be checked and capped against the min and max + // values in the institutional record + checkPressureParamsRange( ¶ms ); + // Extract treatment parameters from given payload to staging array so we can more easily work with them extractTreatmentParamsFromPayload( params ); @@ -603,7 +613,7 @@ * @brief * The isTreatmentParamInRange function determines whether a given treatment * parameter is in range. - * @details Inputs: treatParamsRanges[] + * @details Inputs: treatParamsRanges[], hdInstitutionalRecord * @details Outputs: none * @param param ID of parameter to check range for * @param value value of parameter to check range for @@ -615,27 +625,105 @@ if ( param < NUM_OF_TREATMENT_PARAMS ) { - if ( CRITICAL_DATA_TYPE_U32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) + switch( param ) { - if ( value.uInt >= TREAT_PARAMS_PROPERTIES[ param ].min.uInt && value.uInt <= TREAT_PARAMS_PROPERTIES[ param ].max.uInt ) - { - result = TRUE; - } + case TREATMENT_PARAM_BLOOD_FLOW: + result = ( ( value.uInt >= hdInstitutionalRecord.minBloodFlowMLPM ) && + ( value.uInt <= hdInstitutionalRecord.maxBloodFlowMLPM ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_DIALYSATE_FLOW: + result = ( ( value.uInt >= hdInstitutionalRecord.minDialysateFlowMLPM ) && + ( value.uInt <= hdInstitutionalRecord.maxDialysateFlowMLPM ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_TREATMENT_DURATION: + result = ( ( value.uInt >= hdInstitutionalRecord.minTxDurationMIN ) && + ( value.uInt <= hdInstitutionalRecord.maxTxDurationMIN ) ? TRUE : FALSE ); + // If the 1-minute treatment is selected, it is ok to accept the time. This test configuration specifically checks for a 1-minute run + result |= ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME: + result = ( ( value.uInt >= hdInstitutionalRecord.minStopHeparinDispBeforeTxEndMIN ) && + ( value.uInt <= hdInstitutionalRecord.maxStopHeparinDispBeforeTxEndMIN ) ? TRUE : FALSE ); + // The value of the heparin pre stop time should only be checked if the heparin dispense rate in not zero. + // If the stop time is outside of range but the heparin dispense rate is 0, this item has passed regardless. + // If the stop time is outside of range and the heparin is not 0, then this item has failed. + // Staged params is directly used because the heparin dispense rate is check after the stop so we need to know about it + // prior to checking later in this switch case + result |= ( stagedParams[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].sFlt <= NEARLY_ZERO ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_SALINE_BOLUS_VOLUME: + result = ( ( value.uInt >= hdInstitutionalRecord.minSalineBolusVolumeML ) && + ( value.uInt <= hdInstitutionalRecord.maxSalineBolusVolumeML ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_DIALYSATE_TEMPERATURE: + result = ( ( value.sFlt >= hdInstitutionalRecord.minDialysateTempC ) && + ( value.sFlt <= hdInstitutionalRecord.maxDialysateTempC ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW: + result = ( ( value.sInt >= hdInstitutionalRecord.minArtPressLimitWindowMMHG ) && + ( value.sInt <= hdInstitutionalRecord.maxArtPressLimitWindowMMHG ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW: + result = ( ( value.sInt >= hdInstitutionalRecord.minVenPressLimitWindowMMHG ) && + ( value.sInt <= hdInstitutionalRecord.maxVenPressLimitWindowMMHG ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC: + result = ( ( value.sInt >= hdInstitutionalRecord.minVenAsymPressLimitMMHG ) && + ( value.sInt <= hdInstitutionalRecord.maxVenAsymPressLimitMMHG ) ? TRUE : FALSE ); + break; + + case TREATMENT_PARAM_UF_VOLUME: + result = ( ( value.sFlt >= hdInstitutionalRecord.minUFVolumeL ) && ( value.sFlt <= hdInstitutionalRecord.maxUFVolumeL ) ? TRUE : FALSE ); + result |= ( value.sFlt <= NEARLY_ZERO ? TRUE : FALSE ); // There might be a minimum UF volume set in the institutional record but a treatment with 0 vol should be allowed + break; + + case TREATMENT_PARAM_HEPARIN_DISPENSE_RATE: + result = ( ( value.sFlt >= hdInstitutionalRecord.minHeparinDispRateMLPHR ) && + ( value.sFlt <= hdInstitutionalRecord.maxHeparinDispRateMLPHR ) ? TRUE : FALSE ); + result |= ( value.sFlt <= NEARLY_ZERO ? TRUE : FALSE ); // Even if the minimum is not 0, 0 is accepted meaning heparin can be turned off + break; + + case TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME: + result = ( ( value.sFlt >= hdInstitutionalRecord.minHeparinBolusVolumeML ) && + ( value.sFlt <= hdInstitutionalRecord.maxHeparinBolusVolumeML ) ? TRUE : FALSE ); + result |= ( value.sFlt <= NEARLY_ZERO ? TRUE : FALSE ); // Even if the minimum is not 0, 0 is accepted meaning heparin can be turned off + break; + + default: +#ifndef _VECTORCAST_ + // The treatment parameters that do not have any institutional record. + // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 + // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function + // The treatment parameters that do not have any institutional record. + if ( CRITICAL_DATA_TYPE_U32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) +#endif + { + result = ( ( value.uInt >= TREAT_PARAMS_PROPERTIES[ param ].min.uInt ) && + ( value.uInt <= TREAT_PARAMS_PROPERTIES[ param ].max.uInt ) ? TRUE : FALSE ); + } +#ifndef _VECTORCAST_ + // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 + // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function + else if ( CRITICAL_DATA_TYPE_S32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) + { + result = ( ( value.sInt >= TREAT_PARAMS_PROPERTIES[ param ].min.sInt ) && + ( value.sInt <= TREAT_PARAMS_PROPERTIES[ param ].max.sInt ) ? TRUE : FALSE ); + } + else + { + result = ( ( value.sFlt >= TREAT_PARAMS_PROPERTIES[ param ].min.sFlt ) && + ( value.sFlt <= TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ) ? TRUE : FALSE ); + } +#endif } - else if ( CRITICAL_DATA_TYPE_S32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) - { - if ( value.sInt >= TREAT_PARAMS_PROPERTIES[ param ].min.sInt && value.sInt <= TREAT_PARAMS_PROPERTIES[ param ].max.sInt ) - { - result = TRUE; - } - } - else - { - if ( value.sFlt >= TREAT_PARAMS_PROPERTIES[ param ].min.sFlt && value.sFlt <= TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ) - { - result = TRUE; - } - } } else { @@ -660,7 +748,9 @@ if ( param < NUM_OF_TREATMENT_PARAMS ) { - result = TREAT_PARAMS_PROPERTIES[ param ].min.sInt; + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, TRUE ); + result = value.sInt; } else { @@ -685,7 +775,9 @@ if ( param < NUM_OF_TREATMENT_PARAMS ) { - result = TREAT_PARAMS_PROPERTIES[ param ].max.sInt; + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, FALSE ); + result = value.sInt; } else { @@ -697,6 +789,251 @@ /*********************************************************************//** * @brief + * The getU32TreatmentParamLowerRangeLimit function returns the lower range + * limit for a given unsigned integer treatment parameter. + * @details Inputs: none + * @details Outputs: none + * @param param ID of parameter to get lower range limit for + * @return lower range limit for given unsigned integer treatment parameter + *************************************************************************/ +U32 getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ) +{ + U32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, TRUE ); + result = value.uInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_U32_PARAM_MIN_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getU32TreatmentParamUpperRangeLimit function returns the upper range + * limit for a given unsigned integer treatment parameter. + * @details Inputs: none + * @details Outputs: none + * @param param ID of parameter to get upper range limit for + * @return upper range limit for given unsigned integer treatment parameter + *************************************************************************/ +U32 getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ) +{ + U32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, FALSE ); + result = value.uInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_U32_PARAM_MAX_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getF32TreatmentParamLowerRangeLimit function returns the lower range + * limit for a given float treatment parameter. + * @details Inputs: none + * @details Outputs: none + * @param param ID of parameter to get lower range limit for + * @return lower range limit for given float treatment parameter + *************************************************************************/ +F32 getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ) +{ + F32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, TRUE ); + result = value.sFlt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MIN_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getF32TreatmentParamUpperRangeLimit function returns the upper range + * limit for a given float treatment parameter. + * @details Inputs: none + * @details Outputs: none + * @param param ID of parameter to get lower range limit for + * @return upper range limit for given float treatment parameter + *************************************************************************/ +F32 getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ) +{ + F32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; + getInstitutionalRecordEdgeValue( param, &value, FALSE ); + result = value.sFlt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MAX_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getS32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details Inputs: TREAT_PARAMS_PROPERTIES + * @details Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +S32 getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + S32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sInt : TREAT_PARAMS_PROPERTIES[ param ].max.sInt ); + + return value; +} + +/*********************************************************************//** + * @brief + * The getU32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details Inputs: TREAT_PARAMS_PROPERTIES + * @details Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +U32 getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + U32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.uInt : TREAT_PARAMS_PROPERTIES[ param ].max.uInt ); + + return value; +} + +/*********************************************************************//** + * @brief + * The getF32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details Inputs: TREAT_PARAMS_PROPERTIES + * @details Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +F32 getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + F32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sFlt : TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ); + + return value; +} + +/*********************************************************************//** + * @brief + * The isNVInstitutionalRecordInRange function checks whether all the + * institutional NV records are valid and within range or not. + * @details Inputs: none + * @details Outputs: none + * @param nvInstRcrd pointer to the institutional record in the non-volatile + * data management + * @return TRUE if all of the parameters are valid otherwise, FALSE + *************************************************************************/ +BOOL isNVInstitutionalRecordInRange( HD_INSTITUTIONAL_RECORD_T* nvInstRcrd ) +{ + BOOL result = TRUE; + + result &= ( ( nvInstRcrd->minBloodFlowMLPM >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].min.uInt ) && + ( nvInstRcrd->minBloodFlowMLPM <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxBloodFlowMLPM >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].min.uInt ) && + ( nvInstRcrd->maxBloodFlowMLPM <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_BLOOD_FLOW ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minDialysateFlowMLPM >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_FLOW ].min.uInt ) && + ( nvInstRcrd->minDialysateFlowMLPM <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_FLOW ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxDialysateFlowMLPM >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_FLOW ].min.uInt ) && + ( nvInstRcrd->maxDialysateFlowMLPM <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_FLOW ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minTxDurationMIN >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_TREATMENT_DURATION ].min.uInt ) && + ( nvInstRcrd->minTxDurationMIN <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_TREATMENT_DURATION ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxTxDurationMIN >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_TREATMENT_DURATION ].min.uInt ) && + ( nvInstRcrd->maxTxDurationMIN <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_TREATMENT_DURATION ].max.uInt ) ? TRUE : FALSE ); +#ifndef _VECTORCAST_ + // The heparin stop time has been masked out from VectorCAST because the minimum time is 0 minutes while the variable is a U32 so it cannot be + // tested in VectorCAST by setting the minimum to less than 0. + result &= ( ( nvInstRcrd->minStopHeparinDispBeforeTxEndMIN >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ].min.uInt ) && + ( nvInstRcrd->minStopHeparinDispBeforeTxEndMIN <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxStopHeparinDispBeforeTxEndMIN >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ].min.uInt ) && + ( nvInstRcrd->maxStopHeparinDispBeforeTxEndMIN <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ].max.uInt ) ? TRUE : FALSE ); +#endif + result &= ( ( nvInstRcrd->minSalineBolusVolumeML >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_SALINE_BOLUS_VOLUME ].min.uInt ) && + ( nvInstRcrd->minSalineBolusVolumeML <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_SALINE_BOLUS_VOLUME ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxSalineBolusVolumeML >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_SALINE_BOLUS_VOLUME ].min.uInt ) && + ( nvInstRcrd->maxSalineBolusVolumeML <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_SALINE_BOLUS_VOLUME ].max.uInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minDialysateTempC >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_TEMPERATURE ].min.sFlt ) && + ( nvInstRcrd->minDialysateTempC <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_TEMPERATURE ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxDialysateTempC >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_TEMPERATURE ].min.sFlt ) && + ( nvInstRcrd->maxDialysateTempC <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_DIALYSATE_TEMPERATURE ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minArtPressLimitWindowMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ].min.sInt ) && + ( nvInstRcrd->minArtPressLimitWindowMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxArtPressLimitWindowMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ].min.sInt ) && + ( nvInstRcrd->maxArtPressLimitWindowMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minVenPressLimitWindowMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ].min.sInt ) && + ( nvInstRcrd->minVenPressLimitWindowMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxVenPressLimitWindowMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ].min.sInt ) && + ( nvInstRcrd->maxVenPressLimitWindowMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minVenAsymPressLimitMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ].min.sInt ) && + ( nvInstRcrd->minVenAsymPressLimitMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxVenAsymPressLimitMMHG >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ].min.sInt ) && + ( nvInstRcrd->maxVenAsymPressLimitMMHG <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ].max.sInt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minUFVolumeL >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_UF_VOLUME ].min.sFlt ) && + ( nvInstRcrd->minUFVolumeL <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_UF_VOLUME ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxUFVolumeL >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_UF_VOLUME ].min.sFlt ) && + ( nvInstRcrd->maxUFVolumeL <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_UF_VOLUME ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minHeparinDispRateMLPHR >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].min.sFlt ) && + ( nvInstRcrd->minHeparinDispRateMLPHR <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxHeparinDispRateMLPHR >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].min.sFlt ) && + ( nvInstRcrd->maxHeparinDispRateMLPHR <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->minHeparinBolusVolumeML >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].min.sFlt ) && + ( nvInstRcrd->minHeparinBolusVolumeML <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].max.sFlt ) ? TRUE : FALSE ); + result &= ( ( nvInstRcrd->maxHeparinBolusVolumeML >= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].min.sFlt ) && + ( nvInstRcrd->maxHeparinBolusVolumeML <= TREAT_PARAMS_PROPERTIES[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].max.sFlt ) ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief + * The setNVInstitutionalRecordToTxParamsRecord function sets the newly received + * institutional record from the non-volatile memory to the local copy in the + * treatment parameters. + * @details Inputs: none + * @details Outputs: hdInstitutionalRecord + * @param nvInstitutionalRecord pointer to the newly received institutional record + * in the non-volatile data management. + * @return none + *************************************************************************/ +void setNVInstitutionalRecordToTxParamsRecord( HD_INSTITUTIONAL_RECORD_T* nvInstitutionalRecord ) +{ + memcpy( &hdInstitutionalRecord, nvInstitutionalRecord, sizeof(HD_INSTITUTIONAL_RECORD_T) ); +} + +/*********************************************************************//** + * @brief * The extractTreatmentParamsFromPayload function extracts the individual * treatment parameters received from the UI into a staging array where * they will be validated and stay until user confirms them. @@ -745,15 +1082,22 @@ *************************************************************************/ BOOL setTreatmentParameterU32( TREATMENT_PARAM_T param, U32 value ) { + CRITICAL_DATAS_T integerData; BOOL result = FALSE; + integerData.uInt = value; + result = isTreatmentParamInRange( param, integerData ); + // Validate parameter if ( param <= TREATMENT_PARAM_LAST_UINT ) { - CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; - data.uInt = value; - result = setCriticalData( &treatmentParameters[ param ], data ); + data.uInt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } } else { @@ -775,15 +1119,22 @@ *************************************************************************/ BOOL setTreatmentParameterS32( TREATMENT_PARAM_T param, S32 value ) { + CRITICAL_DATAS_T unsignedIntData; BOOL result = FALSE; + unsignedIntData.sInt = value; + result = isTreatmentParamInRange( param, unsignedIntData ); + // Validate parameter if ( ( param >= TREATMENT_PARAM_FIRST_INT ) && ( param <= TREATMENT_PARAM_LAST_INT ) ) { - CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; - data.sInt = value; - result = setCriticalData( &treatmentParameters[ param ], data ); + data.sInt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } } else { @@ -805,15 +1156,22 @@ *************************************************************************/ BOOL setTreatmentParameterF32( TREATMENT_PARAM_T param, F32 value ) { + CRITICAL_DATAS_T floatData; BOOL result = FALSE; + floatData.sFlt = value; + result = isTreatmentParamInRange( param, floatData ); + // Validate parameter if ( ( param >= TREATMENT_PARAM_FIRST_F32 ) && ( param < NUM_OF_TREATMENT_PARAMS ) ) { - CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; - data.sFlt = value; - result = setCriticalData( &treatmentParameters[ param ], data ); + data.sFlt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } } else { @@ -951,7 +1309,142 @@ return ( ( origTreatmentParams.uFVolume_L * ML_PER_LITER ) / origTreatmentParams.treatmentDuration_min ); } +/*********************************************************************//** + * @brief + * The checkPressureParamsRange function checks the provided arterial and venous + * pressure values that are provided by the user + * @details Inputs: hdInstitutionalRecord + * @details Outputs: none + * @param txParams pointer to the provided treatment parameters + * @return none + *************************************************************************/ +static void checkPressureParamsRange( TREATMENT_PARAMS_DATA_PAYLOAD_T* txParams ) +{ + S32 pressureMMHG = 0; + S32 minInstitutionalMMHG = 0; + S32 maxInstitutionalMMHG = 0; + // Check arterial pressure ranges + pressureMMHG = txParams->arterialPressureLimitWindow_mmHg; + minInstitutionalMMHG = hdInstitutionalRecord.minArtPressLimitWindowMMHG; + maxInstitutionalMMHG = hdInstitutionalRecord.maxArtPressLimitWindowMMHG; + pressureMMHG = ( pressureMMHG < minInstitutionalMMHG ? minInstitutionalMMHG : pressureMMHG ); + pressureMMHG = ( pressureMMHG > maxInstitutionalMMHG ? maxInstitutionalMMHG : pressureMMHG ); + txParams->arterialPressureLimitWindow_mmHg = pressureMMHG; + + // Check venous pressure ranges + pressureMMHG = txParams->venousPressureLimitWindow_mmHg; + minInstitutionalMMHG = hdInstitutionalRecord.minVenPressLimitWindowMMHG; + maxInstitutionalMMHG = hdInstitutionalRecord.maxVenPressLimitWindowMMHG; + pressureMMHG = ( pressureMMHG < minInstitutionalMMHG ? minInstitutionalMMHG : pressureMMHG ); + pressureMMHG = ( pressureMMHG > maxInstitutionalMMHG ? maxInstitutionalMMHG : pressureMMHG ); + txParams->venousPressureLimitWindow_mmHg = pressureMMHG; + + // Check venous asymmetric ranges + pressureMMHG = txParams->venousPressureLimitAsymmetric_mmHg; + minInstitutionalMMHG = hdInstitutionalRecord.minVenAsymPressLimitMMHG; + maxInstitutionalMMHG = hdInstitutionalRecord.maxVenAsymPressLimitMMHG; + pressureMMHG = ( pressureMMHG < minInstitutionalMMHG ? minInstitutionalMMHG : pressureMMHG ); + pressureMMHG = ( pressureMMHG > maxInstitutionalMMHG ? maxInstitutionalMMHG : pressureMMHG ); + txParams->venousPressureLimitAsymmetric_mmHg = pressureMMHG; +} + +/*********************************************************************//** + * @brief + * The getInstitutionalRecordEdgeValue function returns the minimum or + * the maximum value in the HD institutional record + * @details Inputs: hdInstitutionalRecord + * @details Outputs: none + * @param txParams pointer to the provided treatment parameters + * @param value pointer the CRITICAL_DATAS_T union + * @param isMin boolean flag to indicate whether min is needed or max + * @return none + *************************************************************************/ +static void getInstitutionalRecordEdgeValue( TREATMENT_PARAM_T param, CRITICAL_DATAS_T* value, BOOL isMin ) +{ + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + switch( param ) + { + case TREATMENT_PARAM_BLOOD_FLOW: + value->uInt = ( TRUE == isMin ? hdInstitutionalRecord.minBloodFlowMLPM : hdInstitutionalRecord.maxBloodFlowMLPM ); + break; + + case TREATMENT_PARAM_DIALYSATE_FLOW: + value->uInt = ( TRUE == isMin ? hdInstitutionalRecord.minDialysateFlowMLPM : hdInstitutionalRecord.maxDialysateFlowMLPM ); + break; + + case TREATMENT_PARAM_TREATMENT_DURATION: + value->uInt = ( TRUE == isMin ? hdInstitutionalRecord.minTxDurationMIN : hdInstitutionalRecord.maxTxDurationMIN ); + break; + + case TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME: + value->uInt = ( TRUE == isMin ? hdInstitutionalRecord.minStopHeparinDispBeforeTxEndMIN : hdInstitutionalRecord.maxStopHeparinDispBeforeTxEndMIN ); + break; + + case TREATMENT_PARAM_SALINE_BOLUS_VOLUME: + value->uInt = ( TRUE == isMin ? hdInstitutionalRecord.minSalineBolusVolumeML : hdInstitutionalRecord.maxSalineBolusVolumeML ); + break; + + case TREATMENT_PARAM_DIALYSATE_TEMPERATURE: + value->sFlt = ( TRUE == isMin ? hdInstitutionalRecord.minDialysateTempC : hdInstitutionalRecord.maxDialysateTempC ); + break; + + case TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW: + value->sInt = ( TRUE == isMin ? hdInstitutionalRecord.minArtPressLimitWindowMMHG : hdInstitutionalRecord.maxArtPressLimitWindowMMHG ); + break; + + case TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW: + value->sInt = ( TRUE == isMin ? hdInstitutionalRecord.minVenPressLimitWindowMMHG : hdInstitutionalRecord.maxVenPressLimitWindowMMHG ); + break; + + case TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC: + value->sInt = ( TRUE == isMin ? hdInstitutionalRecord.minVenAsymPressLimitMMHG : hdInstitutionalRecord.maxVenAsymPressLimitMMHG ); + break; + + case TREATMENT_PARAM_UF_VOLUME: + value->sFlt = ( TRUE == isMin ? hdInstitutionalRecord.minUFVolumeL : hdInstitutionalRecord.maxUFVolumeL ); + break; + + case TREATMENT_PARAM_HEPARIN_DISPENSE_RATE: + value->sFlt = ( TRUE == isMin ? hdInstitutionalRecord.minHeparinDispRateMLPHR : hdInstitutionalRecord.maxHeparinDispRateMLPHR ); + break; + + case TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME: + value->sFlt = ( TRUE == isMin ? hdInstitutionalRecord.minHeparinBolusVolumeML : hdInstitutionalRecord.maxHeparinBolusVolumeML ); + break; + + default: +#ifndef _VECTORCAST_ + // The treatment parameters that do not have any institutional record. + // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 + // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function + if ( CRITICAL_DATA_TYPE_U32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) +#endif + { + value->uInt = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.uInt : TREAT_PARAMS_PROPERTIES[ param ].max.uInt ); + } +#ifndef _VECTORCAST_ + // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 + // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function + else if ( CRITICAL_DATA_TYPE_S32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) + { + value->sInt = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sInt : TREAT_PARAMS_PROPERTIES[ param ].max.sInt ); + } + else + { + value->sFlt = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sFlt : TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ); + } +#endif + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_PARAM, (U32)param ) + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/