Index: firmware/App/Services/NVRecordsDD.c =================================================================== diff -u -r1e809a81cb8831f5aa5938bd333cc374920d5b87 -r45b03b9f23005c05fc75f69416595a155e250cbe --- firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 1e809a81cb8831f5aa5938bd333cc374920d5b87) +++ firmware/App/Services/NVRecordsDD.c (.../NVRecordsDD.c) (revision 45b03b9f23005c05fc75f69416595a155e250cbe) @@ -13,8 +13,12 @@ ***************************************************************************/ #include // For memcpy +#include "Common.h" +#include "DDDefs.h" #include "NVMsgQ.h" #include "NVRecordsDD.h" +#include "NVMgmtDD.h" +#include "Timers.h" #include "Utilities.h" // For crc calculation // Data addresses and length in RTC RAM @@ -71,18 +75,6 @@ ((((RECORD_BYTE_SIZE(rcrd) / buf) + 1)) * buf) \ - RECORD_BYTE_SIZE(rcrd)) ///< DG padding length macro. - - - -/// NVDataMgmt self-test states enumeration. -typedef enum NVDataMgmt_Self_Test_States -{ - NVDATAMGMT_SELF_TEST_STATE_READ_RECORDS = 0, ///< Self test read records. - NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC, ///< Self test check CRC. - NVDATAMGMT_SELF_TEST_STATE_COMPLETE, ///< Self test complete. - NUM_OF_NVDATAMGMT_SELF_TEST_STATES ///< Total number of self-test states. -} NVDATAMGMT_SELF_TEST_STATE_T; - #pragma pack(push, 1) // ********** DD record structures ********** @@ -99,7 +91,6 @@ 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_RESERVOIR_VOLUME_RECORD_T reservoirVolumesRecord; ///< DG reservoir volumes. 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. @@ -130,31 +121,31 @@ typedef struct { DD_SERVICE_RECORD_T ddServiceRecord; ///< DG service record. - U08 padding[ RECORD_PADDING_LENGTH(DD_SERVICE_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< DG service group padding. + U08 padding[ RECORD_PADDING_LENGTH(DD_SERVICE_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG service group padding. U16 crc; ///< CRC for the DG service structure. } DD_SERVICE_GROUP_T; /// DG scheduler record structure typedef struct { DD_SCHEDULED_RUN_RECORD_T ddScheduledRun; ///< DG scheduled runs. - U08 padding[ RECORD_PADDING_LENGTH(DD_SCHEDULED_RUN_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< DG scheduled run group padding. + U08 padding[ RECORD_PADDING_LENGTH(DD_SCHEDULED_RUN_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG scheduled run group padding. U16 crc; ///< CRC for the DG scheduled runs structure. } DD_SCHEDULED_RUNS_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_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< DG scheduled run group padding. + U08 padding[ RECORD_PADDING_LENGTH(DD_USAGE_INFO_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG scheduled run group padding. U16 crc; ///< CRC for the DG usage info structure. } DD_USAGE_INFO_GROUP_T; /// DG heaters record typedef struct { DD_HEATERS_RECORD_T ddHeatersInfo; ///< DG heaters info record. - U08 padding[ RECORD_PADDING_LENGTH(DD_HEATERS_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< DG heater info group padding. + U08 padding[ RECORD_PADDING_LENGTH(DD_HEATERS_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< DG heater info group padding. U16 crc; ///< CRC for the DG heaters info structure. } DD_HEATERS_INFO_GROUP_T; @@ -165,7 +156,7 @@ DD_SW_CONFIG_RECORD_T ddSWConfigsRecord; ///< Software configurations record. // Since the software configurations are one byte, Num_of was used for the length of the lists - U08 padding[ RECORD_PADDING_LENGTH(DD_SW_CONFIG_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< Software configurations group padding. + U08 padding[ RECORD_PADDING_LENGTH(DD_SW_CONFIG_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) ]; ///< Software configurations group padding. U16 crc; ///< Software configurations CRC. } DD_SW_CONFIG_GROUP_T; #endif @@ -183,6 +174,20 @@ static DD_SW_CONFIG_GROUP_T ddSWConfigGroup; ///< DG Software configurations structure(including padding and final CRC). #endif +// 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_SCHEDULED_RUNS_START_ADDRESS, sizeof(DD_SCHEDULED_RUNS_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_SCHEDULED_RUNS_GROUP_T),(U08*)&ddScheduledRunsGroup, (U08*)&ddScheduledRunsGroup.crc, DD_EVENT_SCHEDULED_RUNS_UPDATE }, // NVDATAMGMT_SCHEDULER_RECORD + {DD_HEATERS_INFO_START_ADDRESS, sizeof(DD_HEATERS_INFO_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_HEATERS_INFO_GROUP_T), (U08*)&ddHeatersInfoGroup, (U08*)&ddHeatersInfoGroup.crc, DD_EVENT_HEATERS_INFO_UPDATE }, // NVDATAMGMT_HEATERS_INFO_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 +#ifndef _RELEASE_ + {SW_CONFIGS_START_ADDRESS, sizeof(DD_SW_CONFIG_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DD_SW_CONFIG_GROUP_T), (U08*)&ddSWConfigGroup, (U08*)&ddSWConfigGroup.crc, DD_EVENT_SW_CONFIG_UPDATE } // NVDATAMGMT_SW_CONFIG_RECORD +#endif +}; + static NVDATAMGMT_SELF_TEST_STATE_T nvDataMgmtSelfTestState; ///< NVDataMgmt self-test state variable. static SELF_TEST_STATUS_T nvDataMgmtSelfTestResult; ///< NVDataMgmt self-test result. static U32 usageWriteTries; ///< Usage write tries. @@ -201,14 +206,14 @@ static BOOL isDDROPumpRecordValid( DD_RO_PUMP_CAL_RECORD_T* record ); static BOOL isDDPreROPurgeVolumeRecordValid( DD_PRE_RO_PURGE_VOLUME_T* record ); static BOOL isDDDrainLineVolRecordValid( DD_DRAIN_LINE_VOLUME_T* record ); -static BOOL isDDReservoirVolRecordValid( DD_RESERVOIR_VOLUME_DATA_T* record ); static BOOL isDDGenericVolRecordValid( DD_GENERIC_VOLUME_DATA_T* record ); static BOOL isDDAcidConcentrateRecordValid( DD_ACID_CONCENTRATE_T* record ); static BOOL isDDBicarbConcentrateRecordValid( DD_BICARB_CONCENTRATE_T* record ); static BOOL isDDFilterRecordValid( DD_FILTER_CAL_RECORD_T* record ); static BOOL isDDFanRecordValid( DD_FAN_CAL_RECORD_T* record ); static BOOL isDDAccelerometerSensorRecordValid( DD_ACCEL_SENSOR_CAL_RECORD_T* record ); static BOOL isDDHeatingCalRecordValid( DD_HEATING_CAL_RECORD_T* record ); +static BOOL isDDFillConductiviesRecordValid( DD_ACID_BICARB_FILL_COND_VALUES_T* record, DD_ACID_TYPES_T acidType, DD_FILL_COND_OPS_T operation ); #ifndef _RELEASE_ static BOOL isSWConfigRecordValid( void ); #endif @@ -254,6 +259,11 @@ return nvDataMgmtSelfTestResult; } +PROCESS_RECORD_SPECS_T getProcessRecord( RECORD_JOBS_STATE_T job ) +{ + return RECORDS_SPECS[ job ]; +} + /*********************************************************************//** * @brief * The handleSelfTestReadRecords waits for the records to be read @@ -267,9 +277,9 @@ // Check if the queues are empty and the exec state machine is in Idle meaning all the records have been read and the state machine // is back at Idle so even the last job in the queue has been processed - if ( ( TRUE == isRecordQueueEmpty() ) && ( NVDATAMGMT_EXEC_STATE_IDLE == nvDataMgmtExecState ) ) + if ( ( TRUE == isRecordQueueEmpty() ) && ( TRUE == isNVExecStateIdle() ) ) { - recordsReadStatus = NVDATAMGMT_RECORDS_READ; + updateRecordReadStatus( NVDATAMGMT_RECORDS_READ ); state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; } @@ -295,7 +305,7 @@ BOOL hasSWConfigRecordPassed = TRUE; BOOL hasUsageRecordPassed = TRUE; - recordsReadStatus = NVDATAMGMT_RECORDS_CRC_CHECKED; + updateRecordReadStatus( NVDATAMGMT_RECORDS_CRC_CHECKED ); // Check all the calibration groups haveCalGroupsPassed = isDDCalibrationRecordValid(); @@ -334,8 +344,8 @@ // Check if the records' entire CRCs as well as the individual CRCs passed if ( ( TRUE == haveCalGroupsPassed ) && ( TRUE == hasSystemRecordPassed ) && ( TRUE == hasServiceRecordPassed ) && ( TRUE == hasInstitutionalRecordPassed ) ) { - newCalStartTimer = getMSTimerCount(); - isNewCalAvailable = TRUE; + updateCalStartTimer( getMSTimerCount() ); + updateNewCalAvailableFlag( TRUE ); nvDataMgmtSelfTestResult = SELF_TEST_STATUS_PASSED; } @@ -487,7 +497,7 @@ // CRC did not pass so set all values to default ddServiceGroup.ddServiceRecord.lastServiceEpochDate = 0; ddServiceGroup.ddServiceRecord.serviceIntervalSeconds = RECORD_DEFAULT_SERVICE_INTERVAL_S; - ddServiceGroup.ddServiceRecord.lastResetTimeEpoch = getRTCTimestamp(); +// ddServiceGroup.ddServiceRecord.lastResetTimeEpoch = getRTCTimestamp(); ddServiceGroup.ddServiceRecord.crc = crc16 ( (U08*)&ddServiceGroup.ddServiceRecord, sizeof( DD_SERVICE_RECORD_T ) - sizeof( U16 ) ); ddServiceGroup.crc = crc16 ( (U08*)&ddServiceGroup, sizeof( DD_SERVICE_GROUP_T ) - sizeof( U16 ) ); status = FALSE; @@ -519,7 +529,7 @@ ddUsageInfoGroup.ddUsageInfo.lastHeatDisCompleteDateEpoch = 0; ddUsageInfoGroup.ddUsageInfo.roWaterGenSinceLastServiceL = 0.0F; ddUsageInfoGroup.ddUsageInfo.roWaterGenTotalL = 0.0F; - ddUsageInfoGroup.ddUsageInfo.lastResetTimeEpoch = getRTCTimestamp(); +// ddUsageInfoGroup.ddUsageInfo.lastResetTimeEpoch = getRTCTimestamp(); ddUsageInfoGroup.ddUsageInfo.crc = crc16( (U08*)&ddUsageInfoGroup.ddUsageInfo, sizeof( DD_USAGE_INFO_RECORD_T ) - sizeof( U16 ) ); ddUsageInfoGroup.crc = crc16( (U08*)&ddUsageInfoGroup, sizeof( DD_USAGE_INFO_GROUP_T ) - sizeof( U16 ) ); status = FALSE; @@ -635,13 +645,6 @@ isHardwareRecordValid = isDDDrainLineVolRecordValid( drainLineVol ); isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; - DD_RESERVOIR_VOLUME_RECORD_T* reservoirVol = &ddCalibrationRecord.ddCalibrationGroups.reservoirVolumesRecord; - for ( i = 0; i < NUM_OF_CAL_DATA_RSRVRS; i++ ) - { - isHardwareRecordValid = isDDReservoirVolRecordValid( &reservoirVol->reservoir[ i ] ); - isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; - } - DD_GENERIC_VOLUME_RECORD_T* genericVol = &ddCalibrationRecord.ddCalibrationGroups.genericVolumeRecord; for ( i = 0; i < GENERIC_VOL_RESERVED_SPACE_COUNT; i++ ) { @@ -844,38 +847,6 @@ /*********************************************************************//** * @brief - * The isDDReservoirVolRecordValid function checks whether the calibration - * record of reservoir volume is valid or not. - * @details Inputs: none - * @details Outputs: none - * @param record: DD_RESERVOIR_VOLUME_DATA_T pointer - * @return TRUE if the record is valid otherwise FALSE - *************************************************************************/ -static BOOL isDDReservoirVolRecordValid( DD_RESERVOIR_VOLUME_DATA_T* record ) -{ - BOOL status = TRUE; - U16 calcCRC = crc16 ( (U08*)record, sizeof(DD_RESERVOIR_VOLUME_DATA_T) - sizeof(U16) ); - U16 recordCRC = record->crc; - - if ( calcCRC != recordCRC ) - { - // CRC did not pass so set all values to default - record->maxResidualFluid = RECORD_DEFAULT_CONST; - record->normalFillVolume = RECORD_DEFAULT_CONST; - record->rsrvrUnfilledWeight = EMPTY_RESERVOIR_WEIGHT_GRAMS; - record->rsrvrVolume = RECORD_DEFAULT_CONST; - record->calibrationTime = RECORD_DEFAULT_TIME; - record->crc = crc16 ( (U08*)record, sizeof(DD_RESERVOIR_VOLUME_DATA_T) - sizeof(U16) ); - - // Set the to FALSE since the record is not valid - status = FALSE; - } - - return status; -} - -/*********************************************************************//** - * @brief * The isDDGenericVolRecordValid function checks whether the calibration * record of generic volume is valid or not. * @details Inputs: none @@ -1086,6 +1057,99 @@ /*********************************************************************//** * @brief + * The isDGFillConductiviesRecordValid function checks whether fill conductivity + * record is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_ACID_BICARB_FILL_COND_VALUES_T pointer containing the + * fill conductivities of acid and bicrab + * @param operation which is the type fill operation that is check (e.g. normal ops) + * @param acidType whcih is the type of acid that its values are checked (e.g. 0-1251-1) + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDDFillConductiviesRecordValid( DD_ACID_BICARB_FILL_COND_VALUES_T* record, DD_ACID_TYPES_T acidType, DD_FILL_COND_OPS_T operation ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DD_ACID_BICARB_FILL_COND_VALUES_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + F32 acidSensorCond = 0.0F; + F32 bicarbSensorCond = 0.0F; + + switch ( operation ) + { + case FILL_COND_NORMAL_OP: + switch ( acidType ) + { + case ACID_08_1251_1: + acidSensorCond = DEFAULT_FILL_1251_1_ACID_SNSR_US_PER_CM; + bicarbSensorCond = DEFAULT_FILL_1251_1_BIC_SNSR_US_PER_CM; + break; + + case ACID_08_2251_0: + acidSensorCond = DEFAULT_FILL_2251_0_ACID_SNSR_US_PER_CM; + bicarbSensorCond = DEFAULT_FILL_2251_0_BIC_SNSR_US_PER_CM; + break; + + case ACID_08_3251_9: + acidSensorCond = DEFAULT_FILL_3251_9_ACID_SNSR_US_PER_CM; + bicarbSensorCond = DEFAULT_FILL_3251_9_BIC_SNSR_US_PER_CM; + break; + + default: + // TODO software fault + break; + } + break; + + case FILL_COND_ACID_TEST: + switch ( acidType ) + { + case ACID_08_1251_1: + acidSensorCond = DEFAULT_ACID_TEST_1251_1_US_PER_CM; + bicarbSensorCond = DEFAULT_ACID_TEST_1251_1_US_PER_CM; + break; + + case ACID_08_2251_0: + acidSensorCond = DEFAULT_ACID_TEST_2251_0_US_PER_CM; + bicarbSensorCond = DEFAULT_ACID_TEST_2251_0_US_PER_CM; + break; + + case ACID_08_3251_9: + acidSensorCond = DEFAULT_ACID_TEST_3251_9_US_PER_CM; + bicarbSensorCond = DEFAULT_ACID_TEST_3251_9_US_PER_CM; + break; + + default: + // TODO software fault + break; + } + break; + + case FILL_COND_BICARB_TEST: + acidSensorCond = DEFAULT_BIC_TEST_ACID_SNSR_US_PER_CM; + bicarbSensorCond = DEFAULT_BIC_TEST_BIC_SNSR_US_PER_CM; + break; + } + + // CRC did not pass so set all values to default + record->acidConduSPerCM = acidSensorCond; + record->bicarbConduSPerCM = bicarbSensorCond; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DD_ACID_BICARB_FILL_COND_VALUES_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + + +/*********************************************************************//** + * @brief * The setLastDisinfectDate sets a queue job to write the last time that DG * was disinfected. * @details Inputs: dgUsageInfoGroup @@ -1094,49 +1158,49 @@ * @param epochTime last disinfect time in epoch * @return TRUE if queue is not full *************************************************************************/ -BOOL setLastDisinfectDate( DG_USAGE_INFO_ITEMS_T disinfect, U32 epochTime ) +BOOL setLastDisinfectDate( DD_USAGE_INFO_ITEMS_T disinfect, U32 epochTime ) { BOOL status = FALSE; - if ( FALSE == isQueueFull() ) + if ( FALSE == isRecordQueueFull() ) { switch ( disinfect ) { case USAGE_INFO_BASIC_FLUSH: - dgUsageInfoGroup.dgUsageInfo.lastBasicFlushCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastBasicFlushCompleteDateEpoch = epochTime; break; case USAGE_INFO_CHEM_DIS_START: - dgUsageInfoGroup.dgUsageInfo.lastChemDisStartDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastChemDisStartDateEpoch = epochTime; break; case USAGE_INFO_CHEM_DIS: - dgUsageInfoGroup.dgUsageInfo.lastChemDisCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastChemDisCompleteDateEpoch = epochTime; break; case USAGE_INFO_CHEM_FLUSH: - dgUsageInfoGroup.dgUsageInfo.lastChemDisFlushCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastChemDisFlushCompleteDateEpoch = epochTime; break; case USAGE_INFO_HEAT_DIS: - dgUsageInfoGroup.dgUsageInfo.lastHeatDisCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastHeatDisCompleteDateEpoch = epochTime; break; case USAGE_INFO_FILTER_FLUSH: - dgUsageInfoGroup.dgUsageInfo.lastFilterFlushCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastFilterFlushCompleteDateEpoch = epochTime; break; case USAGE_INFO_HEAT_DIS_ACTIVE_COOL: - dgUsageInfoGroup.dgUsageInfo.lastHeatActiveCoolCompleteDateEpoch = epochTime; + ddUsageInfoGroup.ddUsageInfo.lastHeatActiveCoolCompleteDateEpoch = epochTime; break; default: // SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_USAGE_INFO_SELECTED, disinfect ); break; } - dgUsageInfoGroup.dgUsageInfo.crc = crc16( (U08*)&dgUsageInfoGroup.dgUsageInfo, sizeof( DG_USAGE_INFO_RECORD_T ) - sizeof( U16 ) ); - dgUsageInfoGroup.crc = crc16( (U08*)&dgUsageInfoGroup, sizeof( DG_USAGE_INFO_GROUP_T ) - sizeof( U16 ) ); + ddUsageInfoGroup.ddUsageInfo.crc = crc16( (U08*)&ddUsageInfoGroup.ddUsageInfo, sizeof( DD_USAGE_INFO_RECORD_T ) - sizeof( U16 ) ); + ddUsageInfoGroup.crc = crc16( (U08*)&ddUsageInfoGroup, sizeof( DD_USAGE_INFO_GROUP_T ) - sizeof( U16 ) ); usageWriteTries = 0; status = TRUE; @@ -1171,7 +1235,7 @@ // In HD the treatment time since last service is reset to 0 // In DG the RO water generation since the last service in reset to 0 - ddServiceGroup.ddServiceRecord.lastServiceEpochDate = getRTCTimestamp(); +// ddServiceGroup.ddServiceRecord.lastServiceEpochDate = getRTCTimestamp(); ddServiceGroup.ddServiceRecord.crc = crc16( (U08*)&ddServiceGroup.ddServiceRecord, sizeof( DD_SERVICE_RECORD_T ) - sizeof( U16 ) ); ddServiceGroup.crc = crc16( (U08*)&ddServiceGroup, sizeof( DD_SERVICE_GROUP_T ) - sizeof( U16 ) ); // Update the DG usage info @@ -1191,3 +1255,292 @@ return status; } + +/*********************************************************************//** + * @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 + * provided alarm by the caller. + * @details Inputs: ddCalibrationRecord + * @details Outputs: ddCalibrationRecord + * @param nvData the non-volatile data to be copied + * @param bufferAddress the address of the provided buffer by the caller + * @param bufferLength the length of the provided buffer by the caller + * @param numOfSnsrs2Check the number of sensors to check in a array of sensors called + * @param nvAlarm the corresponding alarm of the non-volatile data to be raised + * if the data is not valid + * @return TRUE if the non-volatile data is valid otherwise, FALSE + *************************************************************************/ +BOOL getNVRecord2Driver( NV_DATA_T nvData, U08* bufferAddress, U32 bufferLength, U08 numOfSnsrs2Check, ALARM_ID_T nvAlarm ) +{ + U08 i; + U08* nvDataStartPtr = 0; + BOOL isNVDataInvalid = FALSE; + U32 nvDataLength = 0; + + switch ( nvData ) + { + + case GET_CAL_PRESSURE_SENOSRS: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.presSensorsCalRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.presSensorsCalRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.presSensorsCalRecord.pressureSensors[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_LOAD_CELL_SENSORS: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.loadCellsCalRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.loadCellsCalRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.loadCellsCalRecord.loadCells[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_FLOW_SENSORS: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.flowSensorsCalRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.flowSensorsCalRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.flowSensorsCalRecord.flowSensors[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_ACID_CONCENTREATES: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.acidConcentratesRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.acidConcentratesRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.acidConcentratesRecord.acidConcentrate[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_BICARB_CONCENTRATES: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.bicarbConcentratesRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.bicarbConcentratesRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.bicarbConcentratesRecord.bicarbConcentrate[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_ACCEL_SENSORS: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.accelerometerSensorCalRecord; + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.accelerometerSensorCalRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_TEMP_SENSORS: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.tempSensorsCalRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.tempSensorsCalRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.tempSensorsCalRecord.tempSensors[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_HEATING_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.heatingCalRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.heatingCalRecord ); + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.heatingCalRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_DRAIN_LINE_VOLUME_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.drainLineVolumeRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.drainLineVolumeRecord ); + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.drainLineVolumeRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_RO_PUMP_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.roPumpRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.roPumpRecord ); + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.roPumpRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_CONCENTRATE_PUMPS_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.concentratePumpsRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.concentratePumpsRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.concentratePumpsRecord.concentratePumps[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_DRAIN_PUMP_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.drainPumpRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.drainPumpRecord ); + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.drainPumpRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_FANS_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.fansRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.fansRecord ); + for ( i = 0; i < numOfSnsrs2Check; i++ ) + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.fansRecord.fans[ i ].calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_PRE_RO_PURGE_VOLUME_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.preROPurgeVolumeRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.preROPurgeVolumeRecord ); + isNVDataInvalid = ( 0 == ddCalibrationRecord.ddCalibrationGroups.preROPurgeVolumeRecord.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_FILTERS_RECORD: + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.filtersRecord; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.filtersRecord ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.filtersRecord.carbonFilter.calibrationTime ? TRUE : FALSE ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.filtersRecord.carbonPolishFilter.calibrationTime ? TRUE : FALSE ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.filtersRecord.roFilter.calibrationTime ? TRUE : FALSE ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.filtersRecord.sedimentFilter.calibrationTime ? TRUE : FALSE ); + isNVDataInvalid |= ( 0 == ddCalibrationRecord.ddCalibrationGroups.filtersRecord.ultraFilter.calibrationTime ? TRUE : FALSE ); + break; + + case GET_CAL_FILL_CONDUCTIVITIES_RECORD: + { + DD_FILL_COND_OPS_T fillOps; + + nvDataStartPtr = (U08*)&ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord.fillCondValues; + nvDataLength = sizeof( ddCalibrationRecord.ddCalibrationGroups.fillCondCalRecord.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 ); + } + } + } + break; + + case GET_INF_HEATERS_RECORD: + nvDataStartPtr = (U08*)&ddHeatersInfoGroup.ddHeatersInfo; + nvDataLength = sizeof( ddHeatersInfoGroup.ddHeatersInfo ); + break; + + case GET_SYS_RECORD: + nvDataStartPtr = (U08*)&ddSystemGroup.ddSystemRecord; + nvDataLength = sizeof( ddSystemGroup.ddSystemRecord ); + break; + + case GET_SRV_RECORD: + nvDataStartPtr = (U08*)&ddServiceGroup.ddServiceRecord; + nvDataLength = sizeof( ddServiceGroup.ddServiceRecord ); + break; + + case GET_SRR_RECORD: + nvDataStartPtr = (U08*)&ddScheduledRunsGroup.ddScheduledRun; + nvDataLength = sizeof( ddScheduledRunsGroup.ddScheduledRun ); + break; + + case GET_USAGE_RECORD: + nvDataStartPtr = (U08*)&ddUsageInfoGroup.ddUsageInfo; + nvDataLength = sizeof( ddUsageInfoGroup.ddUsageInfo ); + break; + + default: +// SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_NV_RECORD_SELECTED, nvData ); + break; + } + + // Make sure the provided buffer length is >= NV Data Length in the NV data management so the memory of the other variables is not + // overridden. + if ( ( bufferLength >= nvDataLength ) && ( nvDataStartPtr != 0 ) ) + { + // Copy the data into the provided buffer + memcpy( bufferAddress, nvDataStartPtr, bufferLength ); + } + + // Check if the non-volatile data is valid and if not raise the alarm + if ( TRUE == isNVDataInvalid ) + { + // If no alarm has been provided to raise, just set the variable as TRUE + if ( ALARM_ID_NO_ALARM == nvAlarm ) + { + isNVDataInvalid = FALSE; + } + else + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAL_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + activateAlarmNoData( nvAlarm ); + } +#ifndef _RELEASE_ + else + { + isNVDataInvalid = FALSE; + } +#endif + } + } + + // Reverse the polarity to signal the outside users that the calibration has passed. + return ( FALSE == isNVDataInvalid ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief + * The testSetNVRecordCRCOverride overrides the non-volatile record CRC override. + * @details Inputs: none + * @details Outputs: none + * @param job the job to override its CRC (i.e. calibration record) + * @param crc the value its CRC to be overridden + * @return TRUE if the job was scheduled successfully otherwise, FALSE + *************************************************************************/ +BOOL testSetNVRecordCRCOverride( U32 job, U16 crc ) +{ + BOOL status = FALSE; + RECORD_JOBS_STATE_T nvJob = (RECORD_JOBS_STATE_T)job; + + switch( nvJob ) + { + case NVDATAMGMT_CALIBRATION_RECORD: + ddCalibrationRecord.crc = crc; + status = enqueueSector0Records(); + break; + + case NVDATAMGMT_SYSTEM_RECORD: + ddSystemGroup.ddSystemRecord.crc = crc; + status = enqueueSector0Records(); + break; + + case NVDATAMGMT_SERVICE_RECORD: + ddServiceGroup.ddServiceRecord.crc = crc; + status = enqueueSector0Records(); + break; + + case NVDATAMGMT_USAGE_INFO_RECORD: + ddUsageInfoGroup.ddUsageInfo.crc = crc; + if ( getAvailableRecordQueueCount() > 0 ) + { + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_USAGE_INFO_RECORD ); + status = TRUE; + } + break; + + } + + return status; +} + +void updateNVSelfTestResult( SELF_TEST_STATUS_T result ) +{ + nvDataMgmtSelfTestResult = result; +} + +void updateNVSelfTestState( NVDATAMGMT_SELF_TEST_STATE_T state ) +{ + nvDataMgmtSelfTestState = state; +} + +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The getSoftwareConfigStatus function returns the status of a software + * configuration. + * @details Inputs: swConfigsList + * @details Outputs: none + * @param config which is the configuration of the that its status is requested + * @return status of the software configuration (0 or 1) + *************************************************************************/ +U08 getSoftwareConfigStatus( SOFTWARE_CONFIG_T config ) +{ + U08 value = 0; + + // If the build is not a release, get the value from the software configurations list + // If the build is a release, the configuration not matter what its value is kept in + // the NV RAM, it returns a 0 which is the configuration is disabled + value = ddSWConfigGroup.ddSWConfigsRecord.swConfigs[ config ]; + + return value; +} +#endif