Index: firmware/App/Services/NVRecordsDD.c =================================================================== diff -u -r724f9a0cf2b603e988a519420bf95f4aa4da4b93 -r1be7dc9ec7ae5a6576a4c841e3b22ac77aea8db8 --- firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 724f9a0cf2b603e988a519420bf95f4aa4da4b93) +++ firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 1be7dc9ec7ae5a6576a4c841e3b22ac77aea8db8) @@ -66,6 +66,9 @@ #define DEFAULT_BIC_TEST_ACID_SNSR_US_PER_CM 0.0F ///< Bicarb test acid sensor conductivity uS/cm. #define DEFAULT_BIC_TEST_BIC_SNSR_US_PER_CM 3890.0F ///< Bicarb test bicarb sensor conductivity uS/cm. +#define DEFAULT_MAX_RO_REJECTION_RATIO_PCT 90 ///< Max RO rejection ratio in percent. +#define DEFAULT_MIN_INLET_WATER_COND_ALARM_US_P_CM 200.0F ///< Min inlet water conductivity alarm limit in uS/cm. + #define MAX_NUM_OF_WRITE_TRIES 3U ///< Max number of write tries. #define RECORD_BYTE_SIZE(r) (sizeof(r) + sizeof(U16)) ///< Record byte size macro. @@ -85,53 +88,62 @@ /// DD calibration groups structure typedef struct { - DD_PRES_SENSORS_CAL_RECORD_T presSensorsCalRecord; ///< DG pressure sensors. - DD_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< DG flow sensors. - DD_TEMP_SENSORS_CAL_RECORD_T tempSensorsCalRecord; ///< DG temperature sensors. - DD_CONC_PUMPS_CAL_RECORD_T concentratePumpsRecord; ///< DG concentrate pumps. - DD_DRAIN_PUMP_CAL_RECORD_T drainPumpRecord; ///< DG drain pump. - DD_RO_PUMP_CAL_RECORD_T roPumpRecord; ///< DG RO pump. - DD_DRAIN_LINE_VOLUME_T drainLineVolumeRecord; ///< DG drain line volume. - DD_PRE_RO_PURGE_VOLUME_T preROPurgeVolumeRecord; ///< DG RO purge volume. - DD_GENERIC_VOLUME_RECORD_T genericVolumeRecord; ///< DG generic volume (magic number because the value is unknown). - DD_ACID_CONCENTRATES_RECORD_T acidConcentratesRecord; ///< DG acid concentrates. - DD_BICARB_CONCENTRATES_RECORD_T bicarbConcentratesRecord; ///< DG bicarb concentrates. - DD_FILTERS_CAL_RECORD_T filtersRecord; ///< DG filters. - DD_FANS_CAL_RECORD_T fansRecord; ///< DG fans. - DD_ACCEL_SENSOR_CAL_RECORD_T accelerometerSensorCalRecord; ///< DG accelerometer sensor. - DD_HEATING_CAL_RECORD_T heatingCalRecord; ///< DG heating calibration record. - DD_CHEMICALS_FILL_COND_CAL_RECORD_T fillCondCalRecord; ///< DG fill acid/bicarb target conductivities calibration record. + DD_PRES_SENSORS_CAL_RECORD_T presSensorsCalRecord; ///< DD pressure sensors. + DD_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< DD flow sensors. + DD_TEMP_SENSORS_CAL_RECORD_T tempSensorsCalRecord; ///< DD temperature sensors. + DD_CONC_PUMPS_CAL_RECORD_T concentratePumpsRecord; ///< DD concentrate pumps. + DD_DRAIN_PUMP_CAL_RECORD_T drainPumpRecord; ///< DD drain pump. + DD_RO_PUMP_CAL_RECORD_T roPumpRecord; ///< DD RO pump. + DD_DRAIN_LINE_VOLUME_T drainLineVolumeRecord; ///< DD drain line volume. + DD_PRE_RO_PURGE_VOLUME_T preROPurgeVolumeRecord; ///< DD RO purge volume. + DD_GENERIC_VOLUME_RECORD_T genericVolumeRecord; ///< DD generic volume (magic number because the value is unknown). + DD_ACID_CONCENTRATES_RECORD_T acidConcentratesRecord; ///< DD acid concentrates. + DD_BICARB_CONCENTRATES_RECORD_T bicarbConcentratesRecord; ///< DD bicarb concentrates. + DD_FILTERS_CAL_RECORD_T filtersRecord; ///< DD filters. + DD_FANS_CAL_RECORD_T fansRecord; ///< DD fans. + DD_ACCEL_SENSOR_CAL_RECORD_T accelerometerSensorCalRecord; ///< DD accelerometer sensor. + DD_HEATING_CAL_RECORD_T heatingCalRecord; ///< DD heating calibration record. + DD_CONCENTRATES_COND_CAL_RECORD_T concentratesCondCalRecord; ///< DD fill acid/bicarb target conductivities calibration record. } DD_CALIBRATION_GROUPS_T; /// DG calibration records structure typedef struct { - DD_CALIBRATION_GROUPS_T ddCalibrationGroups; ///< DG calibration groups. - U08 padding[ RECORD_PADDING_LENGTH(DD_CALIBRATION_GROUPS_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG calibration record padding byte array. + DD_CALIBRATION_GROUPS_T ddCalibrationGroups; ///< DD calibration groups. + U08 padding[ RECORD_PADDING_LENGTH(DD_CALIBRATION_GROUPS_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DD calibration record padding byte array. U16 crc; ///< CRC for the DG calibration record structure. } DD_CALIBRATION_RECORD_T; /// DG system group structure typedef struct { - DD_SYSTEM_RECORD_T ddSystemRecord; ///< DG system record. - U08 padding[ RECORD_PADDING_LENGTH(DD_SYSTEM_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG system group padding byte array. + DD_SYSTEM_RECORD_T ddSystemRecord; ///< DD system record. + U08 padding[ RECORD_PADDING_LENGTH(DD_SYSTEM_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DD system group padding byte array. U16 crc; ///< CRC for the DG system group structure. } DD_SYSTEM_GROUP_T; /// DG service record structure typedef struct { - DD_SERVICE_RECORD_T ddServiceRecord; ///< DG service record. - U08 padding[ RECORD_PADDING_LENGTH(DD_SERVICE_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG service group padding. + DD_SERVICE_RECORD_T ddServiceRecord; ///< DD service record. + U08 padding[ RECORD_PADDING_LENGTH(DD_SERVICE_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DD service group padding. U16 crc; ///< CRC for the DG service structure. } DD_SERVICE_GROUP_T; + +/// DD institutional record structure +typedef struct +{ + DD_INSTITUTIONAL_RECORD_T ddInstitutionalRecord; ///< DD institutional record. + U08 padding[ RECORD_PADDING_LENGTH(DD_INSTITUTIONAL_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DD institutional group padding. + U16 crc; ///< CRC for the HD institutional structure. +} DD_INSTITUTIONAL_GROUP_T; + /// DG usage record structure typedef struct { - DD_USAGE_INFO_RECORD_T ddUsageInfo; ///< DG usage info record. - U08 padding[ RECORD_PADDING_LENGTH(DD_USAGE_INFO_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG scheduled run group padding. + DD_USAGE_INFO_RECORD_T ddUsageInfo; ///< DD usage info record. + U08 padding[ RECORD_PADDING_LENGTH(DD_USAGE_INFO_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DD scheduled run group padding. U16 crc; ///< CRC for the DG usage info structure. } DD_USAGE_INFO_GROUP_T; @@ -140,18 +152,20 @@ // ********** private data ********** // Calibration variables -static DD_CALIBRATION_RECORD_T ddCalibrationRecord; ///< DG calibration record structure (including padding and final CRC). -static DD_SYSTEM_GROUP_T ddSystemGroup; ///< DG system group structure (including padding and final CRC). -static DD_SERVICE_GROUP_T ddServiceGroup; ///< DG service group structure (including padding and final CRC). -static DD_USAGE_INFO_GROUP_T ddUsageInfoGroup; ///< DG usage info structure (including padding and final CRC). +static DD_CALIBRATION_RECORD_T ddCalibrationRecord; ///< DD calibration record structure (including padding and final CRC). +static DD_SYSTEM_GROUP_T ddSystemGroup; ///< DD system group structure (including padding and final CRC). +static DD_SERVICE_GROUP_T ddServiceGroup; ///< DD service group structure (including padding and final CRC). +static DD_INSTITUTIONAL_GROUP_T ddInstitutionalGroup; ///< DD institutional group structure (including padding and final CRC). +static DD_USAGE_INFO_GROUP_T ddUsageInfoGroup; ///< DD usage info structure (including padding and final CRC). // Process records specifications const PROCESS_RECORD_SPECS_T RECORDS_SPECS[ NUM_OF_NVDATMGMT_RECORDS_JOBS ] = { // Start address Size of the job Max write bytes per job Max read bytes per job Record structure pointer Record CRC pointer Event calibration record update {CAL_RECORD_NV_MEM_START_ADDRESS, sizeof(DD_CALIBRATION_RECORD_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_CALIBRATION_RECORD_T), (U08*)&ddCalibrationRecord, (U08*)&ddCalibrationRecord.crc, DD_EVENT_CAL_RECORD_UPDATE }, // NVDATAMGMT_CALIBRATION_RECORD {SYSTEM_RECORD_NV_MEM_START_ADDRESS, sizeof(DD_SYSTEM_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_SYSTEM_GROUP_T), (U08*)&ddSystemGroup, (U08*)&ddSystemGroup.crc, DD_EVENT_SYSTEM_RECORD_UPDATE }, // NVDATAMGMT_SYSTEM_RECORD {SERVICE_RECORD_NV_MEM_START_ADDRESS, sizeof(DD_SERVICE_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_SERVICE_GROUP_T), (U08*)&ddServiceGroup, (U08*)&ddServiceGroup.crc, DD_EVENT_SERVICE_UPDATE }, // NVDATAMGMT_SERVICE_RECORD - {DD_USAGE_INFO_START_ADDRESS, sizeof(DD_USAGE_INFO_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_USAGE_INFO_GROUP_T), (U08*)&ddUsageInfoGroup, (U08*)&ddUsageInfoGroup.crc, DD_EVENT_USAGE_INFO_UPDATE }, // NVDATAMGMT_USAGE_INFO_RECORD + {INSTIT_RECORD_NV_MEM_START_ADDRESS, sizeof(DD_INSTITUTIONAL_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_INSTITUTIONAL_GROUP_T), (U08*)&ddInstitutionalGroup, (U08*)&ddInstitutionalGroup.crc, DD_EVENT_INSTIT_RECORD_UPDATE }, // NVDATAMGMT_INTITUTIONAL_RECORD + {USAGE_INFO_START_ADDRESS, sizeof(DD_USAGE_INFO_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_USAGE_INFO_GROUP_T), (U08*)&ddUsageInfoGroup, (U08*)&ddUsageInfoGroup.crc, DD_EVENT_USAGE_INFO_UPDATE }, // NVDATAMGMT_USAGE_INFO_RECORD }; static NVDATAMGMT_SELF_TEST_STATE_T nvDataMgmtSelfTestState; ///< NVDataMgmt self-test state variable. @@ -434,6 +448,62 @@ /*********************************************************************//** * @brief + * The isddInstitutionalRecordValid function checks the validity of the HD + * institutional record. + * @details Inputs: ddInstitutionalGroup.ddInstitutionalRecord + * @details Outputs: none + * @return TRUE if the HD institutional record is valid otherwise FALSE + *************************************************************************/ +static BOOL isddInstitutionalRecordValid( void ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16( (U08*)&ddInstitutionalGroup.ddInstitutionalRecord, sizeof( DD_INSTITUTIONAL_RECORD_T ) - sizeof( U16 ) ); + U16 recordCRC = ddInstitutionalGroup.ddInstitutionalRecord.crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default +// ddInstitutionalGroup.ddInstitutionalRecord.minBloodFlowMLPM = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_BLOOD_FLOW, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxBloodFlowMLPM = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_BLOOD_FLOW, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minDialysateFlowMLPM = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_DIALYSATE_FLOW, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxDialysateFlowMLPM = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_DIALYSATE_FLOW, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minTxDurationMIN = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_TREATMENT_DURATION, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxTxDurationMIN = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_TREATMENT_DURATION, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minStopHeparinDispBeforeTxEndMIN = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxStopHeparinDispBeforeTxEndMIN = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minSalineBolusVolumeML = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_SALINE_BOLUS_VOLUME, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxSalineBolusVolumeML = getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_SALINE_BOLUS_VOLUME, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minDialysateTempC = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_DIALYSATE_TEMPERATURE, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxDialysateTempC = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_DIALYSATE_TEMPERATURE, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minArtPressLimitWindowMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxArtPressLimitWindowMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minVenPressLimitWindowMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxVenPressLimitWindowMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minVenAsymPressLimitMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxVenAsymPressLimitMMHG = getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minUFVolumeL = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_UF_VOLUME, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxUFVolumeL = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_UF_VOLUME, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minHeparinDispRateMLPHR = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxHeparinDispRateMLPHR = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minHeparinBolusVolumeML = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME, TRUE ); +// ddInstitutionalGroup.ddInstitutionalRecord.maxHeparinBolusVolumeML = getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME, FALSE ); +// ddInstitutionalGroup.ddInstitutionalRecord.minRORejectionRatioPCT = DEFAULT_MAX_RO_REJECTION_RATIO_PCT; +// ddInstitutionalGroup.ddInstitutionalRecord.minInletWaterCondAlarmLimitUSPCM = DEFAULT_MIN_INLET_WATER_COND_ALARM_US_P_CM; +// ddInstitutionalGroup.ddInstitutionalRecord.calibrationTime = getRTCTimestamp(); +// ddInstitutionalGroup.ddInstitutionalRecord.crc = crc16 ( (U08*)&ddInstitutionalGroup.ddInstitutionalRecord, +// sizeof( DD_INSTITUTIONAL_RECORD_T ) - sizeof( U16 ) ); +// ddInstitutionalGroup.crc = crc16 ( (U08*)&ddInstitutionalGroup, sizeof( HD_INSTITUTIONAL_GROUP_T ) - sizeof( U16 ) ); + status = FALSE; + + // Institutional record failure is also considered as RTC RAM failure +// activateAlarmNoData( ALARM_ID_HD_INVALID_INSTITUTIONAL_RECORD_CRC ); + } + + return status; +} + +/*********************************************************************//** + * @brief * The isDDUsageRecordValid function checks whether the DG usage information * is valid or not. * @details Inputs: ddUsageInfoGroup @@ -599,7 +669,7 @@ isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; DD_FILL_COND_OPS_T j; - DD_CHEMICALS_FILL_COND_CAL_RECORD_T* acidBicarbTempRecord = &ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord; + DD_CONCENTRATES_COND_CAL_RECORD_T* acidBicarbTempRecord = &ddCalibrationRecord.ddCalibrationGroups.concentratesCondCalRecord; for ( i = 0; i < NUM_OF_ACID_TYPE; i++ ) { for ( j = FILL_COND_NORMAL_OP; j < NUM_OF_FILL_COND_TEST; j++ ) @@ -1150,6 +1220,32 @@ /*********************************************************************//** * @brief + * The getMinRORejectionRatioInInstitRecordPCT returns the value of the min RO + * rejection ratio in institutional record in percent + * @details Inputs: ddInstitutionalGroup + * Output: none + * @return the min RO rejection ratio in institutional record in percent + *************************************************************************/ +U32 getMinRORejectionRatioInInstitRecordPCT( void ) +{ + return ddInstitutionalGroup.ddInstitutionalRecord.minRORejectionRatioPCT; +} + +/*********************************************************************//** + * @brief + * The getMinInletWaterConductivityLimitInstitRecord returns the value of + * the inlet water conductivity alarm limit in uS/cm in institutional record + * @details Inputs: ddInstitutionalGroup + * Output: none + * @return the inlet water conductivity alarm limit in uS/cm in institutional record + *************************************************************************/ +F32 getMinInletWaterConductivityLimitInstitRecordUSPCM( void ) +{ + return ddInstitutionalGroup.ddInstitutionalRecord.minInletWaterCondAlarmLimitUSPCM; +} + +/*********************************************************************//** + * @brief * The getNVRecord2Driver function copies the requested non-volatile * data into the provided buffer by the caller. The function then checks if * the non-volatile data is valid. If the data is not valid, it raises the @@ -1271,14 +1367,14 @@ { DD_FILL_COND_OPS_T fillOps; - nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord.fillCondValues; - nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord.fillCondValues ); + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.concentratesCondCalRecord.fillCondValues; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.concentratesCondCalRecord.fillCondValues ); for ( i = 0; i < numOfSnsrs2Check; i++ ) { for ( fillOps = FILL_COND_NORMAL_OP; fillOps < NUM_OF_FILL_COND_TEST; fillOps++ ) { - isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord.fillCondValues[ i ][ fillOps ].calibrationTime ? TRUE : FALSE ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.concentratesCondCalRecord.fillCondValues[ i ][ fillOps ].calibrationTime ? TRUE : FALSE ); } } } @@ -1294,6 +1390,11 @@ nvDataLength = sizeof( ddServiceGroup.ddServiceRecord ); break; + case GET_INSTITUTIONAL_RECORD: + nvDataStartPtr = (U08*)&ddInstitutionalGroup.ddInstitutionalRecord; + nvDataLength = sizeof( ddInstitutionalGroup.ddInstitutionalRecord ); + break; + case GET_USAGE_RECORD: nvDataStartPtr = (U08*)&ddUsageInfoGroup.ddUsageInfo; nvDataLength = sizeof( ddUsageInfoGroup.ddUsageInfo ); @@ -1361,6 +1462,11 @@ status = enqueueSector0Records(); break; + case NVDATAMGMT_INTITUTIONAL_RECORD: + ddInstitutionalGroup.ddInstitutionalRecord.crc = crc; + status = enqueueSector0Records(); + break; + case NVDATAMGMT_USAGE_INFO_RECORD: ddUsageInfoGroup.ddUsageInfo.crc = crc; if ( getAvailableRecordQueueCount() > 0 )