Index: NVDataMgmt.c =================================================================== diff -u -r66600859e4fb3036f48901aae8c9845f37e3e707 -r5ae8aa4f20756e41805c0259c4e5b7f56f523240 --- NVDataMgmt.c (.../NVDataMgmt.c) (revision 66600859e4fb3036f48901aae8c9845f37e3e707) +++ NVDataMgmt.c (.../NVDataMgmt.c) (revision 5ae8aa4f20756e41805c0259c4e5b7f56f523240) @@ -8,7 +8,7 @@ * @file NVDataMgmt.c * * @author (last) Dara Navaei -* @date (last) 02-Mar-2022 +* @date (last) 31-Mar-2022 * * @author (original) Dara Navaei * @date (original) 12-Feb-2020 @@ -74,8 +74,8 @@ // Data addresses and length in RTC RAM #define LOG_RECORD_START_ADDRESS 0x00000000 // 0 ///< Log record start address in RTC RAM (0). -#define HD_TREATMENT_TIME_ADDRESS 0x00000010 // 16 ///< HD treatment time start address in RTC RAM (16). -#define DG_CONSUMED_WATER_ADDRESS 0x00000020 // 32 ///< DG water consumption start address in RTC RAM (32). +#define HD_USAGE_INFO_START_ADDRESS 0x00000010 // 16 ///< HD usage info start address in RTC RAM (16). +#define DG_USAGE_INFO_START_ADDRESS 0x00000020 // 32 ///< DG usage info start address in RTC RAM (32). #define SERVICE_RECORD_START_ADDRESS 0x00000030 // 48 ///< Service date record start address in RTC RAM (HD/DG) (48). #define DG_SCHEDULED_RUNS_START_ADDRESS (SERVICE_RECORD_START_ADDRESS + sizeof(DG_SERVICE_GROUP_T)) ///< DG scheduled runs start address in RTC RAM. #define DG_HEATERS_INFO_START_ADDRESS (DG_SCHEDULED_RUNS_START_ADDRESS + sizeof(DG_HEATERS_INFO_GROUP_T))///< DG heaters info start address in RTC RAM. @@ -106,13 +106,13 @@ - RECORD_BYTE_SIZE(rcrd)) /// DG padding length macro. #define RECORD_DEFAULT_TIME 0U ///< Record default time (calibration/set). -#define RECORD_FOURTH_ORDER_COEFF 0.0 ///< Record fourth order coefficient. -#define RECORD_THIRD_ORDER_COEFF 0.0 ///< Record third order coefficient. -#define RECORD_SECOND_ORDER_COEFF 0.0 ///< Record second order coefficient. -#define RECORD_DEFAULT_GAIN 1.0 ///< Record default gain. -#define RECORD_DEFAULT_OFFSET 0.0 ///< Record default offset. -#define RECORD_DEFAULT_CONST 0.0 ///< Record default constant. -#define RECORD_DEFAULT_RATIO 1.0 ///< Record default ratio. +#define RECORD_FOURTH_ORDER_COEFF 0.0F ///< Record fourth order coefficient. +#define RECORD_THIRD_ORDER_COEFF 0.0F ///< Record third order coefficient. +#define RECORD_SECOND_ORDER_COEFF 0.0F ///< Record second order coefficient. +#define RECORD_DEFAULT_GAIN 1.0F ///< Record default gain. +#define RECORD_DEFAULT_OFFSET 0.0F ///< Record default offset. +#define RECORD_DEFAULT_CONST 0.0F ///< Record default constant. +#define RECORD_DEFAULT_RATIO 1.0F ///< Record default ratio. // The service record interval is equivalent to 6 months #define RECORD_DEFAULT_SERVICE_INTERVAL_S 15768000U ///< Record default service interval in seconds. #define RECORD_DEFAULT_CHARACTER ' ' ///< Record default character. @@ -127,16 +127,16 @@ // DG specific defines #ifdef _DG_ -#define FLUSH_LINES_DEFAULT_VOLUME_L 0.01 ///< Water volume to flush when starting re-circulate mode in liters. +#define FLUSH_LINES_DEFAULT_VOLUME_L 0.01F ///< Water volume to flush when starting re-circulate mode in liters. #define ACID_CONC_DEFAULT_MIXING_RATIO ( 2.35618 / FRACTION_TO_PERCENT_FACTOR ) ///< Ratio between RO water and acid concentrate mixing ratio. #define BICARB_CONC_DEFAULT_MIXING_RATIO ( 4.06812 / FRACTION_TO_PERCENT_FACTOR ) ///< Ratio between RO water and bicarbonate concentrate mixing ratio. #define PRES_SENSORS_RESERVED_SPACE_COUNT 6 ///< Pressure sensors reserved space count. #define FLOW_SENSROS_RESERVED_SPACE_COUNT 2 ///< Flow sensors reserved space count. #define TEMP_SENSORS_RESERVED_SPACE_COUNT 5 ///< Temperature sensors reserved space count. #define COND_SENSORS_RESERVED_SPACE_COUNT 2 ///< Conductivity sensors reserved space count. #define GENERIC_VOL_RESERVED_SPACE_COUNT 4 ///< Generic volumes reserved space count. -#define RESERVOIR_TEMPERATURE_TAU_C_PER_MIN -0.512 ///< Reservoir temperature time constant C/min. -#define ULTRAFILTER_TEMPERATURE_TAU_C_PER_MIN -4.565 ///< Ultrafilter temperature time constant C/min. +#define RESERVOIR_TEMPERATURE_TAU_C_PER_MIN -0.512F ///< Reservoir temperature time constant C/min. +#define ULTRAFILTER_TEMPERATURE_TAU_C_PER_MIN -4.565F ///< Ultrafilter temperature time constant C/min. #define ULTRAFILTER_VOLUME_ML 700 ///< Ultrafilter volume in milliliters. #endif @@ -347,15 +347,18 @@ U16 crc; ///< CRC for the DG heaters info structure. } DG_HEATERS_INFO_GROUP_T; +#ifndef _RELEASE_ /// DG software configurations group typedef struct { DG_SW_CONFIG_RECORD_T dgSWConfigsRecord; ///< 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(DG_SW_CONFIG_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< Software configurations group padding. U16 crc; ///< Software configurations CRC. } DG_SW_CONFIG_GROUP_T; #endif +#endif #ifdef _HD_ /// HD calibration groups structure @@ -403,6 +406,7 @@ U16 crc; ///< CRC for the HD usage info structure. } HD_USAGE_INFO_GROUP_T; +#ifndef _RELEASE_ /// HD software configurations group typedef struct { @@ -411,6 +415,7 @@ U08 padding[ RECORD_PADDING_LENGTH(HD_SW_CONFIG_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) ]; ///< Software configurations group padding. U16 crc; ///< Software configurations CRC. } HD_SW_CONFIG_GROUP_T; +#endif #endif #pragma pack(pop) @@ -423,16 +428,21 @@ static DG_SCHEDULED_RUNS_GROUP_T dgScheduledRunsGroup; ///< DG scheduled run structure (including padding and final CRC). static DG_USAGE_INFO_GROUP_T dgUsageInfoGroup; ///< DG usage info structure (including padding and final CRC). static DG_HEATERS_INFO_GROUP_T dgHeatersInfoGroup; ///< DG heaters info structure (including padding and final CRC). +#ifndef _RELEASE_ static DG_SW_CONFIG_GROUP_T dgSWConfigGroup; ///< 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 ] = { {CAL_RECORD_NV_MEM_START_ADDRESS, sizeof(DG_CALIBRATION_RECORD_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DG_CALIBRATION_RECORD_T), (U08*)&dgCalibrationRecord, (U08*)&dgCalibrationRecord.crc, NVDATAMGMT_EEPROM}, // NVDATAMGMT_CALIBRATION_RECORD {SYSTEM_RECORD_NV_MEM_START_ADDRESS, sizeof(DG_SYSTEM_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(DG_SYSTEM_GROUP_T), (U08*)&dgSystemGroup, (U08*)&dgSystemGroup.crc, NVDATAMGMT_EEPROM}, // NVDATAMGMT_SYSTEM_RECORD {SERVICE_RECORD_START_ADDRESS, sizeof(DG_SERVICE_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgServiceGroup, (U08*)&dgServiceGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_SERVICE_RECORD +#ifndef _RELEASE_ {SW_CONFIGS_START_ADDRESS, sizeof(DG_SW_CONFIG_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgSWConfigGroup, (U08*)&dgSWConfigGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_SW_CONFIG_RECORD +#endif {DG_SCHEDULED_RUNS_START_ADDRESS, sizeof(DG_SCHEDULED_RUNS_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgScheduledRunsGroup, (U08*)&dgScheduledRunsGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_SCHEDULER_RECORD - {DG_HEATERS_INFO_START_ADDRESS, sizeof(DG_HEATERS_INFO_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgHeatersInfoGroup, (U08*)&dgHeatersInfoGroup.crc, NVDATAMGMT_RTC} // NVDATAMGMT_HEATERS_INFO_RECORD + {DG_HEATERS_INFO_START_ADDRESS, sizeof(DG_HEATERS_INFO_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgHeatersInfoGroup, (U08*)&dgHeatersInfoGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_HEATERS_INFO_RECORD + {DG_USAGE_INFO_START_ADDRESS, sizeof(DG_USAGE_INFO_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&dgUsageInfoGroup, (U08*)&dgUsageInfoGroup.crc, NVDATAMGMT_RTC} // NVDATAMGMT_USAGE_INFO_RECORD }; #endif @@ -441,13 +451,18 @@ static HD_SYSTEM_GROUP_T hdSystemGroup; ///< HD system group structure (including padding and final CRC). static HD_SERVICE_GROUP_T hdServiceGroup; ///< HD service group structure (including padding and final CRC). static HD_USAGE_INFO_GROUP_T hdUsageInfoGroup; ///< HD usage info group structure (including padding and final CRC). +#ifndef _RELEASE_ static HD_SW_CONFIG_GROUP_T hdSWConfigGroup; ///< HD Software configurations structure(including padding and final CRC). +#endif // Process records specifications const PROCESS_RECORD_SPECS_T RECORDS_SPECS [ NUM_OF_NVDATMGMT_RECORDS_JOBS ] = { {CAL_RECORD_NV_MEM_START_ADDRESS, sizeof(HD_CALIBRATION_RECORD_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(HD_CALIBRATION_RECORD_T), (U08*)&hdCalibrationRecord, (U08*)&hdCalibrationRecord.crc, NVDATAMGMT_EEPROM}, // NVDATAMGMT_CALIBRATION_RECORD {SYSTEM_RECORD_NV_MEM_START_ADDRESS, sizeof(HD_SYSTEM_GROUP_T), MAX_EEPROM_WRITE_BUFFER_BYTES, sizeof(HD_SYSTEM_GROUP_T), (U08*)&hdSystemGroup, (U08*)&hdSystemGroup.crc, NVDATAMGMT_EEPROM}, // NVDATAMGMT_SYSTEM_RECORD {SERVICE_RECORD_START_ADDRESS, sizeof(HD_SERVICE_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&hdServiceGroup, (U08*)&hdServiceGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_PROCESS_LAST_SERVICE_RECORD - {SW_CONFIGS_START_ADDRESS, sizeof(HD_SW_CONFIG_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&hdSWConfigGroup, (U08*)&hdSWConfigGroup.crc, NVDATAMGMT_RTC} // NVDATAMGMT_SW_CONFIG_RECORD +#ifndef _RELEASE_ + {SW_CONFIGS_START_ADDRESS, sizeof(HD_SW_CONFIG_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&hdSWConfigGroup, (U08*)&hdSWConfigGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_SW_CONFIG_RECORD +#endif + {HD_USAGE_INFO_START_ADDRESS, sizeof(HD_USAGE_INFO_GROUP_T), MAX_RTC_RAM_OPS_BUFFER_BYTES, MAX_RTC_RAM_OPS_BUFFER_BYTES, (U08*)&hdUsageInfoGroup, (U08*)&hdUsageInfoGroup.crc, NVDATAMGMT_RTC}, // NVDATAMGMT_USAGE_INFO }; #endif @@ -485,6 +500,7 @@ static volatile BOOL powerOffIsImminent = FALSE; ///< Power off warning has been signaled. Non-volatile memory operations should be completed ASAP and then ceased. static BOOL isNewCalAvailable = FALSE; ///< Signal to indicate whether a new calibration data is available. static U32 newCalStartTimer = 0; ///< New calibration availability start timer. +static BOOL hasServiceRecordBeenUpdated; ///< Flag that indicates the service record has been updated once the calibration record has been updated. // Private functions static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestStart( void ); @@ -534,6 +550,7 @@ static BOOL didCommandTimeout( ALARM_ID_T alarm, U08* state ); static BOOL eraseDataLogSectors( void ); static void monitorNewCalSignal( void ); +static void updateServiceRecord( void ); // Record operations queue functions static void enqueueRecordJob( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, RECORD_JOBS_STATE_T job ); @@ -546,11 +563,14 @@ static BOOL areRecordsValid( void ); static BOOL isPolynomialRecordValid( POLYNOMIAL_CAL_PAYLOAD_T* record ); +#ifndef _RELEASE_ +static BOOL isSWConfigRecordValid( void ); +#endif + #ifdef _DG_ static BOOL isDGSystemRecordValid( void ); static BOOL isDGServiceRecordValid( void ); static BOOL isDGCalibrationRecordValid( void ); -static BOOL isSWConfigRecordValid( void ); static BOOL isDGConcPumpRecordValid( DG_CONC_PUMPS_CAL_DATA_T* record ); static BOOL isDGDrainPumpRecordValid( DG_DRAIN_PUMP_CAL_RECORD_T* record ); static BOOL isDGROPumpRecordValid( DG_RO_PUMP_CAL_RECORD_T* record ); @@ -570,7 +590,6 @@ static BOOL isHDSystemRecordValid( void ); static BOOL isHDServiceRecordValid( void ); static BOOL isHDCalibrationRecordValid( void ); -static BOOL isSWConfigRecordValid( void ); static BOOL isHDValveRecordValid( HD_VALVE_CAL_PAYLOAD_T* record ); static BOOL isHDPumpRecordValid( HD_PUMP_CAL_PAYLOAD_T* record ); static BOOL isHDAccelerometerSensorValid( HD_ACCELEROMETER_SENSOR_CAL_RECORD_T* record ); @@ -587,7 +606,7 @@ * queueFrontIndex, queueCount, recordUpdateAddress, recordQueueRearIndex, * recordQueueFrontIndex, recordQueueCount, recordAddressOffset, * writtenRecordStatus, hasPublishRecordBeenRequested, isNewCalAvailable, - * newCalStartTimer + * newCalStartTimer, hasServiceRecordBeenUpdated * @return none *************************************************************************/ void initNVDataMgmt( void ) @@ -610,6 +629,7 @@ hasPublishRecordBeenRequested = FALSE; isNewCalAvailable = FALSE; newCalStartTimer = 0; + hasServiceRecordBeenUpdated = FALSE; // Initialize and activate flash bank 7 Fapi_initializeFlashBanks( ROUNDED_HCLK_FREQ ); @@ -938,6 +958,26 @@ /*********************************************************************//** * @brief + * The benignPolynomialCalRecord function benigns the provided polynomial + * calibration record. + * @details Inputs: none + * @details Outputs: none + * @return record which is a pointer to a polynomial calibration record + * otherwise none + *************************************************************************/ +void benignPolynomialCalRecord( POLYNOMIAL_CAL_PAYLOAD_T* record ) +{ + record->fourthOrderCoeff = RECORD_FOURTH_ORDER_COEFF; + record->thirdOrderCoeff = RECORD_THIRD_ORDER_COEFF; + record->secondOrderCoeff = RECORD_SECOND_ORDER_COEFF; + record->gain = RECORD_DEFAULT_GAIN; + record->offset = RECORD_DEFAULT_OFFSET; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof( POLYNOMIAL_CAL_PAYLOAD_T ) - sizeof( U16 ) ); +} + +/*********************************************************************//** + * @brief * The isNewCalibrationRecordAvailable function returns the status of a * new calibration availability. * @details Inputs: none @@ -1006,28 +1046,28 @@ nvDataStartPtr = (U08*)&hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord; nvDataLength = sizeof( hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord ); for ( i = 0; i < NUM_OF_CAL_DATA_HD_PUMPS; i++ ) - isNVDataValid = ( 0 == hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord.hdPumps[ i ].calibrationTime ? FALSE : TRUE ); + isNVDataValid |= ( 0 == hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord.hdPumps[ i ].calibrationTime ? FALSE : TRUE ); break; case GET_CAL_PRESSURE_SENSORS: nvDataStartPtr = (U08*)&hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord; nvDataLength = sizeof( hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord ); for ( i = 0; i < NUM_OF_CAL_DATA_HD_PRESSURE_SESNSORS; i++ ) - isNVDataValid = ( 0 == hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord.hdPressureSensors[ i ].calibrationTime ? FALSE : TRUE ); + isNVDataValid |= ( 0 == hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord.hdPressureSensors[ i ].calibrationTime ? FALSE : TRUE ); break; case GET_CAL_OCCLUSION_SESNSORS: nvDataStartPtr = (U08*)&hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord; nvDataLength = sizeof( hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord ); for ( i = 0; i < NUM_OF_CAL_DATA_OCCLUSION_SENSORS; i++ ) - isNVDataValid = ( 0 == hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord.hdOcclusionSensors[ i ].calibrationTime ? FALSE : TRUE ); + isNVDataValid |= ( 0 == hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord.hdOcclusionSensors[ i ].calibrationTime ? FALSE : TRUE ); break; case GET_CAL_VALVES: nvDataStartPtr = (U08*)&hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord; nvDataLength = sizeof( hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord ); for ( i = 0; i < NUM_OF_CAL_DATA_HD_VALVES; i++ ) - isNVDataValid = ( 0 == hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord.hdvalves[ i ].calibrationTime ? FALSE : TRUE ); + isNVDataValid |= ( 0 == hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord.hdvalves[ i ].calibrationTime ? FALSE : TRUE ); break; case GET_SYS_RECORD: @@ -1152,8 +1192,8 @@ break; case GET_CAL_FILTERS_RECORD: - nvDataStartPtr = (U08*)&dgCalibrationRecord.dgCalibrationGroups.filtersRecord; - nvDataLength = sizeof( dgCalibrationRecord.dgCalibrationGroups.filtersRecord ); + nvDataStartPtr = (U08*)&dgCalibrationRecord.dgCalibrationGroups.filtersRecord; + nvDataLength = sizeof( dgCalibrationRecord.dgCalibrationGroups.filtersRecord ); isNVDataValid |= ( 0 == dgCalibrationRecord.dgCalibrationGroups.filtersRecord.carbonFilter.calibrationTime ? FALSE : TRUE ); isNVDataValid |= ( 0 == dgCalibrationRecord.dgCalibrationGroups.filtersRecord.carbonPolishFilter.calibrationTime ? FALSE : TRUE ); isNVDataValid |= ( 0 == dgCalibrationRecord.dgCalibrationGroups.filtersRecord.roFilter.calibrationTime ? FALSE : TRUE ); @@ -1195,7 +1235,6 @@ memcpy( bufferAddress, nvDataStartPtr, bufferLength ); } -#ifndef SKIP_CAL_CHECK // Check if the non-volatile data is valid and if not raise the alarm if ( FALSE == isNVDataValid ) { @@ -1206,16 +1245,25 @@ } else { - activateAlarmNoData( nvAlarm ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAL_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + activateAlarmNoData( nvAlarm ); + } +#ifndef _RELEASE_ + else + { + isNVDataValid = TRUE; + } +#endif } } -#else - isNVDataValid = TRUE; -#endif return isNVDataValid; } +#ifndef _RELEASE_ /*********************************************************************//** * @brief * The getSoftwareConfigStatus function returns the status of a software @@ -1232,17 +1280,16 @@ // 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 -#ifndef _RELEASE_ #ifdef _DG_ value = dgSWConfigGroup.dgSWConfigsRecord.swConfigs[ config ]; #endif #ifdef _HD_ value = hdSWConfigGroup.hdSWConfigsRecord.swConfigs[ config ]; #endif -#endif return value; } +#endif #ifdef _DG_ /*********************************************************************//** @@ -1307,23 +1354,34 @@ #ifdef _HD_ /*********************************************************************//** * @brief - * The setTreatmentTime sets a queue job to write the treatment time in - * the specified RAM address. - * @details Inputs: treatmentTimeRecord - * @details Outputs: treatmentTimeRecord - * @param hours treatmet time in hours + * The setTxTimeHours sets the treatment time in hours. + * @details Inputs: none + * @details Outputs: hdUsageInfoGroup + * @param hours treatment time in hours + * @param isServiceDone flag to indicate the service has been done * @return TRUE if the queue was not full so the job was scheduled successfully *************************************************************************/ -BOOL setTreatmentTime ( U32 hours ) +BOOL setTxTimeHours( F32 hours, BOOL isServiceDone ) { BOOL status = FALSE; - hdUsageInfoGroup.hdUsageInfo.treatmentTime = hours; - hdUsageInfoGroup.crc = crc16 ( (U08*)&hdUsageInfoGroup.hdUsageInfo.treatmentTime, sizeof(U32) ); + if ( TRUE == isServiceDone ) + { + hdUsageInfoGroup.hdUsageInfo.txTimeTotalHrs += hdUsageInfoGroup.hdUsageInfo.txTimeSinceLastSrvcHrs; + hdUsageInfoGroup.hdUsageInfo.txTimeSinceLastSrvcHrs = hours; + } + else + { + hdUsageInfoGroup.hdUsageInfo.txTimeSinceLastSrvcHrs += hours; + hdUsageInfoGroup.hdUsageInfo.txTimeTotalHrs += hdUsageInfoGroup.hdUsageInfo.txTimeSinceLastSrvcHrs; + } + + hdUsageInfoGroup.hdUsageInfo.crc = crc16( (U08*)&hdUsageInfoGroup.hdUsageInfo, sizeof( HD_USAGE_INFO_RECORD_T ) - sizeof( U16 ) ); + hdUsageInfoGroup.crc = crc16( (U08*)&hdUsageInfoGroup, sizeof( HD_USAGE_INFO_GROUP_T ) - sizeof( U16 ) ); + if ( FALSE == isQueueFull() ) { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, HD_TREATMENT_TIME_ADDRESS, - (U08*)&hdUsageInfoGroup, 0, sizeof(HD_USAGE_INFO_RECORD_T) ); + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, HD_USAGE_INFO_START_ADDRESS, (U08*)&hdUsageInfoGroup, 0, sizeof( HD_USAGE_INFO_GROUP_T ) ); status = TRUE; } @@ -1332,57 +1390,117 @@ /*********************************************************************//** * @brief - * The getTreatmentTime returns the total number treatment hours of the - * HD device. + * The setTxLastStartTimeEpoch sets the last treatment start time in epoch * @details Inputs: none - * Output: none - * @return treatment time as U32 + * Output: hdUsageInfoGroup + * @return TRUE if the write job was queued properly otherwise, FALSE *************************************************************************/ -U32 getTreatmentTime ( void ) +BOOL setTxLastStartTimeEpoch( U32 epoch ) { - return hdUsageInfoGroup.hdUsageInfo.treatmentTime; + BOOL status = FALSE; + hdUsageInfoGroup.hdUsageInfo.txLastStartTimeEpoch = epoch; + hdUsageInfoGroup.hdUsageInfo.crc = crc16 ( (U08*)&hdUsageInfoGroup.hdUsageInfo, sizeof( HD_USAGE_INFO_RECORD_T ) - sizeof( U16 ) ); + hdUsageInfoGroup.crc = crc16 ( (U08*)&hdUsageInfoGroup, sizeof( HD_USAGE_INFO_GROUP_T ) - sizeof( U16 ) ); + + if ( FALSE == isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, HD_USAGE_INFO_START_ADDRESS, (U08*)&hdUsageInfoGroup, 0, sizeof( HD_USAGE_INFO_GROUP_T ) ); + status = TRUE; + } + + return status; } #endif #ifdef _DG_ /*********************************************************************//** * @brief - * The setWaterConsumption sets a queue job to write the amount of water - * that has been consumed in DG. - * @details Inputs: waterConsumptionRecord - * @details Outputs: waterConsumptionRecord + * The setROWaterGeneratedL sets a queue job to write the amount of generated + * RO water that has been generated in DG. + * @details Inputs: dgUsageInfoGroup + * @details Outputs: dgUsageInfoGroup * @param liters consumed water is liters + * @param isServiceDone TURE if service is done otherwise, FALSE * @return TRUE if queue is not full *************************************************************************/ -BOOL setWaterConsumption ( U32 liters ) +BOOL setROWaterGeneratedL( F32 liters, BOOL isServiceDone ) { BOOL status = FALSE; - dgUsageInfoGroup.dgUsageInfo.waterConsumption = liters; - dgUsageInfoGroup.crc = crc16 ( (U08*)&dgUsageInfoGroup.dgUsageInfo.waterConsumption, sizeof(U16) ); - if ( !isQueueFull() ) + if ( TRUE == isServiceDone ) { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_CONSUMED_WATER_ADDRESS, - (U08*)&dgUsageInfoGroup, 0, sizeof(DG_USAGE_INFO_RECORD_T) ); - status = TRUE; //TODO this is not right use enqueueRecordJob function to schedule a write + dgUsageInfoGroup.dgUsageInfo.roWaterGenTotalL += dgUsageInfoGroup.dgUsageInfo.roWaterGenSinceLastServiceL; + dgUsageInfoGroup.dgUsageInfo.roWaterGenSinceLastServiceL = liters; } + else + { + dgUsageInfoGroup.dgUsageInfo.roWaterGenSinceLastServiceL += liters; + dgUsageInfoGroup.dgUsageInfo.roWaterGenTotalL += dgUsageInfoGroup.dgUsageInfo.roWaterGenSinceLastServiceL; + } + 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 ) ); + + if ( FALSE == isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_USAGE_INFO_START_ADDRESS, (U08*)&dgUsageInfoGroup, 0, sizeof( DG_USAGE_INFO_GROUP_T ) ); + status = TRUE; + } + return status; } /*********************************************************************//** * @brief - * The getWaterConsumption returns the amount of consumed water. - * @details Inputs: none - * @details Outputs: none - * @return water consumption as a U32 + * The setLastDisinfectDate sets a queue job to write the last time that DG + * was disinfected. + * @details Inputs: dgUsageInfoGroup + * @details Outputs: dgUsageInfoGroup + * @param epochTime last disinfect time in epoch + * @return TRUE if queue is not full *************************************************************************/ -U32 getWaterConsumption ( void ) +BOOL setLastDisinfectDate( U32 epochTime ) { - return dgUsageInfoGroup.dgUsageInfo.waterConsumption; + BOOL status = FALSE; + dgUsageInfoGroup.dgUsageInfo.lastDisinfectDate = epochTime; + 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 ) ); + + if ( FALSE == isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_USAGE_INFO_START_ADDRESS, (U08*)&dgUsageInfoGroup, 0, sizeof( DG_USAGE_INFO_GROUP_T ) ); + status = TRUE; + } + + return status; } /*********************************************************************//** * @brief + * The setDisinfectStatus sets a queue job to write whether the device is already + * disinfected or not. + * @details Inputs: dgUsageInfoGroup + * @details Outputs: dgUsageInfoGroup + * @param disinfectStatus disinfect status + * @return TRUE if queue is not full + *************************************************************************/ +BOOL setDisinfectStatus( BOOL disinfectStatus ) +{ + BOOL status = FALSE; + dgUsageInfoGroup.dgUsageInfo.isDisinfected = disinfectStatus; + 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 ) ); + + if ( FALSE == isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_USAGE_INFO_START_ADDRESS, (U08*)&dgUsageInfoGroup, 0, sizeof( DG_USAGE_INFO_GROUP_T ) ); + status = TRUE; + } + + return status; +} + +/*********************************************************************//** + * @brief * The setHeatersInfoRecord sets a queue job to write the DG heaters info * back to the RTC RAM. * @details Inputs: none @@ -1597,13 +1715,16 @@ // If the RTC RAM is ready, read the results if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - getDataFromRAM( (U08*)&hdUsageInfoGroup, sizeof(HD_USAGE_INFO_RECORD_T) ); // If the RAM is ready, request a read for the log records (RAM) if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { - readFromRAM( LOG_RECORD_START_ADDRESS, sizeof(LOG_RECORD_T) ); - currentTime = getMSTimerCount(); - state = NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD; + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS[ NVDATAMGMT_USAGE_INFO_RECORD ]; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = specs.maxReadBufferSize; + + getDataFromRAM ( bufferAddress, maxBufferLength ); + + state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; } } @@ -1680,12 +1801,18 @@ // If the RAM is ready, request a read for water consumption if ( ( RTC_RAM_STATUS_IDLE == getRTCRAMStatus() ) || ( TRUE == timeoutStatus ) ) { - getDataFromRAM ( (U08*)&dgUsageInfoGroup, sizeof(DG_USAGE_INFO_RECORD_T) ); + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS[ NVDATAMGMT_USAGE_INFO_RECORD ]; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = specs.maxReadBufferSize; + + getDataFromRAM ( bufferAddress, maxBufferLength ); + if ( RTC_RAM_STATE_READY == getRTCRAMState() ) { - readFromRAM ( LOG_RECORD_START_ADDRESS, sizeof(LOG_RECORD_T) ); - currentTime = getMSTimerCount(); - state = NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD; + // TODO Phase 1B + //readFromRAM ( LOG_RECORD_START_ADDRESS, sizeof(LOG_RECORD_T) ); + //currentTime = getMSTimerCount(); + state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; } } @@ -1746,7 +1873,22 @@ getDataFromRAM( bufferAddress, maxBufferLength ); - state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; + if ( RTC_RAM_STATE_READY == getRTCRAMState() ) + { + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS[ NVDATAMGMT_USAGE_INFO_RECORD ]; + U32 startAddress = specs.startAddress; + U32 maxBufferLength = specs.maxReadBufferSize; + + currentTime = getMSTimerCount(); + readFromRAM( startAddress, maxBufferLength ); + +#ifdef _DG_ + state = NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION; +#endif +#ifdef _HD_ + state = NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME; +#endif + } } #else // It is a release so set all the software configurations to 0 to be considered as disable @@ -1782,14 +1924,18 @@ haveCalGroupsPassed = isDGCalibrationRecordValid(); hasSystemRecordPassed = isDGSystemRecordValid(); hasServiceRecordPassed = isDGServiceRecordValid(); +#ifndef _RELEASE_ hasSWConfigRecordPassed = isSWConfigRecordValid(); #endif +#endif #ifdef _HD_ haveCalGroupsPassed = isHDCalibrationRecordValid(); hasSystemRecordPassed = isHDSystemRecordValid(); hasServiceRecordPassed = isHDServiceRecordValid(); +#ifndef _RELEASE_ hasSWConfigRecordPassed = isSWConfigRecordValid(); #endif +#endif // If any of the records did not pass, they should be filled // with benign values. After that, schedule a write to sector 0 @@ -1865,6 +2011,9 @@ // If power off command has been issued, do not process any new jobs if ( powerOffIsImminent != TRUE ) { + // Check if the service record has to be updated + updateServiceRecord(); + // If the record processing queue is not empty, process the queues if ( FALSE == isRecordQueueEmpty() ) { @@ -1892,7 +2041,7 @@ maxBufferLength = jobSpecs.maxReadBufferSize / EEPROM_OPS_SIZE_OF_CONVERTER; } } - // TODO add the log queue later in the future phases. + // TODO add the log queue later in Phase 1B. } // Check if a queue job is available @@ -2026,6 +2175,7 @@ if ( recordCurrentJob.memoryLocation == NVDATAMGMT_EEPROM && FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady ) { U32 i; + U08* bufferPtr = jobSpecs.structAddressPtr + recordAddressOffset; // Loop through the bytes in the buffer @@ -2394,6 +2544,14 @@ #endif break; + case NVDATAMGMT_USAGE_INFO_RECORD: +#ifdef _DG_ + sendDGUsageInfoRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif +#ifdef _HD_ +#endif + break; + default: //Ignore break; @@ -2773,6 +2931,35 @@ /*********************************************************************//** * @brief + * The updateServiceRecord function updates the service record once there is + * a new calibration record received. + * @details Inputs: isNewCalAvailable + * @details Outputs: isNewCalAvailable, hasServiceRecordBeenUpdated + * @return none + *************************************************************************/ +static void updateServiceRecord( void ) +{ + // If a new calibration is available and the service record has not been updated, updated the service record + // Right now, the last service date is updated once a new calibration record is received by the service personnel + if ( ( TRUE == isNewCalAvailable ) && ( FALSE == hasServiceRecordBeenUpdated ) ) + { +#ifdef _HD_ + hdServiceGroup.hdServiceRecord.lastServiceEpochDate = getRTCTimestamp(); + hdServiceGroup.hdServiceRecord.serviceLoc = 0; + hdServiceGroup.hdServiceRecord.crc = crc16( (U08*)&hdServiceGroup.hdServiceRecord, sizeof( HD_SERVICE_RECORD_T ) - sizeof( U16 ) ); + hdServiceGroup.crc = crc16( (U08*)&hdServiceGroup, sizeof( HD_SERVICE_GROUP_T ) - sizeof( U16 ) ); + + if ( FALSE == isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, SERVICE_RECORD_START_ADDRESS, (U08*)&hdServiceGroup, 0, sizeof( HD_SERVICE_RECORD_T ) ); + hasServiceRecordBeenUpdated = TRUE; + } +#endif + } +} + +/*********************************************************************//** + * @brief * The areRecordsValid function checks whether the records are still valid * by calculating the CRCs and comparing it to the strucutre's CRC. * @details Inputs: none @@ -2845,7 +3032,56 @@ return status; } +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The isSWConfigRecordValid function checks the validity of the software + * configuration record. + * @details Inputs: dgSWConfigGroup, hdSWConfigGroup + * @details Outputs: dgSWConfigGroup, hdSWConfigGroup + * @return TRUE if the DG system record is valid otherwise FALSE + *************************************************************************/ +static BOOL isSWConfigRecordValid( void ) +{ + BOOL status = TRUE; + #ifdef _DG_ + U16 calcCRC = crc16( (U08*)&dgSWConfigGroup, sizeof( DG_SW_CONFIG_GROUP_T ) - sizeof(U16) ); + U16 recordCRC = dgSWConfigGroup.crc; + + if ( calcCRC != recordCRC ) + { + memset( (U08*)&dgSWConfigGroup, 0, sizeof( DG_SW_CONFIG_GROUP_T ) ); + + // Recalculate the CRC with the default values + dgSWConfigGroup.crc = crc16( (U08*)&dgSWConfigGroup, sizeof( DG_SW_CONFIG_GROUP_T ) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } +#endif + +#ifdef _HD_ + U16 calcCRC = crc16( (U08*)&hdSWConfigGroup, sizeof( HD_SW_CONFIG_GROUP_T ) - sizeof(U16) ); + U16 recordCRC = hdSWConfigGroup.crc; + + if ( calcCRC != recordCRC ) + { + memset( (U08*)&hdSWConfigGroup, SW_CONFIG_DISABLE_VALUE, sizeof( HD_SW_CONFIG_GROUP_T ) ); + + // Recalculate the CRC with the default values + hdSWConfigGroup.crc = crc16( (U08*)&hdSWConfigGroup, sizeof( HD_SW_CONFIG_GROUP_T ) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } +#endif + + return status; +} +#endif + +#ifdef _DG_ /*********************************************************************//** * @brief * The isDGSystemRecordValid function checks the validity of the DG system @@ -3110,36 +3346,6 @@ /*********************************************************************//** * @brief - * The isSWConfigRecordValid function checks the validity of the software - * configuration record. - * @details Inputs: dgSWConfigGroup - * @details Outputs: dgSWConfigGroup - * @return TRUE if the DG system record is valid otherwise FALSE - *************************************************************************/ -static BOOL isSWConfigRecordValid( void ) -{ - BOOL status = TRUE; - U16 calcCRC = crc16( (U08*)&dgSWConfigGroup, sizeof( DG_SW_CONFIG_GROUP_T ) - sizeof(U16) ); - U16 recordCRC = dgSWConfigGroup.crc; - - if ( calcCRC != recordCRC ) - { - memset( (U08*)&dgSWConfigGroup, 0, sizeof( DG_SW_CONFIG_GROUP_T ) ); - - // Recalculate the CRC with the default values - dgSWConfigGroup.crc = crc16( (U08*)&dgSWConfigGroup, sizeof( DG_SW_CONFIG_GROUP_T ) - sizeof(U16) ); - - //activateAlarmNoData( ALARM_ID_DG_SW_CONFIG_RECORD_INVALID_CRC ); // TODO remove - - // Set the to FALSE since the record is not valid - status = FALSE; - } - - return status; -} - -/*********************************************************************//** - * @brief * The isDGConcPumpRecordValid function checks whether the calibration * record of concentrate pump is valid or not. * @details Inputs: none @@ -3675,36 +3881,6 @@ /*********************************************************************//** * @brief - * The isSWConfigRecordValid function checks the validity of the software - * configuration record. - * @details Inputs: hdSWConfigGroup - * @details Outputs: hdSWConfigGroup - * @return TRUE if the DG system record is valid otherwise FALSE - *************************************************************************/ -static BOOL isSWConfigRecordValid( void ) -{ - BOOL status = TRUE; - U16 calcCRC = crc16( (U08*)&hdSWConfigGroup, sizeof( HD_SW_CONFIG_GROUP_T ) - sizeof(U16) ); - U16 recordCRC = hdSWConfigGroup.crc; - - if ( calcCRC != recordCRC ) - { - memset( (U08*)&hdSWConfigGroup, SW_CONFIG_DISABLE_VALUE, sizeof( HD_SW_CONFIG_GROUP_T ) ); - - // Recalculate the CRC with the default values - hdSWConfigGroup.crc = crc16( (U08*)&hdSWConfigGroup, sizeof( HD_SW_CONFIG_GROUP_T ) - sizeof(U16) ); - - //activateAlarmNoData( ALARM_ID_HD_SW_CONFIG_RECORD_INVALID_CRC ); // TODO remove - - // Set the to FALSE since the record is not valid - status = FALSE; - } - - return status; -} - -/*********************************************************************//** - * @brief * The isHDPumpRecordValid function checks whether the calibration record * of HD pump(s) is valid or not. * @details Inputs: none