Index: NVDataMgmt.c =================================================================== diff -u -r547c33d5e13614b5e8de4739a45db7c3475721d1 -r3901134947efa340fdc31dc7f2d64a48b2470236 --- NVDataMgmt.c (.../NVDataMgmt.c) (revision 547c33d5e13614b5e8de4739a45db7c3475721d1) +++ NVDataMgmt.c (.../NVDataMgmt.c) (revision 3901134947efa340fdc31dc7f2d64a48b2470236) @@ -18,13 +18,16 @@ // Includes #include // For memcpy +#include // For ceilf function +#include "system.h" #include "F021.h" #include "MsgQueues.h" #include "NVDataMgmt.h" #include "RTC.h" -#include "system.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" #include "Timers.h" #include "Utilities.h" @@ -35,272 +38,525 @@ // Private defines -#define QUEUE_MAX_SIZE 20U ///< Max queue size -#define QUEUE_START_INDEX 0U ///< Queue start index -#define MIN_JOBS_NEEDED_FOR_DATA_LOG 3U ///< Min queue required for data log (3) -#define MIN_JOBS_NEEDED_FOR_SECTOR_0 4U ///< Min queue count needed to write all (4) records back in sector 0 +#define QUEUE_MAX_SIZE 20U ///< Max queue size. +#define QUEUE_START_INDEX 0U ///< Queue start index. +#define MIN_JOBS_NEEDED_FOR_DATA_LOG 3U ///< Min queue required for data log (3). +#define MIN_JOBS_NEEDED_FOR_SECTOR_0 4U ///< Min queue count needed to write all (4) records back in sector 0. -// The clock frequency comes from HCLK_FREQ and it has to be rounded up to the -// nearest number -#define ROUNDED_HCLK_FREQ FLOAT_TO_INT_WITH_ROUND(HCLK_FREQ) ///< Rounded HCLK for EERPOM clock -#define BANK7_SECTOR_0_31_ENABLE_BIT_MASK 0x0000000F ///< Bank7 sector 0 t0 31 enable mask -#define BANK7_SECTOR_32_63_ENABLE_BIT_MASK 0x00000000 ///< Bank7 sector 32 to 63 enable mask +// The clock frequency comes from HCLK_FREQ and it has to be rounded up to the nearest number +#define ROUNDED_HCLK_FREQ FLOAT_TO_INT_WITH_ROUND(HCLK_FREQ) ///< Rounded HCLK for EERPOM clock. +#define BANK7_SECTOR_0_31_ENABLE_BIT_MASK 0x0000000F ///< Bank7 sector 0 t0 31 enable mask. +#define BANK7_SECTOR_32_63_ENABLE_BIT_MASK 0x00000000 ///< Bank7 sector 32 to 63 enable mask. -#define BANK7_SECTOR0_START_ADDRESS 0xF0200000 ///< Bank7 sector 0 start address -#define BANK7_SECTOR0_END_ADDRESS 0xF0203FFF ///< Bank7 sector 0 end address +#define BANK7_SECTOR0_START_ADDRESS 0xF0200000 ///< Bank7 sector 0 start address. +#define BANK7_SECTOR0_END_ADDRESS 0xF0203FFF ///< Bank7 sector 0 end address. -#define BANK7_SECTOR1_START_ADDRESS 0xF0204000 ///< Bank7 sector 1 start address -#define BANK7_SECTOR1_END_ADDRESS 0xF0207FFF ///< Bank7 sector 1 end address +#define BANK7_SECTOR1_START_ADDRESS 0xF0204000 ///< Bank7 sector 1 start address. +#define BANK7_SECTOR1_END_ADDRESS 0xF0207FFF ///< Bank7 sector 1 end address. -#define BANK7_SECTOR2_START_ADDRESS 0xF0208000 ///< Bank7 sector 2 start address -#define BANK7_SECTOR2_END_ADDRESS 0xF020BFFF ///< Bank7 sector 2 end address +#define BANK7_SECTOR2_START_ADDRESS 0xF0208000 ///< Bank7 sector 2 start address. +#define BANK7_SECTOR2_END_ADDRESS 0xF020BFFF ///< Bank7 sector 2 end address. -#define BANK7_SECTOR3_START_ADDRESS 0xF020C000 ///< Bank7 sector 3 start address -#define BANK7_SECTOR3_END_ADDRESS 0xF020FFFF ///< Bank7 sector 3 end address +#define BANK7_SECTOR3_START_ADDRESS 0xF020C000 ///< Bank7 sector 3 start address. +#define BANK7_SECTOR3_END_ADDRESS 0xF020FFFF ///< Bank7 sector 3 end address. -#define MAX_EEPROM_WRITE_BUFFER_BYTES 16U ///< Max allowed bytes for an EEPROM write (16 bytes) +#define MAX_EEPROM_WRITE_BUFFER_BYTES 16U ///< Max allowed bytes for an EEPROM write (16 bytes). +#define MAX_RTC_RAM_OPS_BUFFER_BYTES 64U ///< Max target RTC RAM operations (read/write) bytes. -#define MAX_JOB_DATA_SIZE_BYTES 32U ///< Max bytes per job (32 bytes) -#define LOG_DATA_START_INDEX 0U ///< Log data start index -#define MAX_NUM_OF_SECTORS_FOR_LOG_DATA 3U ///< Max number of sector (3 sectors) -#define MAX_LOG_DATA_PER_SECTOR (((BANK7_SECTOR1_END_ADDRESS + 1) - \ - BANK7_SECTOR1_START_ADDRESS) / MAX_JOB_DATA_SIZE_BYTES) ///< Max log data per sector (512 for now) -#define MAX_NUM_OF_EVENTS_IN_SECTOR3 (MAX_NUM_OF_SECTORS_FOR_LOG_DATA * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 3 (1536) -#define MAX_NUM_OF_EVENTS_IN_SECTOR2 ((MAX_NUM_OF_SECTORS_FOR_LOG_DATA - 1) * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 2 (1024) -#define MAX_NUM_OF_EVENTS_IN_SECTOR1 ((MAX_NUM_OF_SECTORS_FOR_LOG_DATA - 2) * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 1 (512) +#define MAX_JOB_DATA_SIZE_BYTES 32U ///< Max bytes per job (32 bytes). +#define LOG_DATA_START_INDEX 0U ///< Log data start index. +#define MAX_NUM_OF_SECTORS_FOR_LOG_DATA 3U ///< Max number of sector (3 sectors). +#define MAX_LOG_DATA_PER_SECTOR (((BANK7_SECTOR1_END_ADDRESS + 1) - \ + BANK7_SECTOR1_START_ADDRESS) / MAX_JOB_DATA_SIZE_BYTES) ///< Max log data per sector (512 for now). +#define MAX_NUM_OF_EVENTS_IN_SECTOR3 (MAX_NUM_OF_SECTORS_FOR_LOG_DATA * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 3 (1536). +#define MAX_NUM_OF_EVENTS_IN_SECTOR2 ((MAX_NUM_OF_SECTORS_FOR_LOG_DATA - 1) * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 2 (1024). +#define MAX_NUM_OF_EVENTS_IN_SECTOR1 ((MAX_NUM_OF_SECTORS_FOR_LOG_DATA - 2) * MAX_LOG_DATA_PER_SECTOR) ///< Max number of accumulated logs in sector 1 (512). // Data addresses and length in RTC RAM -#define BOOTLOADER_FLAG_ADDRESS 0x00000000 ///< Bootloader start address in RTC RAM (0) -#define BOOTLOADER_FLAG_LENGTH_BYTES 4U ///< Bootloader number of bytes (4 bytes) -#define LOG_RECORD_START_ADDRESS 0x00000010 // 16 ///< Log record start address in RTC RAM (16) -#define HD_TREATMENT_TIME_ADDRESS 0X00000030 // 48 ///< HD treatment time start address in RTC RAM (48) -#define DG_CONSUMED_WATER_ADDRESS 0X00000040 // 64 ///< DG water consumption start address in RTC RAM (64) -#define SERVICE_DATE_START_ADDRESS 0X00000050 // 80 ///< Service date record start address in RTC RAM (80) -#define LAST_DISINFECTION_DATE_ADDRESS 0x00000060 // 96 ///< Last disinfection date start address in RTC RAM (96) +#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 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. -// Data addresses in EEPROM -#define CALIBRATION_RECORD_START_ADDRESS ( BANK7_SECTOR0_START_ADDRESS + sizeof(MFG_RECORD_T) ) ///< Calibration record start address in EEPROM +#define COMMAND_TIME_OUT 500U ///< Timeout for an EEPROM or RTC command in ms. +/// EEPROM functions use the buffer length as the size of U32. So before send the length to any of FAPI functions, it should be divide by 4. +#define EEPROM_OPS_SIZE_OF_CONVERTER 4 -#define COMMAND_TIME_OUT 500U // time in ms ///< Timeout for an EEPROM or RTC command in ms +// ********** Calibration data defines ********** +#define NUM_OF_BYTES_PER_CAL_PAYLOAD 150U ///< Number of bytes per calibration payload. +#define CAL_DATA_SEND_INTERVAL_COUNT (MS_PER_SECOND / (5 * TASK_GENERAL_INTERVAL)) ///< Calibration data send time interval in counts. +#define RECORD_DATA_RECEIVE_TIMEOUT_MS (4 * MS_PER_SECOND) ///< Record data receive all the data packets timeout in ms. +#define RECORD_DATA_MAX_MESSAGE_DFFIRENCE 1 ///< Calibration data receive message different from the previous message. +#define RECORD_DATA_FIRST_RECEIVING_MSG_NUM 1 ///< Calibration data first receiving message number. +#define SYSTEM_RECORD_NV_MEM_START_ADDRESS BANK7_SECTOR0_START_ADDRESS ///< System record storage start address in NV memory. +#define CAL_RECORD_NV_MEM_START_ADDRESS BANK7_SECTOR0_START_ADDRESS + 4096 ///< Calibration record storage start address in NV memory. -#define ERASE_CALIBRATION_KEY 0xD2C3B4A5 ///< 32-bit key required for clearing calibration data. +#define RECORD_BYTE_SIZE(r) (sizeof(r) + sizeof(U16)) ///< Record byte size macro. +// Padding length calculation: (DG struct size % bytes to write(16) == 0 ? 0 : (DG struct size / bytes to write(16)) + 1) * bytes to write(16) +/// DG padding length macro that is calculated with the size of the provided structure. +#define RECORD_PADDING_LENGTH(rcrd, buf) (RECORD_BYTE_SIZE(rcrd) % buf == 0 ? 0 : ((U32)(RECORD_BYTE_SIZE(rcrd) / buf) + 1)) * buf +#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. + +/// Once a new calibration data is available the driver, sets a signal for the defined time. Once the time +/// is out, it turns the signal off. +#define NEW_CAL_AVAILABLE_SIGNAL_TIMEOUT_MS (1 * MS_PER_SECOND) + /// NVDataMgmt self-test states enumeration. typedef enum NVDataMgmt_Self_Test_States { - NVDATAMGMT_SELF_TEST_STATE_START = 0, ///< Self test start - NVDATAMGMT_SELF_TEST_STATE_ENABLE_EEPROM, ///< Self test enable EERPOM - NVDATAMGMT_SELF_TEST_STATE_READ_BOOTLOADER_FLAG, ///< Self test read bootloader - NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD, ///< Self test read log record - NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME, ///< Self test read treatment time - NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION, ///< Self test read water consumption - NVDATAMGMT_SELF_TEST_STATE_READ_MFG_RECORD, ///< Self test read manufacturing record - NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD, ///< Self test read calibration record - NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD, ///< Self test read service record - NVDATAMGMT_SELF_TEST_STATE_READ_LAST_DISINFECTION_DATE, ///< Self test read last disinfection date - 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_START = 0, ///< Self test start. + NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD, ///< Self test read calibration record. + NVDATAMGMT_SELF_TEST_STATE_READ_SYS_RECORD, ///< Self test read system record. + NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD, ///< Self test read service record. + NVDATAMGMT_SELF_TEST_STATE_READ_SCHEDULED_RUNS_RECORD, ///< Self test read scheduled runs record (DG only). + NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD, ///< Self test read log record. + NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME, ///< Self test read treatment time. TODO combine with water consumption + NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION, ///< Self test read water consumption. TODO combine with tx time + 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; /// NVDataMgmt Exec states enumeration. typedef enum NVDataMgmt_Exec_State { - NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST = 0, ///< Exec state wait for POST - NVDATAMGMT_EXEC_STATE_IDLE, ///< Exec state Idle - NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM, ///< Exec state write to EEPROM - NVDATAMGMT_EXEC_STATE_READ_FROM_EEPROM, ///< Exec state read from EEPROM - NVDATAMGMT_EXEC_STATE_ERASE_EEPROM, ///< Exec state erase EEPROM - NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC, ///< Exec state write to RTC - NVDATAMGMT_EXEC_STATE_READ_FROM_RTC, ///< Exec state read from RTC - NUM_OF_NVDATAMGMT_EXEC_STATES ///< Total number of exec states + NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST = 0, ///< Exec state wait for POST. + NVDATAMGMT_EXEC_STATE_IDLE, ///< Exec state Idle. + NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM, ///< Exec state write to EEPROM. + NVDATAMGMT_EXEC_STATE_VERIFY_EEPROM_WRITE, ///< Exec state verify EEPROM write. + NVDATAMGMT_EXEC_STATE_READ_FROM_EEPROM, ///< Exec state read from EEPROM. + NVDATAMGMT_EXEC_STATE_ERASE_EEPROM, ///< Exec state erase EEPROM. + NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC, ///< Exec state write to RTC. + NVDATAMGMT_EXEC_STATE_VERIFY_RTC_WRITE, ///< Exec state verify RTC write. + NVDATAMGMT_EXEC_STATE_READ_FROM_RTC, ///< Exec state read from RTC. + NUM_OF_NVDATAMGMT_EXEC_STATES ///< Total number of exec states. } NVDATAMGMT_EXEC_STATE_T; /// NVDataMgmt memory operation modes enumeration. typedef enum NVDataMgmt_Operation { - NVDATAMGMT_NONE = 0, ///< Default mode to prevent any accidental ops - NVDATAMGMT_WRITE, ///< Operation mode write - NVDATAMGMT_READ, ///< Operation mode read - NVDATAMGMT_ERASE_SECTOR, ///< Operation mode erase a sector (EEPROM) - NUM_OF_NVDATAMGMT_OPS_STATES ///< Total number of operation states + NVDATAMGMT_NONE = 0, ///< Default mode to prevent any accidental ops. + NVDATAMGMT_WRITE, ///< Operation mode write. + NVDATAMGMT_READ, ///< Operation mode read. + NVDATAMGMT_ERASE_SECTOR, ///< Operation mode erase a sector (EEPROM). + NUM_OF_NVDATAMGMT_OPS_STATES ///< Total number of operation states. } NVDATAMGMT_OPERATION_STATE_T; -/// NVDataMgmt memory locations enumeration. +/// NVDataMgmt memory locations enumeration typedef enum NVDataMgmt_Location { - NVDATAMGMT_EEPROM = 0, ///< Location EEPROM - NVDATAMGMT_RTC, ///< Location RTC (RAM) - NUM_OF_NVDATAMGMT_LOC_STATES ///< Total number of location states + NVDATAMGMT_EEPROM = 0, ///< Location EEPROM. + NVDATAMGMT_RTC, ///< Location RTC (RAM). + NUM_OF_NVDATAMGMT_LOC_STATES ///< Total number of location states. } NVDATAMGMT_LOCATION_STATE_T; +/// NVDataMgmt process records states +typedef enum NVDataMgmt_Process_Records_States +{ + NVDATAMGMT_PROCESS_RECORD_STATE_IDLE = 0, ///< NVDataMgmt process record idle state. + NVDATAMGMT_PROCESS_RECORD_STATE_SEND_RECORD, ///< NVDataMgmt process record send record state. + NUM_OF_NVDATAMGMT_PROCESS_RECORD_STATES ///< Number of NVDataMgmt process records state. +} PROCESS_RECORD_STATE_T; + +/// NVDataMgmt receive records states +typedef enum NVDataMgmt_Receive_Records_States +{ + NVDATAMGMT_RECEIVE_RECORD_IDLE = 0, ///< NVDataMgmt receive record idle. + NVDATAMGMT_RECEIVE_RECORD_RECEIVE, ///< NVDataMgmt receive record receive. + NUM_OF_NVDATAMGMT_RECEIVE_RECORD_STATES ///< Number of NVDataMgmt receive record. +} RECEIVE_RECORD_STATE_T; + +/// NVDataMgmt records' jobs states +typedef enum NVDataMgmt_Records_Jobs +{ + NVDATAMGMT_CALIBRATION_RECORD = 0, ///< NVDataMgmt process write calibration record. + NVDATAMGMT_SYSTEM_RECORD, ///< NVDataMgmt process write system record. + NVDATAMGMT_SERVICE_RECORD, ///< NVDATAMgmt process service record. + NVDATAMGMT_SCHEDULED_RUNS_RECORD, ///< NVDataMgmt process scheduled runs record. + NUM_OF_NVDATMGMT_RECORDS_JOBS ///< Number of NVDataMgmt records jobs. +} RECORD_JOBS_STATE_T; + +/// NVDataMgmt write record validity check states +typedef enum NVDataMgmt_Write_Record_Validity_Check +{ + NVDATAMGMT_RECORD_NOT_CHECKED = 0, ///< NVDataMgmt (written) record not checked. + NVDATAMGMT_RECORD_VALID, ///< NVDataMgmt record is valid. + NVDATAMGMT_RECORD_NOT_VALID, ///< NVDataMgmt record is not valid. + NUM_OF_NVDATAMGMT_RECORD_VALIDITY_CHECK ///< Number of NVDataMgmt validity check states. +} RECORD_VALIDITY_CHECK_T; + +/// NVDataMgmt active queue +typedef enum NVDataMgmt_Active_Queue +{ + NVDATAMGMT_QUEUE_NONE = 0, ///< NVDataMgmt queue none. + NVDATAMGMT_PROCESS_RECORDS, ///< NVDataMgmt process records. + NVDATAMGMT_PROCESS_LOGS, ///< NVDataMgmt process logs. + NUM_OF_NVDATAMGMT_QUEUES ///< Number of NVDataMgmt queues. +} ACTIVE_QUEUE_T; + #pragma pack(push, 1) +/// Process records specifications structure +typedef struct +{ + U32 startAddress; ///< Jobs spec start address. + U32 sizeofJob; ///< Jobs spec size of job. + U32 maxWriteBufferSize; ///< Jobs max write allowed processing buffer size. + U32 maxReadBufferSize; ///< Jobs max read allowed processing buffer size. + U08* structAddressPtr; + U08* structCRCPtr; +} PROCESS_RECORD_SPECS_T; + +/// Process records job structure +typedef struct +{ + NVDATAMGMT_OPERATION_STATE_T memoryOperation; ///< Memory operation. + NVDATAMGMT_LOCATION_STATE_T memoryLocation; ///< Memory location. + RECORD_JOBS_STATE_T recordJob; ///< Record job (i.e sector 0). +} PROCESS_RECORD_JOB_T; + /// Memory operations structure. typedef struct { - NVDATAMGMT_OPERATION_STATE_T memoryOperation; ///< Memory operation - NVDATAMGMT_LOCATION_STATE_T memoryLocation; ///< Memory location - U32 startAddress; ///< Operation start address - U08 buffer [ MAX_JOB_DATA_SIZE_BYTES ]; ///< Buffer - READ_DATA_T* externalAddress; ///< External address of a buffer - U32 length; ///< Length of a buffer -} MEMORY_OPS_T; + NVDATAMGMT_OPERATION_STATE_T memoryOperation; ///< Memory operation. + NVDATAMGMT_LOCATION_STATE_T memoryLocation; ///< Memory location. + U32 startAddress; ///< Operation start address. + U08 buffer [ MAX_JOB_DATA_SIZE_BYTES ]; ///< Buffer. + READ_DATA_T* externalAddress; ///< External address of a buffer. + U32 length; ///< Length of a buffer. +} MEMORY_LOG_OPS_T; /// Log header structure. typedef struct { - U16 recordCount; ///< Record count - U16 nextWriteIndex; ///< Next write index - U16 nextReadIndex; ///< Next read index - BOOL isHdrCorrupted; ///< Log header corruption flag + U16 recordCount; ///< Record count. + U16 nextWriteIndex; ///< Next write index. + U16 nextReadIndex; ///< Next read index. + BOOL isHdrCorrupted; ///< Log header corruption flag. } LOG_HEADER_T; /// Log record structure. typedef struct { - LOG_HEADER_T logHeader; ///< Log header struct - U16 crc; ///< Log header CRC + LOG_HEADER_T logHeader; ///< Log header struct. + U16 crc; ///< Log header CRC. } LOG_RECORD_T; -/// Treatment time structure. +// ********** HD/DG record structures ********** + +#ifdef _DG_ +/// DG calibration groups structure typedef struct { - U32 treatmentTime; ///< Treatment time - U16 crc; ///< Treatment time CRC -} TREATMENT_TIME_RECORD_T; + DG_PRES_SENSORS_CAL_RECORD_T presSensorsCalRecord; ///< DG pressure sensors. + DG_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< DG flow sensors. + DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< DG load cells. + DG_TEMP_SENSORS_CAL_RECORD_T tempSensorsCalRecord; ///< DG temperature sensors. + DG_COND_SENSORS_CAL_RECORD_T condSensorsCalRecord; ///< DG conductivity sensors. + DG_CONC_PUMPS_CAL_RECORD_T concentratePumpsRecord; ///< DG concentrate pumps. + DG_DRAIN_PUMP_CAL_RECORD_T drainPumpRecord; ///< DG drain pump. + DG_RO_PUMP_CAL_RECORD_T roPumpRecord; ///< DG RO pump. + DG_DRAIN_LINE_VOLUME_T drainLineVolumeRecord; ///< DG drain line volume. + DG_PRE_RO_PURGE_VOLUME_T preROPurgeVolumeRecord; ///< DG RO purge volume. + DG_RESERVOIR_VOLUME_RECORD_T reservoirVolumesRecord; ///< DG reservoir volumes. + DG_GENERIC_VOLUME_RECORD_T genericVolumeRecord; ///< DG generic volume (magic number because the value is unknown). + DG_ACID_CONCENTRATES_RECORD_T acidConcentratesRecord; ///< DG acid concentrates. + DG_BICARB_CONCENTRATES_RECORD_T bicarbConcentratesRecord; ///< DG bicarb concentrates. + DG_FILTERS_CAL_RECORD_T filtersRecord; ///< DG filters. + DG_FANS_CAL_RECORD_T fansRecord; ///< DG fans. + DG_ACCELEROMETER_SENSOR_CAL_RECORD_T accelerometerCalRecord; ///< DG accelerometer sensor. +} DG_CALIBRATION_GROUPS_T; -/// Water consumption structure. +/// DG calibration records structure typedef struct { - U32 waterConsumption; ///< Water consumption - U16 crc; ///< Water consumption CRC -} WATER_CONSUMPTION_RECORD_T; + DG_CALIBRATION_GROUPS_T dgCalibrationGroups; ///< DG calibration groups. + U08 padding[ RECORD_PADDING_LENGTH(DG_CALIBRATION_GROUPS_T, MAX_EEPROM_WRITE_BUFFER_BYTES) - + RECORD_BYTE_SIZE(DG_CALIBRATION_GROUPS_T) ]; ///< DG calibration record padding byte array. + U16 crc; ///< CRC for the DG calibration record structure. +} DG_CALIBRATION_RECORD_T; -/// Manufacturing data structure. +/// DG system group structure typedef struct { - MFG_DATA_T mfgData; ///< Manufacturing data struct - U16 crc; ///< Manufacturing data CRC - U08 Padding[ 0x30 - sizeof(MFG_DATA_T) - sizeof(U16) ]; ///< Padding for reserved mfg data space -} MFG_RECORD_T; + DG_SYSTEM_RECORD_T dgSystemRecord; ///< DG system record. + U08 padding[ RECORD_PADDING_LENGTH(DG_SYSTEM_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) - + RECORD_BYTE_SIZE(DG_SYSTEM_RECORD_T) ]; ///< DG system group padding byte array. + U16 crc; ///< CRC for the DG system group structure. +} DG_SYSTEM_GROUP_T; -/// Service record structure. +/// DG service record structure typedef struct { - SERVICE_DATA_T serviceData; ///< Service date struct - U16 crc; ///< Service data CRC -} SERVICE_RECORD_T; + DG_SERVICE_RECORD_T dgServiceRecord; ///< DG service record. + U08 padding[ RECORD_PADDING_LENGTH(DG_SERVICE_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) - + RECORD_BYTE_SIZE(DG_SERVICE_RECORD_T) ]; ///< DG service group padding. + U16 crc; ///< CRC for the DG service structure. +} DG_SERVICE_GROUP_T; -/// Calibration record structure. +/// DG scheduler record structure typedef struct { - CALIBRATION_DATA_T calData; ///< Calibration data struct - U16 crc; ///< Calibration data CRC - U08 Padding[ 0x50 - sizeof(CALIBRATION_DATA_T) - sizeof(U16) ]; ///< Padding for reserved cal data space -} CALIBRATION_RECORD_T; + DG_SCHEDULED_RUN_RECORD_T dgScheduledRun; ///< DG scheduled runs. + U08 padding[ RECORD_PADDING_LENGTH(DG_SCHEDULED_RUN_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) - + RECORD_BYTE_SIZE(DG_SCHEDULED_RUN_RECORD_T) ]; ///< DG scheduled run group padding. + U16 crc; ///< CRC for the DG scheduled runs structure. +} DG_SCHEDULED_RUNS_GROUP_T; -/// Last disinfection record structure. typedef struct { - DISINFECTION_DATE_T date; ///< Disinfection date (char array) - U16 crc; ///< Disinfection date CRC -} LAST_DISINFECTION_RECORD_T; -#pragma pack(pop) + DG_USAGE_INFO_RECORD_T dgUsageInfo; ///< DG usage info record. + U08 padding[ RECORD_PADDING_LENGTH(DG_USAGE_INFO_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) - + RECORD_BYTE_SIZE(DG_USAGE_INFO_RECORD_T) ]; ///< DG scheduled run group padding. + U16 crc; ///< CRC for the DG usage info structure. +} DG_USAGE_INFO_GROUP_T; +#endif -// Private variables +#ifdef _HD_ +/// HD calibration groups structure +typedef struct +{ + HD_PUMPS_CAL_RECORD_T pumpsCalRecord; ///< HD pumps. + HD_VALVES_CAL_RECORD_T valvesCalRecord; ///< HD valves. + HD_OCCLUSION_SENSORS_CAL_RECORD_T occlusionSensorsCalRecord; ///< HD occlusion sensors. + HD_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< HD flow sensors. + HD_PRESSURE_SENSORS_CAL_RECORD_T pressureSensorsCalRecord; ///< HD pressure sensors. + HD_TEMP_SENSORS_CAL_RECORD_T tempSensorsCalRecord; ///< HD temperature sensors. + HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T heparinForceSensorCalRecord; ///< HD heparin force sensor. + HD_ACCELEROMETER_SENSOR_CAL_RECORD_T accelerometerCalRecord; ///< HD accelerometer sensor. +} HD_CALIBRATION_GROUPS; -static MEMORY_OPS_T jobQueue [ QUEUE_MAX_SIZE ]; ///< Job queue buffer -static MEMORY_OPS_T currentJob; ///< Current job -static LOG_RECORD_T logRecord; ///< Log record variable -static TREATMENT_TIME_RECORD_T treatmentTimeRecord; ///< Treatment time record -static WATER_CONSUMPTION_RECORD_T waterConsumptionRecord; ///< Water consumption record -static MFG_RECORD_T mfgRecord; ///< Manufacturing record -static CALIBRATION_RECORD_T calibrationRecord; ///< Calibration record -static SERVICE_RECORD_T serviceRecord; ///< Service record -static LAST_DISINFECTION_RECORD_T lastDisinfectionRecord; ///< Disinfection record -static U08 queueRearIndex = QUEUE_START_INDEX; ///< Queue rear index -static U08 queueFrontIndex = QUEUE_START_INDEX; ///< Queue front index -static U08 queueCount = 0; ///< Queue count -static NVDATAMGMT_SELF_TEST_STATE_T NVDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_START; ///< NVDataMgmt self-test state variable -static NVDATAMGMT_EXEC_STATE_T NVDataMgmtExecState = NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST; ///< NVDataMgmt exec state variable -static SELF_TEST_STATUS_T NVDataMgmtSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; ///< NVDataMgmt self-test result -static U32 bootloaderFlag = 0; ///< Bootloader flag -static BOOL hasCommandTimedout = FALSE; ///< Boolean flag for timeout of the commands -static U32 currentTime = 0; ///< Current time -static BOOL calRecordIsValid = FALSE; ///< Flag indicates whether stored calibration record was found to be valid -static volatile BOOL powerOffIsImminent = FALSE; ///< Power off warning has been signaled. Non-volatile memory operations should be completed ASAP and then ceased +/// HD calibration records structure +typedef struct +{ + HD_CALIBRATION_GROUPS hdCalibrationGroups; ///< HD calibration groups. + U08 padding[ RECORD_PADDING_LENGTH(HD_CALIBRATION_GROUPS, MAX_EEPROM_WRITE_BUFFER_BYTES) - + RECORD_BYTE_SIZE(HD_CALIBRATION_GROUPS) ]; ///< HD calibration record padding byte array. + U16 crc; ///< CRC for the DG calibration record structure. +} HD_CALIBRATION_RECORD_T; -// *** This declaration will cause a compiler error if CALIBRATION_DATA_T record size exceeds max message payload size. -U08 calRecordSizeAssertion[ ( sizeof( CALIBRATION_DATA_T ) <= MAX_MSG_PAYLOAD_SIZE ? 1 : -1 ) ]; +/// HD system group structure +typedef struct +{ + HD_SYSTEM_RECORD_T hdsystemRecord; ///< HD system record. + U08 padding[ RECORD_PADDING_LENGTH(HD_SYSTEM_RECORD_T, MAX_EEPROM_WRITE_BUFFER_BYTES) - + RECORD_BYTE_SIZE(HD_SYSTEM_RECORD_T) ]; ///< HD system group padding. + U16 crc; ///< CRC for the HD system group structure. +} HD_SYSTEM_GROUP_T; -// Private functions +/// HD service record structure +typedef struct +{ + HD_SERVICE_RECORD_T hdServiceRecord; ///< HD service record. + U08 padding[ RECORD_PADDING_LENGTH(HD_SERVICE_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) - + RECORD_BYTE_SIZE(HD_SERVICE_RECORD_T) ]; ///< HD service group padding. + U16 crc; ///< CRC for the HD service structure. +} HD_SERVICE_GROUP_T; -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestStart ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestEnableEEPROM ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadBootloaderFlag ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadHDTreatmentTime ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadDGWaterConsumption ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadLogRecord ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadMfgRecord ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadCalibrationRecord ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadServiceRecord ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadLastDisinfectionDate ( void ); -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestCheckCRC ( void ); +/// HD usage info record structure +typedef struct +{ + HD_USAGE_INFO_RECORD_T hdUsageInfo; ///< HD usage info record. + U08 padding[ RECORD_PADDING_LENGTH(HD_USAGE_INFO_RECORD_T, MAX_RTC_RAM_OPS_BUFFER_BYTES) - + RECORD_BYTE_SIZE(HD_USAGE_INFO_RECORD_T) ]; ///< HD scheduled run group padding. + U16 crc; ///< CRC for the HD usage info structure. +} HD_USAGE_INFO_GROUP_T; +#endif +#pragma pack(pop) -static NVDATAMGMT_EXEC_STATE_T handleExecWaitForPostState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecIdleState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecEraseState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecWriteToEEPROMState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecReadFromEEPROMState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecWriteToRAMState ( void ); -static NVDATAMGMT_EXEC_STATE_T handleExecReadFromRAMState ( void ); +// Calibration variables +#ifdef _DG_ +static DG_CALIBRATION_RECORD_T dgCalibrationRecord; ///< DG calibration record structure (including padding and final CRC). +static DG_SYSTEM_GROUP_T dgSystemGroup; ///< DG system group structure (including padding and final CRC). +static DG_SERVICE_GROUP_T dgServiceGroup; ///< DG service group structure (including padding and final CRC). +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). +// 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_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_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_SERVICE_RECORD + {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_SCHEDULER_RECORD +}; +#endif +#ifdef _HD_ +static HD_CALIBRATION_RECORD_T hdCalibrationRecord; ///< HD calibration record structure. +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). +// 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_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_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_PROCESS_LAST_SERVICE_RECORD +}; +#endif +static RECORD_JOBS_STATE_T recordToPublish; ///< Record to publish (i.e. calibration, system) +static PROCESS_RECORD_STATE_T nvDataMgmtExecProcessRecordState = NVDATAMGMT_PROCESS_RECORD_STATE_IDLE; ///< NVDataMgmt exec process record state. +static RECEIVE_RECORD_STATE_T nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; ///< NVDataMgmt exec receive record state. +static BOOL hasPublishRecordBeenRequested = FALSE; ///< Record state machine publish request flag. +static U32 calPublishMessageCount = 1; ///< Calibration data publish message counter. +static U32 calPublishTotalMessages = 1; ///< Calibration data total number of messages to be sent. +static U32 calSendDataIntervalCounter = 0; ///< Calibration data send to CAN bust interval counter. +static U32 previousCalMessageNum = 0; ///< Calibration previous message number. +static U32 recordUpdateAddress = 0; ///< DG record update address for all the write operations. +static U32 recordReceiveStartTime = 0; ///< Time stamp the calibration/service was received. +static PROCESS_RECORD_JOB_T recordJobQueue[ QUEUE_MAX_SIZE ]; ///< Record queue jobs. +static U08 recordQueueRearIndex; ///< Record queue rear index. +static U08 recordQueueFrontIndex; ///< Record queue front index. +static U08 recordQueueCount; ///< Record queue count. +static PROCESS_RECORD_JOB_T recordCurrentJob; ///< Record queue current job. +static U32 recordAddressOffset; ///< Record address offset. +static RECORD_VALIDITY_CHECK_T writtenRecordStatus; ///< Record data write validity check. +static U08 writtenRecordCheckBuffer[ MAX_EEPROM_WRITE_BUFFER_BYTES ]; ///< Written record validity check buffer. +static ACTIVE_QUEUE_T activeQueue; ///< Active queue. -// Queue functions +// Private variables +static MEMORY_LOG_OPS_T jobQueue [ QUEUE_MAX_SIZE ]; ///< Job queue buffer. +static MEMORY_LOG_OPS_T currentJob; ///< Current job. +static LOG_RECORD_T logRecord; ///< Log record variable. +static U08 queueRearIndex = QUEUE_START_INDEX; ///< Queue rear index. +static U08 queueFrontIndex = QUEUE_START_INDEX; ///< Queue front index. +static U08 queueCount = 0; ///< Queue count. +static NVDATAMGMT_SELF_TEST_STATE_T nvDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_START; ///< NVDataMgmt self-test state variable. +static NVDATAMGMT_EXEC_STATE_T nvDataMgmtExecState = NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST; ///< NVDataMgmt exec state variable. +static SELF_TEST_STATUS_T nvDataMgmtSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; ///< NVDataMgmt self-test result. +static U32 currentTime = 0; ///< Current time. +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 void setMemoryOpsStruct ( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, +// Private functions +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestStart( void ); +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadCalibrationRecord( void ); +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadSystemRecord( void ); +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadServiceRecord( void ); +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadScheduledRunsRecord( void ); +#ifdef _HD_ +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadHDTreatmentTime( void ); +#endif +#ifdef _DG_ +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadDGWaterConsumption( void ); +#endif +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadLogRecord( void ); +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestCheckCRC( void ); + +static NVDATAMGMT_EXEC_STATE_T handleExecWaitForPostState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecIdleState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecEraseState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecWriteToEEPROMState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecVerifyEEPROMWriteState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecReadFromEEPROMState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecWriteToRAMState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecVerifyRTCWriteState( void ); +static NVDATAMGMT_EXEC_STATE_T handleExecReadFromRAMState( void ); + +static PROCESS_RECORD_STATE_T handleExecProcessRecordIdleState( void ); +static PROCESS_RECORD_STATE_T handleExecProcessRecordSendRecordState( void ); + +// Log queue functions +static void setMemoryOpsStruct( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, U32 startAddress, U08* data, READ_DATA_T* extAddress, U32 length ); -static void enqueue ( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, +static void enqueue( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, U32 startAddress, U08* data, READ_DATA_T* extAddress, U32 length ); -static void dequeue ( void ); -static U32 prepareWriteLogJobAndGetStartAddress ( U08* data ); -static U32 prepareReadLogJobAndGetStartAddress ( void ); -static BOOL isQueueEmpty ( void ); -static BOOL isQueueFull ( void ); -static U32 getAvailableQueueCount ( void ); -static BOOL enqueueBank7Sector0Records ( void ); +static void dequeue( void ); +static U32 prepareWriteLogJobAndGetStartAddress( U08* data ); +static U32 prepareReadLogJobAndGetStartAddress( void ); +static BOOL isQueueEmpty( void ); +static BOOL isQueueFull( void ); +static U32 getAvailableQueueCount( void ); // Helper functions +static BOOL didCommandTimeout( ALARM_ID_T alarm, U08* state ); +static BOOL eraseDataLogSectors( void ); +static void monitorNewCalSignal( void ); -static BOOL didCommandTimeout ( ALARM_ID_T alarm, U08* state ); -static BOOL eraseDataLogSectors ( void ); +// Record operations queue functions +static void enqueueRecordJob( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, RECORD_JOBS_STATE_T job ); +static void dequeueRecordJob( void ); +static BOOL isRecordQueueEmpty( void ); +static U32 getAvailableRecordQueueCount( void ); +static BOOL enqueueSector0Records( void ); +// Record check helper functions +static BOOL areRecordsValid( void ); +static BOOL isPolynomialRecordValid( POLYNOMIAL_CAL_PAYLOAD_T* record ); + +#ifdef _DG_ +static BOOL isDGCalibrationRecordValid( 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 ); +static BOOL isDGDrainLineVolRecordValid( DG_DRAIN_LINE_VOLUME_T* record ); +static BOOL isDGReservoirVolRecordValid( DG_RESERVOIR_VOLUME_DATA_T* record ); +static BOOL isDGGenericVolRecordValid( DG_GENERIC_VOLUME_DATA_T* record ); +static BOOL isDGAcidConcentrateRecordValid( DG_ACID_CONCENTRATE_T* record ); +static BOOL isDGBicarbConcentrateRecordValid( DG_BICARB_CONCENTRATE_T* record ); +static BOOL isDGFilterRecordValid( DG_FILTER_CAL_RECORD_T* record ); +static BOOL isDGFanRecordValid( DG_FAN_CAL_RECORD_T* record ); +static BOOL isDGAccelerometerSensorRecordValid( DG_ACCELEROMETER_SENSOR_CAL_RECORD_T* record ); +#endif +#ifdef _HD_ +static BOOL isHDCalibrationRecordValid( 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 ); +#endif + /*********************************************************************//** * @brief * The initNVDataMgmt function initializes the module. - * @details Inputs: NVDataMgmtSelfTestState, NVDataMgmtExecState, NVDataMgmtSelfTestResult, - * queueRearIndex, queueFrontIndex, queueCount - * @details Outputs: NVDataMgmtSelfTestState, NVDataMgmtExecState, NVDataMgmtSelfTestResult, - * queueRearIndex, queueFrontIndex, queueCount + * @details Inputs: none + * @details Outputs: nvDataMgmtSelfTestState, nvDataMgmtExecState, + * nvDataMgmtSelfTestResult, nvDataMgmtExecProcessRecordState, + * nvDataMgmtExecReceiveRecordState, queueRearIndex, queueFrontIndex, + * queueFrontIndex, queueCount, recordUpdateAddress, recordQueueRearIndex, + * recordQueueFrontIndex, recordQueueCount, recordAddressOffset, + * writtenRecordStatus, hasPublishRecordBeenRequested, isNewCalAvailable, + * newCalStartTimer * @return none *************************************************************************/ -void initNVDataMgmt ( void ) +void initNVDataMgmt( void ) { - NVDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_START; - NVDataMgmtExecState = NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST; - NVDataMgmtSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - queueRearIndex = QUEUE_START_INDEX; - queueFrontIndex = QUEUE_START_INDEX; - queueCount = 0; + // Initialize the parameters + nvDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_START; + nvDataMgmtExecState = NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST; + nvDataMgmtSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; + nvDataMgmtExecProcessRecordState = NVDATAMGMT_PROCESS_RECORD_STATE_IDLE; + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + queueRearIndex = QUEUE_START_INDEX; + queueFrontIndex = QUEUE_START_INDEX; + queueCount = 0; + recordUpdateAddress = 0; + recordQueueRearIndex = QUEUE_START_INDEX; + recordQueueFrontIndex = QUEUE_START_INDEX; + recordQueueCount = 0; + recordAddressOffset = 0; + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_CHECKED; + hasPublishRecordBeenRequested = FALSE; + isNewCalAvailable = FALSE; + newCalStartTimer = 0; + + // Initialize and activate flash bank 7 Fapi_initializeFlashBanks( ROUNDED_HCLK_FREQ ); Fapi_setActiveFlashBank( Fapi_FlashBank7 ); + Fapi_enableEepromBankSectors( BANK7_SECTOR_0_31_ENABLE_BIT_MASK, BANK7_SECTOR_32_63_ENABLE_BIT_MASK ); } /*********************************************************************//** * @brief * The signalPowerOffWarning signals this module that system power off is - * imminent and any non-volatile data writes in progress should be wrapped up - * quickly and any pending non-volatile data writes should not be started. - * @details Inputs: none + * imminent and any non-volatile data writes in progress should be wrapped + * up quickly and any pending non-volatile data writes should not be started. + * @details Inputs: powerOffIsImminent * @details Outputs: powerOffIsImminent * @return none *************************************************************************/ @@ -311,140 +567,311 @@ /*********************************************************************//** * @brief - * The setMfgData updates the structure that holds the manufacturing data, - * calls another function to calculate the CRC for the provided data and - * calls another function to erase sector 0 and write the new manufacturing - * data. - * @details Inputs: mfgRecord - * @details Outputs: mfgRecord - * @return TRUE is the enqueue was successfully scheduled + * The execNVDataMgmt runs the NVDataMgmt main tasks. + * @details Inputs: nvDataMgmtExecState + * @details Outputs: nvDataMgmtExecState + * @return none *************************************************************************/ -BOOL setMfgData ( MFG_DATA_T data ) +void execNVDataMgmt( void ) { - mfgRecord.mfgData = data; - mfgRecord.crc = crc16 ( (U08*)&mfgRecord.mfgData, sizeof(MFG_DATA_T) ); - BOOL status = enqueueBank7Sector0Records(); - return status; + switch ( nvDataMgmtExecState ) + { + case NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST: + nvDataMgmtExecState = handleExecWaitForPostState(); + break; + + case NVDATAMGMT_EXEC_STATE_IDLE: + nvDataMgmtExecState = handleExecIdleState(); + break; + + case NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM: + nvDataMgmtExecState = handleExecWriteToEEPROMState(); + break; + + case NVDATAMGMT_EXEC_STATE_VERIFY_EEPROM_WRITE: + nvDataMgmtExecState = handleExecVerifyEEPROMWriteState(); + break; + + case NVDATAMGMT_EXEC_STATE_READ_FROM_EEPROM: + nvDataMgmtExecState = handleExecReadFromEEPROMState(); + break; + + case NVDATAMGMT_EXEC_STATE_ERASE_EEPROM: + nvDataMgmtExecState = handleExecEraseState(); + break; + + case NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC: + nvDataMgmtExecState = handleExecWriteToRAMState(); + break; + + case NVDATAMGMT_EXEC_STATE_VERIFY_RTC_WRITE: + nvDataMgmtExecState = handleExecVerifyRTCWriteState(); + break; + + case NVDATAMGMT_EXEC_STATE_READ_FROM_RTC: + nvDataMgmtExecState = handleExecReadFromRAMState(); + break; + + default: +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, nvDataMgmtExecState ); +#else + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, nvDataMgmtExecState ); +#endif + nvDataMgmtExecState = NVDATAMGMT_EXEC_STATE_IDLE; + break; + } } /*********************************************************************//** * @brief - * The getMfgData returns the data in the structure that holds manufacturing - * record to buffer that the caller has provided. - * @details Inputs: mfgRecord - * @details Outputs: none - * @param buffer address of manufacturing data buffer - * @return TRUE if the buffer pointer was not null and the copy was successful + * The execNVDataMgmtSelfTest runs the NVDataMgmt POST during the self-test. + * @details Inputs: nvDataMgmtSelfTestState, nvDataMgmtSelfTestResult + * @details Outputs: nvDataMgmtSelfTestState + * @return nvDataMgmtSelfTestResult the result of self-test *************************************************************************/ -BOOL getMfgData ( MFG_DATA_T* buffer ) +SELF_TEST_STATUS_T execNVDataMgmtSelfTest ( void ) { - BOOL status = FALSE; - - if ( buffer != NULL ) + switch ( nvDataMgmtSelfTestState ) { - memcpy ( buffer, (U08*)&mfgRecord.mfgData, sizeof(MFG_DATA_T) ); - status = TRUE; + case NVDATAMGMT_SELF_TEST_STATE_START: + nvDataMgmtSelfTestState = handleSelfTestStart(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD: + nvDataMgmtSelfTestState = handleSelfTestReadCalibrationRecord(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_READ_SYS_RECORD: + nvDataMgmtSelfTestState = handleSelfTestReadSystemRecord(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD: + nvDataMgmtSelfTestState = handleSelfTestReadServiceRecord(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_READ_SCHEDULED_RUNS_RECORD: + nvDataMgmtSelfTestState = handleSelfTestReadScheduledRunsRecord(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD: + nvDataMgmtSelfTestState = handleSelfTestReadLogRecord(); + break; +#ifdef _HD_ + case NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME: + nvDataMgmtSelfTestState = handleSelfTestReadHDTreatmentTime(); + break; +#endif +#ifdef _DG_ + case NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION: + nvDataMgmtSelfTestState = handleSelfTestReadDGWaterConsumption(); + break; +#endif + case NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC: + nvDataMgmtSelfTestState = handleSelfTestCheckCRC(); + break; + + case NVDATAMGMT_SELF_TEST_STATE_COMPLETE: + // Done with POST. Do nothing + break; + + default: +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, nvDataMgmtSelfTestState ); +#else + SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, nvDataMgmtSelfTestState ); +#endif + nvDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_COMPLETE; + nvDataMgmtSelfTestResult = SELF_TEST_STATUS_FAILED; + break; } - return status; + return nvDataMgmtSelfTestResult; } /*********************************************************************//** * @brief - * The setCalibrationData updates the structure that holds the calibration data, - * calls another function to calculate the CRC for the provided data and - * calls another function to erase sector 0 and write the new manufacturing - * data. - * @details Inputs: calibrationRecord - * @details Outputs: calibrationRecord - * @param data calibration data structure - * @return TRUE if updating was successfully scheduled + * The execNVDataMgmtProcessRecord runs the NVDataMgmt send records related + * to tasks. + * @details Inputs: nvDataMgmtExecProcessRecordState, + * nvDataMgmtExecReceiveRecordState, recordReceiveStartTime + * @details Outputs: nvDataMgmtExecProcessRecordState, + * nvDataMgmtExecReceiveRecordState + * @return none *************************************************************************/ -BOOL setCalibrationData ( CALIBRATION_DATA_T data ) +void execNVDataMgmtProcessRecord( void ) { - BOOL status; + switch ( nvDataMgmtExecProcessRecordState ) + { + case NVDATAMGMT_PROCESS_RECORD_STATE_IDLE: + nvDataMgmtExecProcessRecordState = handleExecProcessRecordIdleState(); + break; - calibrationRecord.calData = data; - calibrationRecord.crc = crc16( (U08*)&calibrationRecord.calData, sizeof(CALIBRATION_DATA_T) ); - // The entire sector 0 must be erased and re-written again - status = enqueueBank7Sector0Records(); + case NVDATAMGMT_PROCESS_RECORD_STATE_SEND_RECORD: + nvDataMgmtExecProcessRecordState = handleExecProcessRecordSendRecordState(); + break; - return status; + default: +#ifdef _DG_ + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_NVDATAMGMT_EXEC_CAL_STATE, nvDataMgmtExecProcessRecordState ); +#else + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_NVDATAMGMT_EXEC_CAL_STATE, nvDataMgmtExecProcessRecordState ); +#endif + nvDataMgmtExecProcessRecordState = NVDATAMGMT_PROCESS_RECORD_STATE_IDLE; + break; + } + + // Check if the exec receive records is not idle + // This section checks the status of the asynchronous state machine that receives + // data from Dialin. + if ( nvDataMgmtExecReceiveRecordState != NVDATAMGMT_RECEIVE_RECORD_IDLE ) + { + // Check if the data receiving process has timed out. The exec receive record + // state machine is asynchronous so it is checked in this state machine + if ( TRUE == didTimeout( recordReceiveStartTime, RECORD_DATA_RECEIVE_TIMEOUT_MS ) ) + { + // Exec receive state machine timed out. Schedule a read to update the structure + enqueueRecordJob( NVDATAMGMT_READ, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } + } + + // Check the calibration signal + monitorNewCalSignal(); } /*********************************************************************//** * @brief - * The getCalibrationData function returns the data in the structure that hold - * calibration record to buffer that the caller has provided. - * @details Inputs: calibrationRecord - * @details Outputs: none - * @param buffer address of calibration data buffer - * @return TRUE if calibration record valid + * The getDGCalibrationRecord function sets the calibration state machine + * to read and publish calibration record. + * @details Inputs: hasPublishRecordBeenRequested, recordToPublish + * nvDataMgmtExecProcessRecordState + * @details Outputs: hasPublishRecordBeenRequested, recordToPublish + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL getCalibrationData ( CALIBRATION_DATA_T* buffer ) +BOOL getCalibrationRecord( void ) { BOOL status = FALSE; - if ( buffer != NULL ) + // Check if the state machine is in idle state and then set the request + if ( nvDataMgmtExecProcessRecordState == NVDATAMGMT_PROCESS_RECORD_STATE_IDLE ) { - memcpy ( buffer, (U08*)&calibrationRecord.calData, sizeof(CALIBRATION_DATA_T) ); - status = calRecordIsValid; + hasPublishRecordBeenRequested = TRUE; + recordToPublish = NVDATAMGMT_CALIBRATION_RECORD; + status = TRUE; } return status; } /*********************************************************************//** * @brief - * The testResetCalibrationData function erases the calibration data. - * @details - * Inputs: calibrationRecord - * Outputs: none - * @param key a key is required to erase calibration data - * @return TRUE if calibration record valid + * The setCalibrationRecord function writes the calibration record that + * is received from Dialin into the calibration structure. + * @details Inputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @details Outputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @param currentMessage: current message number that is received from + * Dialin + * @param totalMessages: total number of messages from Dialin + * @param length: message length in bytes + * @param *addressPtr: address to the beginning of the calibration data from + * Dialin + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL testResetCalibrationData( U32 key ) +BOOL setCalibrationRecord( U32 currentMessage, U32 totalMessages, U32 length, U08 *addressPtr ) { - BOOL status = FALSE; + BOOL status = TRUE; - // tester must be logged in - if ( TRUE == isTestingActivated() ) + // If the calibration message number is the first message number and receive exec state is idle, switch to idle + if ( ( RECORD_DATA_FIRST_RECEIVING_MSG_NUM == currentMessage ) && ( nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_IDLE ) ) { - // verify key - if ( ERASE_CALIBRATION_KEY == key ) + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_RECEIVE; + recordReceiveStartTime = getMSTimerCount(); + previousCalMessageNum = 0; + recordUpdateAddress = 0; + } + + // Check if there is still a message left to be received + if ( ( nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_RECEIVE ) && ( currentMessage <= totalMessages ) ) + { + // Check if the current message is different from the previous message by 1 + if ( RECORD_DATA_MAX_MESSAGE_DFFIRENCE == ( currentMessage - previousCalMessageNum ) ) { - // erase calibration record - memset( (U08*)&calibrationRecord.calData, 0, sizeof(CALIBRATION_DATA_T) ); - // zero CRC so integrity check will fail unless calibration data set again - calibrationRecord.crc = 0; - // save erased calibration record - status = enqueueBank7Sector0Records(); + // Define a pointer that points to the DG calibration record + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS[ NVDATAMGMT_CALIBRATION_RECORD ]; + U08* ptr = recordSpec.structAddressPtr; + + // Offset the pointer to length that we should start writing from + ptr += recordUpdateAddress; + + // Copy the data into the buffer + memcpy(ptr, addressPtr, length); + + // Check if the current message is total messages + // and 0 everything out since we are done writing + if ( currentMessage == totalMessages ) + { + U16 calcCRC = crc16( recordSpec.structAddressPtr, recordSpec.sizeofJob - sizeof(U16) ); + U16 recordCRC = *(U16*)recordSpec.structCRCPtr; + + if ( calcCRC != recordCRC ) + { + // CRC failed, request a read to read the data back from NV memory and update the structure + enqueueRecordJob( NVDATAMGMT_READ, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + status = FALSE; + } + else + { + // CRC passed, enqueue an erase, a write of calibration data and a write of service record + BOOL scheduleStatus = enqueueSector0Records(); + + // Signal that there is a new calibration record available. + newCalStartTimer = getMSTimerCount(); + isNewCalAvailable = TRUE; + } + // Done with receiving data, go back to idle + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } + else + { + // Update the length as it has successfully been written + recordUpdateAddress += length; + + // Now the current message is the previous message + previousCalMessageNum = currentMessage; + } } + else + { + status = FALSE; + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } } return status; } /*********************************************************************//** * @brief - * The setServiceDate updates the structure that holds the calibration data, - * calls another function to calculate the CRC for the provided data if - * there is enough queues available, it schedules a write to RTC RAM. - * @details Inputs: serviceRecord - * @details Outputs: serviceRecord - * @param data service data buffer - * @return TRUE if the queue had enough space to schedule the job + * The getSystemRecord function sets the system state machine to read + * and publish system record. + * @details Inputs: hasPublishRecordBeenRequested, recordToPublish + * nvDataMgmtExecProcessRecordState + * @details Outputs: hasPublishRecordBeenRequested, recordToPublish + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL setServiceDate ( SERVICE_DATA_T data ) +BOOL getSystemRecord( void ) { BOOL status = FALSE; - serviceRecord.serviceData = data; - serviceRecord.crc = crc16 ( (U08*)&serviceRecord.serviceData, sizeof(SERVICE_DATA_T) ); - if ( !isQueueFull() ) + // Check if the state machine is in idle state and then set the request + if ( nvDataMgmtExecProcessRecordState == NVDATAMGMT_PROCESS_RECORD_STATE_IDLE ) { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, SERVICE_DATE_START_ADDRESS, - (U08*)&serviceRecord, 0, sizeof(SERVICE_RECORD_T) ); + hasPublishRecordBeenRequested = TRUE; + recordToPublish = NVDATAMGMT_SYSTEM_RECORD; status = TRUE; } @@ -453,43 +880,104 @@ /*********************************************************************//** * @brief - * The getServiceDate returns the data in the structure that holds service - * date to buffer that the caller has provided. - * @details Inputs: serviceRecord - * @details Outputs: none - * @param buffer address of service data buffer - * @return TRUE if the buffer address was not null + * The setSystemRecord function writes the system record that is received + * from Dialin into the system structure. + * @details Inputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @details Outputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @param currentMessage: current message number that is received from + * Dialin + * @param totalMessages: total number of messages from Dialin + * @param length: message length in bytes + * @param *addressPtr: address to the beginning of the calibration data + * from Dialin + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL getServiceDate ( SERVICE_DATA_T* buffer ) +BOOL setSystemRecord( U32 currentMessage, U32 totalMessages, U32 length, U08 *addressPtr ) { - BOOL status = FALSE; + BOOL status = TRUE; - if ( buffer != NULL ) + // If the calibration message number is the first message number and receive exec state is idle, switch to idle + if ( RECORD_DATA_FIRST_RECEIVING_MSG_NUM == currentMessage && nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_IDLE ) { - memcpy ( buffer, (U08*)&serviceRecord.serviceData, sizeof(SERVICE_DATA_T) ); - status = TRUE; + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_RECEIVE; + recordReceiveStartTime = getMSTimerCount(); + previousCalMessageNum = 0; + recordUpdateAddress = 0; } + // Check if there is still a message left to be received + if ( nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_RECEIVE && currentMessage <= totalMessages ) + { + // Check if the current message is different from the previous message by 1 + if ( RECORD_DATA_MAX_MESSAGE_DFFIRENCE == ( currentMessage - previousCalMessageNum ) ) + { + // Define a pointer that points to the DG calibration record + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS [ NVDATAMGMT_SYSTEM_RECORD ]; + U08* ptr = recordSpec.structAddressPtr; + + // Offset the pointer to length that we should start writing from + ptr += recordUpdateAddress; + + memcpy(ptr, addressPtr, length); + + // Check if the current message is total messages + // and 0 everything out since we are done writing + if ( currentMessage == totalMessages ) + { + U16 calcCRC = crc16 ( recordSpec.structAddressPtr, recordSpec.sizeofJob - sizeof(U16) ); + // Get the CRC of the structure without the last 16 bits which is the CRC as well as the padding values + U16 recordCRC = *(U16*)recordSpec.structCRCPtr; + + if ( calcCRC != recordCRC ) + { + // CRC failed, request a read to read the data back from NV memory and update the structure + enqueueRecordJob( NVDATAMGMT_READ, NVDATAMGMT_EEPROM, NVDATAMGMT_SYSTEM_RECORD ); + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + status = FALSE; + } + else + { + // CRC passed, enqueue an erase, a write of calibration data and a write of service record + BOOL scheduleStatus = enqueueSector0Records(); + + // Done with receiving data, go back to idle + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } + } + else + { + // Update the length as it has successfully been written + recordUpdateAddress += length; + + // Now the current message is the previous message + previousCalMessageNum = currentMessage; + } + } + } + return status; } /*********************************************************************//** * @brief - * The writeLogData checks if the queue is not full and if it is not, it calls - * enqueue to schedule a job for writing the log data. - * @details Inputs: logRecord - * @details Outputs: none - * @param data address of log data buffer - * @return TRUE if the queue is not full and if the log header is not corrupted + * The getServiceRecord function sets the system state machine to read + * and publish service record. + * @details Inputs: hasPublishRecordBeenRequested, recordToPublish + * hasPublishRecordBeenRequested + * @details Outputs: hasPublishRecordBeenRequested, recordToPublish + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL writeLogData ( LOG_DATA_T* data ) +BOOL getServiceRecord( void ) { BOOL status = FALSE; - // If the header is corrupted, no more data is allowed to be written - if ( !isQueueFull() && logRecord.logHeader.isHdrCorrupted == FALSE ) + // Check if the state machine is in idle state and then set the request + if ( nvDataMgmtExecProcessRecordState == NVDATAMGMT_PROCESS_RECORD_STATE_IDLE ) { - enqueue ( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, 0, (U08*)&data, 0, sizeof(LOG_DATA_T) ); + hasPublishRecordBeenRequested = TRUE; + recordToPublish = NVDATAMGMT_SERVICE_RECORD; status = TRUE; } @@ -498,47 +986,104 @@ /*********************************************************************//** * @brief - * The readLogData checks if the queue is not full and if it is not, it calls - * enqueue to schedule a job for writing the log data. - * @details Inputs: none - * @details Outputs: none - * @param buffer address of read data buffer - * @param length length of the data log - * @return TRUE if there are enough queues available for the job + * The setServiceRecord function writes the service record that + * is received from Dialin into the service structure. + * @details Inputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @details Outputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @param currentMessage: current message number that is received from + * Dialin + * @param totalMessages: total number of messages from Dialin + * @param length: message length in bytes + * @param *addressPtr: address to the beginning of the calibration data + * from Dialin + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL readLogData ( READ_DATA_T* buffer, U32 length ) +BOOL setServiceRecord( U32 currentMessage, U32 totalMessages, U32 length, U08 *addressPtr ) { - BOOL status = FALSE; - U32 availableQueue = getAvailableQueueCount(); + BOOL status = TRUE; - if ( availableQueue >= MIN_JOBS_NEEDED_FOR_DATA_LOG ) + // If the calibration message number is the first message number and receive exec state is idle, switch to idle + if ( RECORD_DATA_FIRST_RECEIVING_MSG_NUM == currentMessage && nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_IDLE ) { - enqueue( NVDATAMGMT_READ, NVDATAMGMT_EEPROM, 0, 0, buffer, length ); - status = TRUE; + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_RECEIVE; + recordReceiveStartTime = getMSTimerCount(); + previousCalMessageNum = 0; + recordUpdateAddress = 0; } + // Check if there is still a message left to be received + if ( nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_RECEIVE && currentMessage <= totalMessages ) + { + // Check if the current message is different from the previous message by 1 + if ( RECORD_DATA_MAX_MESSAGE_DFFIRENCE == ( currentMessage - previousCalMessageNum ) ) + { + // Define a pointer that points to the DG calibration record + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS [ NVDATAMGMT_SERVICE_RECORD ]; + U08* ptr = recordSpec.structAddressPtr; + + // Offset the pointer to length that we should start writing from + ptr += recordUpdateAddress; + + memcpy(ptr, addressPtr, length); + + // Check if the current message is total messages + // and 0 everything out since we are done writing + if ( currentMessage == totalMessages ) + { + U16 calcCRC = crc16 ( recordSpec.structAddressPtr, recordSpec.sizeofJob - sizeof(U16) ); + // Get the CRC of the structure without the last 16 bits which is the CRC as well as the padding values + U16 recordCRC = *(U16*)recordSpec.structCRCPtr; + + if ( calcCRC != recordCRC ) + { + // CRC failed, request a read to read the data back from NV memory and update the structure + enqueueRecordJob( NVDATAMGMT_READ, NVDATAMGMT_RTC, NVDATAMGMT_SERVICE_RECORD ); + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + status = FALSE; + } + else + { + // CRC passed write the last service record to the RTC RAM + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, NVDATAMGMT_SERVICE_RECORD ); + + // Done with receiving data, go back to idle + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } + } + else + { + // Update the length as it has successfully been written + recordUpdateAddress += length; + + // Now the current message is the previous message + previousCalMessageNum = currentMessage; + } + } + } + return status; } /*********************************************************************//** * @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 - * @return TRUE if the queue was not full so the job was scheduled successfully + * The getScheduledRunsRecord function sets the system state machine + * to read and publish the scheduled runs record. + * @details Inputs: hasPublishRecordBeenRequested, recordToPublish + * hasPublishRecordBeenRequested + * @details Outputs: hasPublishRecordBeenRequested, recordToPublish + * @return TRUE if the request was successfully registered *************************************************************************/ -BOOL setTreatmentTime ( U32 hours ) +BOOL getScheduledRunsRecord( void ) { BOOL status = FALSE; - treatmentTimeRecord.treatmentTime = hours; - treatmentTimeRecord.crc = crc16 ( (U08*)&treatmentTimeRecord.treatmentTime, sizeof(U32) ); - if ( !isQueueFull() ) + // Check if the state machine is in idle state and then set the request + if ( nvDataMgmtExecProcessRecordState == NVDATAMGMT_PROCESS_RECORD_STATE_IDLE ) { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, HD_TREATMENT_TIME_ADDRESS, - (U08*)&treatmentTimeRecord, 0, sizeof(TREATMENT_TIME_RECORD_T) ); + hasPublishRecordBeenRequested = TRUE; + recordToPublish = NVDATAMGMT_SCHEDULED_RUNS_RECORD; status = TRUE; } @@ -547,205 +1092,578 @@ /*********************************************************************//** * @brief - * The getTreatmentTime returns the total number treatment hours of the - * HD device. + * The setScheduledRunsRecord function writes the scheduled runs record that + * is received from Dialin into the scheduled runs structure. + * @details Inputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @details Outputs: nvDataMgmtExecReceiveRecordState, recordUpdateAddress + * recordReceiveStartTime, previousCalMessageNum + * @param currentMessage: current message number that is received from + * Dialin + * @param totalMessages: total number of messages from Dialin + * @param length: message length in bytes + * @param *addressPtr: address to the beginning of the calibration data + * from Dialin + * @return TRUE if the request was successfully registered + *************************************************************************/ +BOOL setScheduledRunsRecord( U32 currentMessage, U32 totalMessages, U32 length, U08 *addressPtr ) +{ + BOOL status = TRUE; + + // If the calibration message number is the first message number and receive exec state is idle, switch to idle + if ( RECORD_DATA_FIRST_RECEIVING_MSG_NUM == currentMessage && nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_IDLE ) + { + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_RECEIVE; + recordReceiveStartTime = getMSTimerCount(); + previousCalMessageNum = 0; + recordUpdateAddress = 0; + } + + // Check if there is still a message left to be received + if ( nvDataMgmtExecReceiveRecordState == NVDATAMGMT_RECEIVE_RECORD_RECEIVE && currentMessage <= totalMessages ) + { + // Check if the current message is different from the previous message by 1 + if ( RECORD_DATA_MAX_MESSAGE_DFFIRENCE == ( currentMessage - previousCalMessageNum ) ) + { + // Define a pointer that points to the DG calibration record + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS [ NVDATAMGMT_SCHEDULED_RUNS_RECORD ]; + U08* ptr = recordSpec.structAddressPtr; + + // Offset the pointer to length that we should start writing from + ptr += recordUpdateAddress; + + memcpy(ptr, addressPtr, length); + + // Check if the current message is total messages + // and 0 everything out since we are done writing + if ( currentMessage == totalMessages ) + { + U16 calcCRC = crc16 ( recordSpec.structAddressPtr, recordSpec.sizeofJob - sizeof(U16) ); + // Get the CRC of the structure without the last 16 bits which is the CRC as well as the padding values + U16 recordCRC = *(U16*)recordSpec.structCRCPtr; + + if ( calcCRC != recordCRC ) + { + // CRC failed, request a read to read the data back from NV memory and update the structure + enqueueRecordJob( NVDATAMGMT_READ, NVDATAMGMT_RTC, NVDATAMGMT_SCHEDULED_RUNS_RECORD ); + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + status = FALSE; + } + else + { + // CRC passed write the last service record to the RTC RAM + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, NVDATAMGMT_SCHEDULED_RUNS_RECORD ); + + // Done with receiving data, go back to idle + nvDataMgmtExecReceiveRecordState = NVDATAMGMT_RECEIVE_RECORD_IDLE; + } + } + else + { + // Update the length as it has successfully been written + recordUpdateAddress += length; + + // Now the current message is the previous message + previousCalMessageNum = currentMessage; + } + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isNewCalibrationRecordAvailable function returns the status of a + * new calibration availability. * @details Inputs: none - * Output: none - * @return treatment time as U32 + * @details Outputs: none + * @return isNewCalAvailable which is TRUE is cal is available, otherwise + * FALSE *************************************************************************/ -U32 getTreatmentTime ( void ) +BOOL isNewCalibrationRecordAvailable( void ) { - return treatmentTimeRecord.treatmentTime; + return isNewCalAvailable; } +#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 - * @param liters consumed water is liters - * @return TRUE if queue is not full + * The getDGPressureSensorsCalibrationRecord function returns the DG pressure + * sensors record. + * @details Inputs: none + * @details Outputs: none + * @return DG pressure sensors calibration record *************************************************************************/ -BOOL setWaterConsumption ( U32 liters ) +DG_PRES_SENSORS_CAL_RECORD_T getDGPressureSensorsCalibrationRecord( void ) { - BOOL status = FALSE; - waterConsumptionRecord.waterConsumption = liters; - waterConsumptionRecord.crc = crc16 ( (U08*)&waterConsumptionRecord.waterConsumption, sizeof(U32) ); + return dgCalibrationRecord.dgCalibrationGroups.presSensorsCalRecord; +} - if ( !isQueueFull() ) - { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_CONSUMED_WATER_ADDRESS, - (U08*)&waterConsumptionRecord, 0, sizeof(WATER_CONSUMPTION_RECORD_T) ); - status = TRUE; - } +/*********************************************************************//** + * @brief + * The getDGFlowSensorsCalibrationRecord function returns the DG flow + * sensors record. + * @details Inputs: none + * @details Outputs: none + * @return DG flow sensors calibration record + *************************************************************************/ +DG_FLOW_SENSORS_CAL_RECORD_T getDGFlowSensorsCalibrationRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.flowSensorsCalRecord; +} - return status; +/*********************************************************************//** + * @brief + * The getDGLoadCellsCalibrationRecord function returns the DG load cells + * record. + * @details Inputs: none + * @details Outputs: none + * @return DG load cells calibration record + *************************************************************************/ +DG_LOAD_CELLS_CAL_RECORD_T getDGLoadCellsCalibrationRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.loadCellsCalRecord; } /*********************************************************************//** * @brief - * The getWaterConsumption returns the amount of consumed water. + * The getDGTemperatureSensorsCalibrationRecord function returns the DG + * temperature sensors calibration record. * @details Inputs: none * @details Outputs: none - * @return water consumption as a U32 + * @return DG temperature sensors calibration record *************************************************************************/ -U32 getWaterConsumption ( void ) +DG_TEMP_SENSORS_CAL_RECORD_T getDGTemperatureSensorsCalibrationRecord( void ) { - return waterConsumptionRecord.waterConsumption; + return dgCalibrationRecord.dgCalibrationGroups.tempSensorsCalRecord; } /*********************************************************************//** * @brief - * The setDisinfectionDate gets the last disinfection date, calculates the - * CRC for it and if the queue is not full, it schedules a write to RTC RAM - * to store the last date. - * @details Inputs: lastDisinfectionRecord - * @details Outputs: lastDisinfectionRecord - * @param date disinfection date buffer - * @return TRUE if the queue was not full + * The getDGConducitivitySensorsCalibrationRecord function returns the DG + * conductivity sensors calibration record. + * @details Inputs: none + * @details Outputs: none + * @return DG conductivity sensors calibration record *************************************************************************/ -BOOL setDisinfectionDate ( DISINFECTION_DATE_T date ) +DG_COND_SENSORS_CAL_RECORD_T getDGConducitivitySensorsCalibrationRecord( void ) { - BOOL status = FALSE; - memcpy ( lastDisinfectionRecord.date.disinfectionDate, date.disinfectionDate, sizeof(DISINFECTION_DATE_T) ); - lastDisinfectionRecord.crc = crc16 ( (U08*)&lastDisinfectionRecord.date.disinfectionDate, sizeof(DISINFECTION_DATE_T) ); + return dgCalibrationRecord.dgCalibrationGroups.condSensorsCalRecord; +} - if ( !isQueueFull() ) - { - enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, LAST_DISINFECTION_DATE_ADDRESS, - (U08*)&lastDisinfectionRecord, 0, sizeof(LAST_DISINFECTION_RECORD_T) ); - status = TRUE; - } +/*********************************************************************//** + * @brief + * The getDGROPumpRecord function returns the DG RO pump calibration record. + * @details Inputs: none + * @details Outputs: none + * @return DG RO pump calibration record + *************************************************************************/ +DG_RO_PUMP_CAL_RECORD_T getDGROPumpRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.roPumpRecord; +} - return status; +/*********************************************************************//** + * @brief + * The getDGConcetnratePumpsRecord function returns the DG concentrate + * pumps calibration record. + * @details Inputs: none + * @details Outputs: none + * @return DG concentrate pumps calibration record + *************************************************************************/ +DG_CONC_PUMPS_CAL_RECORD_T getDGConcetnratePumpsRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.concentratePumpsRecord; } /*********************************************************************//** * @brief - * The getDisinfectionDate populates the provided buffer with the last - * disinfection date. - * @details Inputs: lastDisinfectionRecord + * The getDGDrainPumpRecord function returns the DG drain pump calibration + * record. + * @details Inputs: none * @details Outputs: none - * @param buffer address of disinfection date buffer - * @return TRUE if the buffer address was not null + * @return DG drain pump calibration record *************************************************************************/ -BOOL getDisinfectionDate ( DISINFECTION_DATE_T* buffer ) +DG_DRAIN_PUMP_CAL_RECORD_T getDGDrainPumpRecord( void ) { - BOOL status = FALSE; + return dgCalibrationRecord.dgCalibrationGroups.drainPumpRecord; +} - if ( buffer != NULL ) - { - memcpy ( buffer, lastDisinfectionRecord.date.disinfectionDate, sizeof(DISINFECTION_DATE_T) ); - status = TRUE; - } +/*********************************************************************//** + * @brief + * The getDGDrainLineVolumeRecord function returns the DG drain volume + * record. + * @details Inputs: none + * @details Outputs: none + * @return DG drain volume record + *************************************************************************/ +DG_DRAIN_LINE_VOLUME_T getDGDrainLineVolumeRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.drainLineVolumeRecord; +} - return status; +/*********************************************************************//** + * @brief + * The getDGPreROPurgeVolumeRecord function returns the DG pre RO purge + * volume record. + * @details Inputs: none + * @details Outputs: none + * @return DG pre RO purge volume record + *************************************************************************/ +DG_PRE_RO_PURGE_VOLUME_T getDGPreROPurgeVolumeRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.preROPurgeVolumeRecord; } /*********************************************************************//** * @brief - * The execNVDataMgmtSelfTest runs the NVDataMgmt POST during the self-test. - * @details Inputs: NVDataMgmtSelfTestState - * @details Outputs: NVDataMgmtSelfTestState, alarm if there was a software fault - * @return NVDataMgmtSelfTestResult the result of self-test + * The getDGReservoirsVolumeRecord function returns the DG reservoirs + * volume record. + * @details Inputs: none + * @details Outputs: none + * @return DG reservoirs volume record *************************************************************************/ -SELF_TEST_STATUS_T execNVDataMgmtSelfTest ( void ) +DG_RESERVOIR_VOLUME_RECORD_T getDGReservoirVolumeRecord( void ) { - switch ( NVDataMgmtSelfTestState ) - { - case NVDATAMGMT_SELF_TEST_STATE_START: + return dgCalibrationRecord.dgCalibrationGroups.reservoirVolumesRecord; +} - NVDataMgmtSelfTestState = handleSelfTestStart(); - break; +/*********************************************************************//** + * @brief + * The getDGAcidConcentratesRecord function returns the DG acid concentrates + * record. + * @details Inputs: none + * @details Outputs: none + * @return DG acid concentrates record + *************************************************************************/ +DG_ACID_CONCENTRATES_RECORD_T getDGAcidConcentratesRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.acidConcentratesRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_ENABLE_EEPROM: +/*********************************************************************//** + * @brief + * The getDGBicarbConcentratesRecord function returns the DG bicarb concentrates + * record. + * @details Inputs: none + * @details Outputs: none + * @return DG bicarb concentrates record + *************************************************************************/ +DG_BICARB_CONCENTRATES_RECORD_T getDGBicarbConcentratesRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.bicarbConcentratesRecord; +} - NVDataMgmtSelfTestState = handleSelfTestEnableEEPROM(); - break; +/*********************************************************************//** + * @brief + * The getDGFiltersRecord function returns the DG filters record. + * @details Inputs: none + * @details Outputs: none + * @return DG filters record + *************************************************************************/ +DG_FILTERS_CAL_RECORD_T getDGFiltersRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.filtersRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_BOOTLOADER_FLAG: +/*********************************************************************//** + * @brief + * The getDGFansRecord function returns the DG fans record. + * @details Inputs: none + * @details Outputs: none + * @return DG fans record + *************************************************************************/ +DG_FANS_CAL_RECORD_T getDGFansRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.fansRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadBootloaderFlag(); - break; +/*********************************************************************//** + * @brief + * The getDGAccelerometerSensorCalibrationRecord function returns the DG + * accelerometer sensor calibration record. + * @details Inputs: none + * @details Outputs: none + * @return DG accelerometer sensor calibration record + *************************************************************************/ +DG_ACCELEROMETER_SENSOR_CAL_RECORD_T getDGAccelerometerSensorCalibrationRecord( void ) +{ + return dgCalibrationRecord.dgCalibrationGroups.accelerometerCalRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_LOG_RECORD: +/*********************************************************************//** + * @brief + * The getDGSystemRecord function returns the DG systems record. + * @details Inputs: none + * @details Outputs: none + * @return DG systems record + *************************************************************************/ +DG_SYSTEM_RECORD_T getDGSystemRecord( void ) +{ + return dgSystemGroup.dgSystemRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadLogRecord(); - break; +/*********************************************************************//** + * @brief + * The getDGServiceRecord function returns the DG service record. + * @details Inputs: none + * @details Outputs: none + * @return DG service record + *************************************************************************/ +DG_SERVICE_RECORD_T getDGServiceRecord( void ) +{ + return dgServiceGroup.dgServiceRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME: +/*********************************************************************//** + * @brief + * The getDGScheduledRunsRecord function returns the DG scheduled runs record. + * @details Inputs: none + * @details Outputs: none + * @return DG scheduled runs record + *************************************************************************/ +DG_SCHEDULED_RUN_RECORD_T getDGScheduledRunsRecord( void ) +{ + return dgScheduledRunsGroup.dgScheduledRun; +} +#endif - NVDataMgmtSelfTestState = handleSelfTestReadHDTreatmentTime(); - break; +#ifdef _HD_ +/*********************************************************************//** + * @brief + * The getHDPumpsCalibrationRecord function returns the HD pumps calibration + * record. + * @details Inputs: none + * @details Outputs: none + * @return HD pumps calibration record + *************************************************************************/ +HD_PUMPS_CAL_RECORD_T getHDPumpsCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION: +/*********************************************************************//** + * @brief + * The getHDValvesCalibrationRecord function returns the HD valves calibration + * record. + * @details Inputs: none + * @details Outputs: none + * @return HD valves calibration record + *************************************************************************/ +HD_VALVES_CAL_RECORD_T getHDValvesCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadDGWaterConsumption(); - break; +/*********************************************************************//** + * @brief + * The getHDOcclusionSensrosCalibrationRecord function returns the HD + * occlusion sensors calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD occlusion sensors calibration record + *************************************************************************/ +HD_OCCLUSION_SENSORS_CAL_RECORD_T getHDOcclusionSensrosCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_MFG_RECORD: +/*********************************************************************//** + * @brief + * The getHDFlowSensorsCalibrationRecord function returns the HD flow + * sensors calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD flow sensors calibration record + *************************************************************************/ +HD_FLOW_SENSORS_CAL_RECORD_T getHDFlowSensorsCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.flowSensorsCalRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadMfgRecord(); - break; +/*********************************************************************//** + * @brief + * The getHDPressureSensorsCalibrationRecord function returns the HD pressure + * sensors calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD pressure sensors calibration record + *************************************************************************/ +HD_PRESSURE_SENSORS_CAL_RECORD_T getHDPressureSensorsCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD: +/*********************************************************************//** + * @brief + * The getHDTemperatureSensorsCalibrationRecord function returns the HD + * temperature sensors calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD temperature sensors calibration record + *************************************************************************/ +HD_TEMP_SENSORS_CAL_RECORD_T getHDTemperatureSensorsCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.tempSensorsCalRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadCalibrationRecord(); - break; +/*********************************************************************//** + * @brief + * The getHDHeparinForceSensorCalibrationRecord function returns the HD + * heparin force sensor calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD heparin force sensor calibration record + *************************************************************************/ +HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T getHDHeparinForceSensorCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.heparinForceSensorCalRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD: +/*********************************************************************//** + * @brief + * The getHDAccelerometerSensorCalibrationRecord function returns the HD + * accelerometer sensor calibration record. + * @details Inputs: none + * @details Outputs: none + * @return HD heparin force sensor calibration record + *************************************************************************/ +HD_ACCELEROMETER_SENSOR_CAL_RECORD_T getHDAccelerometerSensorCalibrationRecord( void ) +{ + return hdCalibrationRecord.hdCalibrationGroups.accelerometerCalRecord; +} - NVDataMgmtSelfTestState = handleSelfTestReadServiceRecord(); - break; +/*********************************************************************//** + * @brief + * The getHDSystemRecord function returns the HD system record. + * @details Inputs: none + * @details Outputs: none + * @return HD system record + *************************************************************************/ +HD_SYSTEM_RECORD_T getHDSystemRecord( void ) +{ + return hdSystemGroup.hdsystemRecord; +} - case NVDATAMGMT_SELF_TEST_STATE_READ_LAST_DISINFECTION_DATE: +/*********************************************************************//** + * @brief + * The getHDServiceRecord function returns the HD service record. + * @details Inputs: none + * @details Outputs: none + * @return HD service record + *************************************************************************/ +HD_SERVICE_RECORD_T getHDServiceRecord( void ) +{ + return hdServiceGroup.hdServiceRecord; +} +#endif - NVDataMgmtSelfTestState = handleSelfTestReadLastDisinfectionDate(); - break; +/*********************************************************************//** + * @brief + * The writeLogData checks if the queue is not full and if it is not, it calls + * enqueue to schedule a job for writing the log data. + * @details Inputs: logRecord + * @details Outputs: none + * @param data address of log data buffer + * @return TRUE if the queue is not full and if the log header is not corrupted + *************************************************************************/ +BOOL writeLogData ( LOG_DATA_T* data ) +{ + BOOL status = FALSE; - case NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC: + // If the header is corrupted, no more data is allowed to be written + if ( !isQueueFull() && logRecord.logHeader.isHdrCorrupted == FALSE ) + { + enqueue ( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, 0, (U08*)&data, 0, sizeof(LOG_DATA_T) ); + status = TRUE; + } - NVDataMgmtSelfTestState = handleSelfTestCheckCRC(); - break; + return status; +} - case NVDATAMGMT_SELF_TEST_STATE_COMPLETE: +/*********************************************************************//** + * @brief + * The readLogData checks if the queue is not full and if it is not, it calls + * enqueue to schedule a job for writing the log data. + * @details Inputs: none + * @details Outputs: none + * @param buffer address of read data buffer + * @param length length of the data log + * @return TRUE if there are enough queues available for the job + *************************************************************************/ +BOOL readLogData ( READ_DATA_T* buffer, U32 length ) +{ + BOOL status = FALSE; + U32 availableQueue = getAvailableQueueCount(); - // Done with POST. Do nothing - break; + if ( availableQueue >= MIN_JOBS_NEEDED_FOR_DATA_LOG ) + { + enqueue( NVDATAMGMT_READ, NVDATAMGMT_EEPROM, 0, 0, buffer, length ); + status = TRUE; + } - default: -#ifdef _DG_ - SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, - NVDataMgmtSelfTestState ); -#else - SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, - NVDataMgmtSelfTestState ); -#endif - NVDataMgmtSelfTestState = NVDATAMGMT_SELF_TEST_STATE_COMPLETE; - NVDataMgmtSelfTestResult = SELF_TEST_STATUS_FAILED; - break; + return status; +} +#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 + * @return TRUE if the queue was not full so the job was scheduled successfully + *************************************************************************/ +BOOL setTreatmentTime ( U32 hours ) +{ + BOOL status = FALSE; + hdUsageInfoGroup.hdUsageInfo.treatmentTime = hours; + hdUsageInfoGroup.crc = crc16 ( (U08*)&hdUsageInfoGroup.hdUsageInfo.treatmentTime, sizeof(U32) ); + + if ( !isQueueFull() ) + { + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, HD_TREATMENT_TIME_ADDRESS, + (U08*)&hdUsageInfoGroup, 0, sizeof(HD_USAGE_INFO_RECORD_T) ); + status = TRUE; } - return NVDataMgmtSelfTestResult; + return status; } /*********************************************************************//** * @brief - * The setBootloaderFlag sets the bootloader flag to RTC RAM. + * The getTreatmentTime returns the total number treatment hours of the + * HD device. * @details Inputs: none - * @details Outputs: none - * @param flag the bootloader flag - * @return TRUE if the queue was not full + * Output: none + * @return treatment time as U32 *************************************************************************/ -BOOL setBootloaderFlag ( U32 flag ) +U32 getTreatmentTime ( void ) { + return hdUsageInfoGroup.hdUsageInfo.treatmentTime; +} +#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 + * @param liters consumed water is liters + * @return TRUE if queue is not full + *************************************************************************/ +BOOL setWaterConsumption ( U32 liters ) +{ BOOL status = FALSE; + dgUsageInfoGroup.dgUsageInfo.waterConsumption = liters; + dgUsageInfoGroup.crc = crc16 ( (U08*)&dgUsageInfoGroup.dgUsageInfo.waterConsumption, sizeof(U32) ); if ( !isQueueFull() ) { - enqueue ( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, BOOTLOADER_FLAG_ADDRESS, - (U08*)&flag, 0, BOOTLOADER_FLAG_LENGTH_BYTES ); + enqueue( NVDATAMGMT_WRITE, NVDATAMGMT_RTC, DG_CONSUMED_WATER_ADDRESS, + (U08*)&dgUsageInfoGroup, 0, sizeof(DG_USAGE_INFO_RECORD_T) ); status = TRUE; } @@ -754,118 +1672,94 @@ /*********************************************************************//** * @brief - * The getBootloaderFlag gets the bootloader flag from RTC RAM. + * The getWaterConsumption returns the amount of consumed water. * @details Inputs: none * @details Outputs: none - * @return bootloader flag as a U32 + * @return water consumption as a U32 *************************************************************************/ -U32 getBootloaderFlag( void ) +U32 getWaterConsumption ( void ) { - return bootloaderFlag; + return dgUsageInfoGroup.dgUsageInfo.waterConsumption; } - +#endif /*********************************************************************//** * @brief - * The execNVDataMgmt runs the NVDataMgmt main tasks. - * @details Inputs: NVDataMgmtExecState - * @details Outputs: NVDataMgmtExecState, alarm if exec state was invalid - * @return none + * The handleSelfTestStart enables the EEPROM bank sectors. + * @details Inputs: currentTime + * @details Outputs: currentTime + * @return next state *************************************************************************/ -void execNVDataMgmt( void ) -{ // TODO - not sure where it should go Dara, but need to look at powerOffIsImminent flag and block - // queuing of any new jobs, maybe even block starting of any new jobs if flag is set - switch ( NVDataMgmtExecState ) +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestStart ( void ) +{ + NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_START; + + if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady ) { - case NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST: + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_CALIBRATION_RECORD ]; + U32 startAddress = specs.startAddress; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = ( specs.maxReadBufferSize / EEPROM_OPS_SIZE_OF_CONVERTER ); - NVDataMgmtExecState = handleExecWaitForPostState(); - break; - - case NVDATAMGMT_EXEC_STATE_IDLE: - - NVDataMgmtExecState = handleExecIdleState(); - break; - - case NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM: - - NVDataMgmtExecState = handleExecWriteToEEPROMState(); - break; - - case NVDATAMGMT_EXEC_STATE_READ_FROM_EEPROM: - - NVDataMgmtExecState = handleExecReadFromEEPROMState(); - break; - - case NVDATAMGMT_EXEC_STATE_ERASE_EEPROM: - - NVDataMgmtExecState = handleExecEraseState(); - break; - - case NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC: - - NVDataMgmtExecState = handleExecWriteToRAMState(); - break; - - case NVDATAMGMT_EXEC_STATE_READ_FROM_RTC: - - NVDataMgmtExecState = handleExecReadFromRAMState(); - break; - - default: - -#ifdef _DG_ - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, - NVDataMgmtExecState ); -#else - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, - NVDataMgmtExecState ); -#endif - NVDataMgmtExecState = NVDATAMGMT_EXEC_STATE_IDLE; - break; + Fapi_doMarginRead ( (U32*)startAddress, (U32*)bufferAddress, maxBufferLength, Fapi_NormalRead ); + currentTime = getMSTimerCount(); + state = NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD; } + + return state; } /*********************************************************************//** * @brief - * The handleSelfTestStart enables the EEPROM bank sectors. + * The handleSelfTestReadCalibrationRecord reads the calibration record + * from EEPROM. * @details Inputs: currentTime * @details Outputs: currentTime * @return next state *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestStart ( void ) +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadCalibrationRecord ( void ) { - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_ENABLE_EEPROM; + NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD; + BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); - Fapi_enableEepromBankSectors( BANK7_SECTOR_0_31_ENABLE_BIT_MASK, - BANK7_SECTOR_32_63_ENABLE_BIT_MASK ); - // Get the time to check for timeout - currentTime = getMSTimerCount(); + if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) + { + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_SYSTEM_RECORD ]; + U32 startAddress = specs.startAddress; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = ( specs.maxReadBufferSize / EEPROM_OPS_SIZE_OF_CONVERTER ); + Fapi_doMarginRead ( (U32*)startAddress, (U32*)bufferAddress, maxBufferLength, Fapi_NormalRead ); + currentTime = getMSTimerCount(); + state = NVDATAMGMT_SELF_TEST_STATE_READ_SYS_RECORD; + } + return state; } /*********************************************************************//** * @brief - * The handleSelfTestEnableEEPROM waits for EEPROM to return with ready from - * enabling the EEPROM command. - * @details Inputs: currentTime + * The handleSelfTestReadSystemRecord reads the system record from EEPROM. + * @details Inputs: currentTime, calibrationRecord * @details Outputs: currentTime * @return next state *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestEnableEEPROM ( void ) +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadSystemRecord ( void ) { - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_ENABLE_EEPROM; + NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_SYS_RECORD; BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) { - // Enable was successful, Request a read for bootloader if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { - readFromRAM( BOOTLOADER_FLAG_ADDRESS, BOOTLOADER_FLAG_LENGTH_BYTES ); - // Get the time to check for timeout + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_SERVICE_RECORD ]; + U32 startAddress = specs.startAddress; + U32 maxBufferLength = specs.maxReadBufferSize; + currentTime = getMSTimerCount(); - state = NVDATAMGMT_SELF_TEST_STATE_READ_BOOTLOADER_FLAG; + readFromRAM( startAddress, maxBufferLength ); + + state = NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD; } } @@ -874,45 +1768,75 @@ /*********************************************************************//** * @brief - * The handleSelfTestReadBootloaderFlag reads the bootloader flag - * from RTC RAM. - * @details Inputs: currentTime, bootloaderFlag + * The handleSelfTestReadServiceRecord reads the service record from RTC + * RAM. + * @details Inputs: currentTime * @details Outputs: currentTime * @return next state *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadBootloaderFlag ( void ) +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadServiceRecord ( void ) { - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_BOOTLOADER_FLAG; + NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD; BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_RTC_RAM_OPS_ERROR, (U08*)&state ); - // If the read for bootloader is done, read it if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - getDataFromRAM( (U08*)&bootloaderFlag, BOOTLOADER_FLAG_LENGTH_BYTES ); -// If the device is HD, read treatment time, -// If the device is DG, read water consumption -#ifdef _HD_ + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_SERVICE_RECORD ]; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = specs.maxReadBufferSize; + + getDataFromRAM( bufferAddress, maxBufferLength ); + +#ifdef _DG_ if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { - readFromRAM ( HD_TREATMENT_TIME_ADDRESS, sizeof(TREATMENT_TIME_RECORD_T) ); + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_SCHEDULED_RUNS_RECORD ]; + U32 startAddress = specs.startAddress; + U32 maxBufferLength = specs.maxReadBufferSize; + currentTime = getMSTimerCount(); - state = NVDATAMGMT_SELF_TEST_STATE_READ_TREATMENT_TIME; + readFromRAM( startAddress, maxBufferLength ); + + state = NVDATAMGMT_SELF_TEST_STATE_READ_SCHEDULED_RUNS_RECORD; } -#else - if ( getRTCRAMState() == RTC_RAM_STATE_READY ) - { - readFromRAM ( DG_CONSUMED_WATER_ADDRESS, sizeof(WATER_CONSUMPTION_RECORD_T) ); - currentTime = getMSTimerCount(); - state = NVDATAMGMT_SELF_TEST_STATE_READ_WATER_CONSUMPTION; - } #endif +#ifdef _HD_ + state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; +#endif } return state; } /*********************************************************************//** * @brief + * The handleSelfTestReadScheduledRunsRecord reads the scheduled runs + * from RTC RAM (only DG for now). + * @details Inputs: currentTime, serviceRecord + * @details Outputs: currentTime + * @return next state + *************************************************************************/ +static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadScheduledRunsRecord( void ) +{ + NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_SCHEDULED_RUNS_RECORD; + BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_RTC_RAM_OPS_ERROR, (U08*)&state ); + + if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) + { + PROCESS_RECORD_SPECS_T specs = RECORDS_SPECS [ NVDATAMGMT_SCHEDULED_RUNS_RECORD ]; + U08* bufferAddress = specs.structAddressPtr; + U32 maxBufferLength = specs.maxReadBufferSize; + + getDataFromRAM( bufferAddress, maxBufferLength ); + + state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; + } + + return state; +} +#ifdef _HD_ +/*********************************************************************//** + * @brief * The handleSelfTestReadHDTreatmentTime reads the HD treatment time * from RTC RAM. * @details Inputs: currentTime, treatmentTimeRecord @@ -927,7 +1851,7 @@ // If the RTC RAM is ready, read the results if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - getDataFromRAM ( (U08*)&treatmentTimeRecord, sizeof(TREATMENT_TIME_RECORD_T) ); + 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 ) { @@ -939,7 +1863,8 @@ return state; } - +#endif +#ifdef _DG_ /*********************************************************************//** * @brief * The handleSelfTestReadDGWaterConsumption reads the DG water consumption @@ -956,7 +1881,7 @@ // If the RAM is ready, request a read for water consumption if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - getDataFromRAM ( (U08*)&waterConsumptionRecord, sizeof(WATER_CONSUMPTION_RECORD_T) ); + getDataFromRAM ( (U08*)&dgUsageInfoGroup, sizeof(DG_USAGE_INFO_RECORD_T) ); if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { readFromRAM ( LOG_RECORD_START_ADDRESS, sizeof(LOG_RECORD_T) ); @@ -967,7 +1892,7 @@ return state; } - +#endif /*********************************************************************//** * @brief * The handleSelfTestReadLogRecord reads the log record from RTC RAM. @@ -983,222 +1908,64 @@ // If the RAM is in Idle, read the log records if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - U32 len = sizeof(MFG_RECORD_T) / sizeof(U32); - U32 *addr = (U32*)&mfgRecord; + // TODO enable the logs once we get back to logging the data in the future phases + //U32 len = sizeof(MFG_RECORD_T) / sizeof(U32); + //U32 *addr = (U32*)&mfgRecord; getDataFromRAM ( (U08*)&logRecord, sizeof(LOG_RECORD_T) ); currentTime = getMSTimerCount(); // Get ready for reading the manufacturing record - Fapi_doMarginRead( (U32*)BANK7_SECTOR0_START_ADDRESS, addr, len, Fapi_NormalRead ); - state = NVDATAMGMT_SELF_TEST_STATE_READ_MFG_RECORD; + //Fapi_doMarginRead( (U32*)BANK7_SECTOR0_START_ADDRESS, addr, len, Fapi_NormalRead ); + state = NVDATAMGMT_SELF_TEST_STATE_READ_SYS_RECORD; } return state; } /*********************************************************************//** * @brief - * The handleSelfTestReadMfgRecords reads the manufacturing record from - * EEPROM. - * @details Inputs: currentTime, calibrationRecord - * @details Outputs: currentTime - * @return next state - *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadMfgRecord ( void ) -{ - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_MFG_RECORD; - BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); - - // Wait for the read from EEPROM to be successful - if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) - { - currentTime = getMSTimerCount(); - // Send the read command for calibration record - Fapi_doMarginRead ( (U32*)CALIBRATION_RECORD_START_ADDRESS, (U32*)&calibrationRecord, - sizeof(CALIBRATION_RECORD_T) / sizeof(U32), Fapi_NormalRead ); - state = NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleSelfTestReadCalibrationRecord reads the calibration record - * from EEPROM. - * @details Inputs: currentTime - * @details Outputs: currentTime - * @return next state - *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadCalibrationRecord ( void ) -{ - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_CAL_RECORD; - BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); - - // If the EEPROM read was successful, request a read from RAM to - // read the service record - if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) - { - if ( getRTCRAMState() == RTC_RAM_STATE_READY ) - { - currentTime = getMSTimerCount(); - readFromRAM( SERVICE_DATE_START_ADDRESS, sizeof(SERVICE_RECORD_T) ); - state = NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD; - } - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleSelfTestReadServiceRecord reads the service dates from RTC - * RAM. - * @details Inputs: currentTime, serviceRecord - * @details Outputs: currentTime - * @return next state - *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadServiceRecord ( void ) -{ - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_SERVICE_RECORD; - BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_RTC_RAM_OPS_ERROR, (U08*)&state ); - - if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) - { - getDataFromRAM ( (U08*)&serviceRecord, sizeof(SERVICE_RECORD_T) ); - if ( getRTCRAMState() == RTC_RAM_STATE_READY ) - { - currentTime = getMSTimerCount(); - readFromRAM( LAST_DISINFECTION_DATE_ADDRESS, sizeof(LAST_DISINFECTION_RECORD_T) ); - state = NVDATAMGMT_SELF_TEST_STATE_READ_LAST_DISINFECTION_DATE; - } - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleSelfTestReadLastDisinfectionDate reads the last disinfection date - * from RTC RAM. - * @details Inputs: lastDisinfectionRecord - * @details Outputs: none - * @return next state - *************************************************************************/ -static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestReadLastDisinfectionDate ( void ) -{ - NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_READ_LAST_DISINFECTION_DATE; - BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_RTC_RAM_OPS_ERROR, (U08*)&state ); - - if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) - { - getDataFromRAM ( (U08*)&lastDisinfectionRecord, sizeof(LAST_DISINFECTION_RECORD_T) ); - state = NVDATAMGMT_SELF_TEST_STATE_CHECK_CRC; - } - - return state; - -} - -/*********************************************************************//** - * @brief * The handleSelfTestCheckCRC calculates the CRC of the records and compares * them to the CRC that was read. If they don't match, it will fail POST. - * @details Inputs: treatmentTimeRecord, waterConsumptionRecord, lastDisinfectionRecord, - * logRecord, mfgRecord, calibrationRecord, calibrationRecord, serviceRecord, - * NVDataMgmtSelfTestResult - * @details Outputs: NVDataMgmtSelfTestResult, alarm if any of the CRC checks failed + * @details Inputs: nvDataMgmtSelfTestResult + * @details Outputs: none * @return next state *************************************************************************/ static NVDATAMGMT_SELF_TEST_STATE_T handleSelfTestCheckCRC ( void ) { NVDATAMGMT_SELF_TEST_STATE_T state = NVDATAMGMT_SELF_TEST_STATE_COMPLETE; - BOOL hasCRCPassed = TRUE; - U16 calcCRC; - U16 recordCRC; -#ifdef _HD_ - calcCRC = crc16 ( (U08*)&treatmentTimeRecord.treatmentTime, sizeof(U32) ); - recordCRC = treatmentTimeRecord.crc; -#ifndef LIMITED_NVDATA_CRC_CHECKS - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_NVDATA_HW_USAGE_DATA_CRC_ERROR, recordCRC, calcCRC ); - } + BOOL haveCalGroupsPassed = TRUE; + BOOL haveRecordsPassed = TRUE; + +#ifndef DISABLE_CAL_CHECK + // Check the integrity of the records as a whole. Check the upper layer CRC + haveRecordsPassed = areRecordsValid(); #endif -#else - calcCRC = crc16 ( (U08*)&waterConsumptionRecord.waterConsumption, sizeof(U32) ); - recordCRC = waterConsumptionRecord.crc; - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_NVDATA_HW_USAGE_DATA_CRC_ERROR, recordCRC, calcCRC ); - } - // Check the CRC for last disinfection date - calcCRC = crc16 ( (U08*)&lastDisinfectionRecord.date.disinfectionDate, sizeof(DISINFECTION_DATE_T) ); - recordCRC = lastDisinfectionRecord.crc; - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( AlARM_ID_NVDATA_DISINFECTION_DATE_CRC_ERROR, recordCRC, calcCRC ); - } + +#ifdef _DG_ + // Check all the calibration groups + haveCalGroupsPassed = isDGCalibrationRecordValid(); #endif -#ifndef LIMITED_NVDATA_CRC_CHECKS - // Check log header record - calcCRC = crc16 ( (U08*)&logRecord.logHeader, sizeof(LOG_HEADER_T) ); - recordCRC = logRecord.crc; - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - // CRC for the log record has failed. The flag will be set to true - // The log header will be set to full by having the record count be at - // maximum number of counts (1536 in this case) and the read index be a 0 - // of the beginning of the log sectors - logRecord.logHeader.recordCount = MAX_NUM_OF_EVENTS_IN_SECTOR3; - logRecord.logHeader.nextReadIndex = 0; - logRecord.logHeader.nextReadIndex = 0; - logRecord.logHeader.isHdrCorrupted = TRUE; - } - // Check CRC for manufacturing record - calcCRC = crc16 ( (U08*)&mfgRecord.mfgData, sizeof(MFG_DATA_T) ); - recordCRC = mfgRecord.crc; - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_NVDATA_MFG_RECORD_CRC_ERROR, recordCRC, calcCRC ); - } +#ifdef _HD_ + haveCalGroupsPassed = isHDCalibrationRecordValid(); #endif - // Check CRC for calibration record - calcCRC = crc16( (U08*)&calibrationRecord.calData, sizeof(CALIBRATION_DATA_T) ); - recordCRC = calibrationRecord.crc; - if ( calcCRC != recordCRC ) + + // If any of the records did not pass, they should be filled + // with benign values. After that, schedule a write to sector 0 + // to re-write the records with the benign values + if ( FALSE == haveCalGroupsPassed ) { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_NVDATA_CAL_RECORD_CRC_ERROR, recordCRC, calcCRC ); + enqueueSector0Records(); } - else + + // Check if the records' entire CRCs as well as the individual CRCs passed + if ( haveCalGroupsPassed && haveRecordsPassed ) { - calRecordIsValid = TRUE; + nvDataMgmtSelfTestResult = SELF_TEST_STATUS_PASSED; } -#ifndef LIMITED_NVDATA_CRC_CHECKS - // Check CRC for service record - calcCRC = crc16 ( (U08*)&serviceRecord.serviceData, sizeof(SERVICE_DATA_T) ); - recordCRC = serviceRecord.crc; - if ( calcCRC != recordCRC ) - { - hasCRCPassed = FALSE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_NVDATA_SRVC_RECORD_CRC_ERROR, recordCRC, calcCRC ); - } -#endif - // There should be no failed CRCs and no command should timeout for the self-test to pass - if ( hasCRCPassed && !hasCommandTimedout ) - { - NVDataMgmtSelfTestResult = SELF_TEST_STATUS_PASSED; - } else { - NVDataMgmtSelfTestResult = SELF_TEST_STATUS_FAILED; + nvDataMgmtSelfTestResult = SELF_TEST_STATUS_FAILED; } return state; @@ -1207,15 +1974,15 @@ /*********************************************************************//** * @brief * The handleExecWaitForPostState waits for POST to be completed. - * @details Inputs: NVDataMgmtSelfTestState + * @details Inputs: nvDataMgmtSelfTestState * @details Outputs: none * @return next state *************************************************************************/ static NVDATAMGMT_EXEC_STATE_T handleExecWaitForPostState ( void ) { NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_WAIT_FOR_POST; - if ( NVDataMgmtSelfTestState == NVDATAMGMT_SELF_TEST_STATE_COMPLETE ) + if ( nvDataMgmtSelfTestState == NVDATAMGMT_SELF_TEST_STATE_COMPLETE ) { state = NVDATAMGMT_EXEC_STATE_IDLE; } @@ -1227,60 +1994,87 @@ * @brief * The handleExecIdleState checks if the queue is empty and if it is not * empty, it sets the state of the job. - * @details Inputs: currentJob, currentTime - * @details Outputs: currentJob + * @details Inputs: powerOffIsImminent + * @details Outputs: none * @return next state *************************************************************************/ static NVDATAMGMT_EXEC_STATE_T handleExecIdleState ( void ) { NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_IDLE; - if ( !isQueueEmpty() ) + NVDATAMGMT_OPERATION_STATE_T ops; + NVDATAMGMT_LOCATION_STATE_T location; + U32 startAddress; + U08* bufferAddress; + U32 maxBufferLength; + BOOL areQueuesNotEmpty = FALSE; + + // If power off command has been issued, do not process any new jobs + if ( powerOffIsImminent != TRUE ) { - dequeue(); - NVDATAMGMT_OPERATION_STATE_T ops = currentJob.memoryOperation; - NVDATAMGMT_LOCATION_STATE_T location = currentJob.memoryLocation; - U32 startAddress = currentJob.startAddress; - U32 length = currentJob.length; + // If the record processing queue is not empty, process the queues + if ( !isRecordQueueEmpty() ) + { + dequeueRecordJob(); - if ( ops == NVDATAMGMT_WRITE && location == NVDATAMGMT_EEPROM ) + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; + // Set the record address offset to 0 since a job will just be started + recordAddressOffset = 0; + areQueuesNotEmpty = TRUE; + ops = recordCurrentJob.memoryOperation; + location = recordCurrentJob.memoryLocation; + currentTime = getMSTimerCount(); + startAddress = jobSpecs.startAddress + recordAddressOffset; + bufferAddress = jobSpecs.structAddressPtr + recordAddressOffset; + activeQueue = NVDATAMGMT_PROCESS_RECORDS; + + // Choose the right buffer size + if ( ops == NVDATAMGMT_WRITE ) + { + maxBufferLength = jobSpecs.maxWriteBufferSize; + } + else if ( ops == NVDATAMGMT_READ ) + { + maxBufferLength = jobSpecs.maxReadBufferSize; + } + } + // TODO add the log queue later in the future phases. + } + + // Check if a queue job is available + if ( areQueuesNotEmpty ) + { + if ( ops == NVDATAMGMT_ERASE_SECTOR ) { - currentTime = getMSTimerCount(); - Fapi_issueProgrammingCommand ( (U32*)startAddress, currentJob.buffer, length, - 0x00, 0, Fapi_DataOnly ); + Fapi_issueAsyncCommandWithAddress ( Fapi_EraseSector, (U32*)startAddress ); + state = NVDATAMGMT_EXEC_STATE_ERASE_EEPROM; + } + else if ( ops == NVDATAMGMT_WRITE && location == NVDATAMGMT_EEPROM ) + { + Fapi_issueProgrammingCommand ( (U32*)startAddress, (U08*)bufferAddress, maxBufferLength, 0x00, 0, Fapi_DataOnly ); state = NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM; } else if ( ops == NVDATAMGMT_READ && location == NVDATAMGMT_EEPROM ) { - currentTime = getMSTimerCount(); - Fapi_doMarginRead ( (U32*)startAddress, (U32*)( currentJob.externalAddress->externalBuffer ), - length, Fapi_NormalRead ); - // Change the status to in progress until the read operation is done - currentJob.externalAddress->status = NVDATAMGMT_READ_IN_PROGRESS; + Fapi_doMarginRead ( (U32*)startAddress, (U32*)bufferAddress, maxBufferLength, Fapi_NormalRead ); state = NVDATAMGMT_EXEC_STATE_READ_FROM_EEPROM; } - else if ( ops == NVDATAMGMT_ERASE_SECTOR ) - { - currentTime = getMSTimerCount(); - Fapi_issueAsyncCommandWithAddress ( Fapi_EraseSector, (U32*)startAddress ); - state = NVDATAMGMT_EXEC_STATE_ERASE_EEPROM; - } else if ( ops == NVDATAMGMT_WRITE && location == NVDATAMGMT_RTC ) { if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { currentTime = getMSTimerCount(); - writeToRAM ( startAddress, currentJob.buffer, length ); + writeToRAM ( startAddress, bufferAddress, maxBufferLength ); state = NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC; } - } else if ( ops == NVDATAMGMT_READ && location == NVDATAMGMT_RTC ) { if ( getRTCRAMState() == RTC_RAM_STATE_READY ) { currentTime = getMSTimerCount(); - readFromRAM( startAddress, length ); + readFromRAM( startAddress, maxBufferLength ); currentJob.externalAddress->status = NVDATAMGMT_READ_IN_PROGRESS; state = NVDATAMGMT_EXEC_STATE_READ_FROM_RTC; } @@ -1292,31 +2086,130 @@ /*********************************************************************//** * @brief - * The handleExecWriteToEEPROMState issues a write command to EEPROM on entry - * and if the write was successful, it sets the state to Idle. - * @details Inputs: none - * @details Outputs: none - * @return next state + * The handleExecWriteToEEPROMState issues a write command to EEPROM and + * if the write was successful, it sets the state to Idle. + * @details Inputs: recordAddressOffset, writtenRecordCheckBuffer, + * writtenRecordStatus + * @details Outputs: recordAddressOffset, writtenRecordCheckBuffer, + * writtenRecordStatus + * @return next state of the state machine *************************************************************************/ static NVDATAMGMT_EXEC_STATE_T handleExecWriteToEEPROMState ( void ) { - NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM; - BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); + NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM; + BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; - if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) + // Check if the fapi has finished + if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady ) { + // Check the integrity of data (the 16 bytes that were written to EEPROM should be read and be checked for each byte) + if ( writtenRecordStatus == NVDATAMGMT_RECORD_NOT_CHECKED ) + { + currentTime = getMSTimerCount(); + U32 startAddress = jobSpecs.startAddress + recordAddressOffset; + + // Clear the buffer from the previous content + memset( writtenRecordCheckBuffer, 0, sizeof(writtenRecordCheckBuffer)); + + // Issue a FAPI read command but only the bytes that were written, so use maxWriteBufferSize + Fapi_doMarginRead ( (U32*)startAddress, (U32*)writtenRecordCheckBuffer, jobSpecs.maxWriteBufferSize, Fapi_NormalRead ); + + state = NVDATAMGMT_EXEC_STATE_VERIFY_EEPROM_WRITE; + } + else if ( writtenRecordStatus == NVDATAMGMT_RECORD_VALID ) + { + // If the data is valid, and if it is at the end of the write, change to idle + if ( jobSpecs.sizeofJob == recordAddressOffset ) + { + state = NVDATAMGMT_EXEC_STATE_IDLE; + } + else + { + // Update the variables and issue the next write command + currentTime = getMSTimerCount(); + recordAddressOffset += jobSpecs.maxWriteBufferSize; + U32 memoryPtr = jobSpecs.startAddress + recordAddressOffset; + U08* structPtr = jobSpecs.structAddressPtr + recordAddressOffset; + + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_CHECKED; + + // Issue the write command + Fapi_issueProgrammingCommand ( (U32*)memoryPtr, structPtr, jobSpecs.maxWriteBufferSize, 0x00, 0, Fapi_DataOnly ); + } + } + } + // If timed out, get back to Idle + else if ( timeoutStatus == TRUE ) + { + // TODO schedule another write? + recordAddressOffset = 0; state = NVDATAMGMT_EXEC_STATE_IDLE; } return state; } /*********************************************************************//** - * @brief handleExecReadFromEEPROMState + * @brief + * The handleExecVerifyEEPROMWriteState checks all the bytes that were + * written to EEPROM to ensure they match the data in the NV memory. + * @details Inputs: recordAddressOffset, writtenRecordCheckBuffer, + * writtenRecordStatus + * @details Outputs: recordAddressOffset, writtenRecordCheckBuffer, + * writtenRecordStatus + * @return next state of the state machine + *************************************************************************/ +static NVDATAMGMT_EXEC_STATE_T handleExecVerifyEEPROMWriteState ( void ) +{ + NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_VERIFY_EEPROM_WRITE; + BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; + + // Check if the write job is EEPROM or RTC RAM + 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 + for ( i = 0; i < jobSpecs.maxWriteBufferSize; i++ ) + { + // Check if data in the buffer is not the same as the data in the structure + if ( writtenRecordCheckBuffer[ i ] != *bufferPtr ) + { + // Data is not valid. Schedule an erase and write of the calibration record since only a part of + // data cannot be written to EEPROM. + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_VALID; + enqueueRecordJob( NVDATAMGMT_ERASE_SECTOR, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + state = NVDATAMGMT_EXEC_STATE_IDLE; + // Exit the loop since there is no point to check the rest of data + break; + } + else + { + // Everything is good increment the pointer to check the next byte. + bufferPtr++; + // Record data is valid so far + writtenRecordStatus = NVDATAMGMT_RECORD_VALID; + // Go back write to EEPROM state to continue writing the record data + state = NVDATAMGMT_EXEC_STATE_WRITE_TO_EEPROM; + } + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleExecReadFromEEPROMState issues a read command to EEPROM on entry * and if the read was successful, it sets the state to Idle. - * @details Inputs: currentJob - * @details Outputs: currentJob + * @details Inputs: currentJob, activeQueue + * @details Outputs: currentJob, activeQueue * @return next state *************************************************************************/ static NVDATAMGMT_EXEC_STATE_T handleExecReadFromEEPROMState ( void ) @@ -1326,7 +2219,14 @@ if ( FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady || timeoutStatus == TRUE ) { - currentJob.externalAddress->status = NVDATAMGMT_READ_COMPLETE; + // Signal the external client that the read is complete. + // This is only needed for reading the data logs and not the records + if ( activeQueue == NVDATAMGMT_PROCESS_LOGS ) + { + currentJob.externalAddress->status = NVDATAMGMT_READ_COMPLETE; + activeQueue = NVDATAMGMT_QUEUE_NONE; + } + state = NVDATAMGMT_EXEC_STATE_IDLE; } @@ -1359,18 +2259,121 @@ * The handleExecWriteToRAMState issues a write command to RTC RAM if the * RAM was ready, and if the RAM got back to Idle after the write command, * it sets the state to Idle. - * @details Inputs: none - * @details Outputs: none + * @details Inputs: currentTime, writtenRecordStatus, recordAddressOffset + * @details Outputs: currentTime, writtenRecordStatus, recordAddressOffset * @return next state *************************************************************************/ static NVDATAMGMT_EXEC_STATE_T handleExecWriteToRAMState ( void ) { NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC; BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_RTC_RAM_OPS_ERROR, (U08*)&state ); + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; + // Check if the RTC RAM has finished + if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE ) + { + // Check the integrity of data that was written + if ( writtenRecordStatus == NVDATAMGMT_RECORD_NOT_CHECKED ) + { + currentTime = getMSTimerCount(); + U32 startAddress = jobSpecs.startAddress + recordAddressOffset; + + readFromRAM( startAddress, jobSpecs.maxWriteBufferSize ); + + state = NVDATAMGMT_EXEC_STATE_VERIFY_RTC_WRITE; + } + // The written record was not valid. rewrite it again. + else if ( writtenRecordStatus == NVDATAMGMT_RECORD_NOT_VALID ) + { + U32 memoryPtr = jobSpecs.startAddress + recordAddressOffset; + U08* structPtr = jobSpecs.structAddressPtr + recordAddressOffset; + // Set the check status to not checked to check the data again + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_CHECKED; + // Issue the write command + writeToRAM ( memoryPtr, structPtr, jobSpecs.maxWriteBufferSize ); + } + else if ( writtenRecordStatus == NVDATAMGMT_RECORD_VALID ) + { + // If the data is valid, and if it is at the end of the write, or the size of job is equal to + // max write buffer, go to idle + if ( jobSpecs.sizeofJob == recordAddressOffset || jobSpecs.sizeofJob == jobSpecs.maxWriteBufferSize ) + { + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_CHECKED; + state = NVDATAMGMT_EXEC_STATE_IDLE; + } + else + { + // Update the variables and issue the next write command + currentTime = getMSTimerCount(); + recordAddressOffset += jobSpecs.maxWriteBufferSize; + U32 memoryPtr = jobSpecs.startAddress + recordAddressOffset; + U08* structPtr = jobSpecs.structAddressPtr + recordAddressOffset; + + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_CHECKED; + // Issue the write command + writeToRAM ( memoryPtr, structPtr, jobSpecs.maxWriteBufferSize ); + } + } + } + // If timed out, get back to Idle + else if ( timeoutStatus == TRUE ) + { + // TODO schedule another write? + recordAddressOffset = 0; + state = NVDATAMGMT_EXEC_STATE_IDLE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleExecVerifyRTCWriteState checks all the bytes that were + * written to RTC RAM to ensure they match the data in the NV memory. + * @details Inputs: recordAddressOffset, writtenRecordStatus + * @details Outputs: recordAddressOffset, writtenRecordStatus + * @return next state of the state machine + *************************************************************************/ +static NVDATAMGMT_EXEC_STATE_T handleExecVerifyRTCWriteState( void ) +{ + NVDATAMGMT_EXEC_STATE_T state = NVDATAMGMT_EXEC_STATE_VERIFY_RTC_WRITE; + BOOL timeoutStatus = didCommandTimeout ( ALARM_ID_NVDATA_EEPROM_OPS_FAILURE, (U08*)&state ); + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; + + // Check if the write job is EEPROM or RTC RAM if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - state = NVDATAMGMT_EXEC_STATE_IDLE; + U32 i; + U08* bufferPtr = jobSpecs.structAddressPtr + recordAddressOffset; + // Create a temporary buffer with the size of maximum RTC write + U08 tempBufferToCheckData [ MAX_RTC_RAM_OPS_BUFFER_BYTES ]; + getDataFromRAM( tempBufferToCheckData, jobSpecs.maxWriteBufferSize ); + + // Loop through the bytes in the buffer + for ( i = 0; i < jobSpecs.maxWriteBufferSize; i++ ) + { + // Check if data in the buffer is not the same as the data in the structure + if ( tempBufferToCheckData[ i ] != *bufferPtr ) + { + // Data is not valid. Go back to write to RTC state and rewrite the portion that was written + // but it is correct. + writtenRecordStatus = NVDATAMGMT_RECORD_NOT_VALID; + state = NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC; + // Exit the loop since there is no point to check the rest of data + break; + } + else + { + // Everything is good increment the pointer to check the next byte. + bufferPtr++; + // Record data is valid so far + writtenRecordStatus = NVDATAMGMT_RECORD_VALID; + // Go back write to RTC state to continue writing the record data + state = NVDATAMGMT_EXEC_STATE_WRITE_TO_RTC; + } + } } return state; @@ -1382,7 +2385,7 @@ * RAM was ready, and if the RAM got back to Idle after the read command, * it calls another function to read the data back from RTC RAM and * it sets the state to Idle. - * @details Inputs: currentJob + * @details Inputs: activeQueue, currentJob, recordCurrentJob * @details Outputs: currentJob * @return next state *************************************************************************/ @@ -1393,8 +2396,24 @@ if ( getRTCRAMStatus() == RTC_RAM_STATUS_IDLE || timeoutStatus == TRUE ) { - getDataFromRAM( currentJob.externalAddress->externalBuffer, currentJob.length ); - currentJob.externalAddress->status = NVDATAMGMT_READ_COMPLETE; + U08* bufferPtr = 0; + U32 length = 0; + + if ( activeQueue == NVDATAMGMT_PROCESS_RECORDS ) + { + RECORD_JOBS_STATE_T job = recordCurrentJob.recordJob; + PROCESS_RECORD_SPECS_T jobSpecs = RECORDS_SPECS [ job ]; + bufferPtr = jobSpecs.structAddressPtr; + length = jobSpecs.sizeofJob; + } + else + { + // TODO add the rest of the items for for logging + currentJob.externalAddress->status = NVDATAMGMT_READ_COMPLETE; + } + + getDataFromRAM( bufferPtr, length ); + state = NVDATAMGMT_EXEC_STATE_IDLE; } @@ -1403,6 +2422,135 @@ /*********************************************************************//** * @brief + * The handleExecProcessRecordIdleState handles the idle state of the + * exec cal state machine. + * @details Inputs: hasPublishRecordBeenRequested, calPublishTotalMessages, + * calPublishMessageCount, calSendDataIntervalCounter + * @details Outputs: hasPublishRecordBeenRequested, calPublishTotalMessages, + * calPublishMessageCount, calSendDataIntervalCounter + * @return next state of the state machine + *************************************************************************/ +static PROCESS_RECORD_STATE_T handleExecProcessRecordIdleState( void ) +{ + PROCESS_RECORD_STATE_T state = NVDATAMGMT_PROCESS_RECORD_STATE_IDLE; + + if ( hasPublishRecordBeenRequested ) + { + // Set the publish flag to FALSE + hasPublishRecordBeenRequested = FALSE; + + // Get the record specifications to find the size of the job + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS [ recordToPublish ]; + + // Calculate the total number of messages required to be sent using ceilf function. This function rounds up the + // value and its result is converted to U32. + calPublishTotalMessages = (U32)ceilf( (F32)recordSpec.sizeofJob / (F32)NUM_OF_BYTES_PER_CAL_PAYLOAD ); + calPublishMessageCount = 0; + + // Time interval in between data to be sent. It is set to the interval count so on the first call + // of the send calibration record function, the first packet of data is sent + calSendDataIntervalCounter = CAL_DATA_SEND_INTERVAL_COUNT; + + state = NVDATAMGMT_PROCESS_RECORD_STATE_SEND_RECORD; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleExecProcessRecordSendRecordState handles the send calibration + * record state of the state machine. + * @details Inputs: dgCalibrationRecord, calPublishTotalMessages, + * calPublishMessageCount, calSendDataIntervalCounter + * @details Outputs: calPublishTotalMessages, calPublishMessageCount, + * calSendDataIntervalCounter + * @return next state of the state machine + *************************************************************************/ +static PROCESS_RECORD_STATE_T handleExecProcessRecordSendRecordState( void ) +{ + PROCESS_RECORD_STATE_T state = NVDATAMGMT_PROCESS_RECORD_STATE_SEND_RECORD; + + // If the current message number is less than the total, keep sending + if ( calPublishMessageCount < calPublishTotalMessages ) + { + // If it is time to send data + if ( ++calSendDataIntervalCounter >= CAL_DATA_SEND_INTERVAL_COUNT ) + { + // Set to default cal data payload length + U32 length = NUM_OF_BYTES_PER_CAL_PAYLOAD; + + PROCESS_RECORD_SPECS_T recordSpec = RECORDS_SPECS [ recordToPublish ]; + U08* startPtr = recordSpec.structAddressPtr; + + // If this is the last calibration data payload, calculate the remainder of the bytes to send + if ( ( calPublishMessageCount + 1 ) == calPublishTotalMessages ) + { + length = recordSpec.sizeofJob - ( calPublishMessageCount * NUM_OF_BYTES_PER_CAL_PAYLOAD ); + } + + // Find the new location of the pointer which is the start of the calibration payload to be sent + startPtr += calPublishMessageCount * NUM_OF_BYTES_PER_CAL_PAYLOAD; + + switch( recordToPublish ) + { + case NVDATAMGMT_CALIBRATION_RECORD: +#ifdef _DG_ + // Pass the information to the CAN bus + sendDGCalibrationRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif +#ifdef _HD_ + sendHDCalibrationRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif + break; + + case NVDATAMGMT_SYSTEM_RECORD: +#ifdef _DG_ + // Pass the information to the CAN bus + sendDGSystemRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif +#ifdef _HD_ + sendHDSystemRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif + break; + + case NVDATAMGMT_SERVICE_RECORD: +#ifdef _DG_ + // Pass the information to the CAN bus + sendDGServiceRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif +#ifdef _HD_ + sendHDServiceRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif + break; + + case NVDATAMGMT_SCHEDULED_RUNS_RECORD: +#ifdef _DG_ + // Pass the information to the CAN bus + sendDGScheduledRunsRecord( calPublishMessageCount + 1, calPublishTotalMessages, length, startPtr ); +#endif + // There are no scheduled runs for HD right now. + break; + + default: + //Ignore + break; + } + + calPublishMessageCount++; + calSendDataIntervalCounter = 0; + } + } + else + { + state = NVDATAMGMT_PROCESS_RECORD_STATE_IDLE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The setMemoryOpsStruct function checks whether it is an EEPROM write, * EEPROM read, or RTC RAM operation. For read or write data logs into EEPROM, * it calls other functions to check for wraps and to find the next address for @@ -1695,33 +2843,6 @@ /*********************************************************************//** * @brief - * The enqueueBank7Sector0Records checks whether there are enough number of - * queues for erasing and setting the records. If there are enough queues, - * it schedules an erase job and then schdules jobs to write all the records - * back to Bank 7 Sector 0. - * @details Inputs: mfgRecord, calibrationRecord - * @details Outputs: none - * @return TRUE if there are enough queue jobs available - *************************************************************************/ -static BOOL enqueueBank7Sector0Records( void ) -{ - BOOL status = FALSE; - U32 currentQueueCount = getAvailableQueueCount(); - - if ( currentQueueCount >= MIN_JOBS_NEEDED_FOR_SECTOR_0 ) - { - // Sector 0 must be erased first - enqueue ( NVDATAMGMT_ERASE_SECTOR, NVDATAMGMT_EEPROM, BANK7_SECTOR0_START_ADDRESS, 0, 0, 0 ); - enqueue ( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, BANK7_SECTOR0_START_ADDRESS, (U08*)&mfgRecord, 0, sizeof(MFG_RECORD_T) ); - enqueue ( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, CALIBRATION_RECORD_START_ADDRESS, (U08*)&calibrationRecord, 0, sizeof(CALIBRATION_RECORD_T) ); - status = TRUE; - } - - return status; -} - -/*********************************************************************//** - * @brief * The didCommandTimedout checks whether the a command whether RTC RAM or * EEPROM has timedout. If it has timedout, it sets the alarm and turns * flag to TRUE. @@ -1742,7 +2863,6 @@ if ( didTimeout( currentTime, COMMAND_TIME_OUT ) ) { SET_ALARM_WITH_1_U32_DATA( alarm, *state ); - hasCommandTimedout = TRUE; status = TRUE; } @@ -1773,4 +2893,856 @@ return status; } +/*********************************************************************//** + * @brief + * The monitorNewCalSignal function monitors the new calibration signal + * and if it on and time to on has elapsed, it turns it off. + * @details Inputs: isNewCalAvailable + * @details Outputs: isNewCalAvailable + * @return none + *************************************************************************/ +static void monitorNewCalSignal( void ) +{ + if ( didTimeout( newCalStartTimer, NEW_CAL_AVAILABLE_SIGNAL_TIMEOUT_MS ) && ( TRUE == isNewCalAvailable ) ) + { + isNewCalAvailable = FALSE; + } +} + +/*********************************************************************//** + * @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 + * @details Outputs: none + * @return TRUE if the records' data is valid otherwise FALSE + *************************************************************************/ +static BOOL areRecordsValid( void ) +{ + U32 i; + U16 calcCRC; + U16 recordCRC; + PROCESS_RECORD_SPECS_T spec; + BOOL status = TRUE; + + for ( i = 0; i < NUM_OF_NVDATMGMT_RECORDS_JOBS; i++ ) + { + spec = RECORDS_SPECS [ i ]; + calcCRC = crc16 ( spec.structAddressPtr, spec.sizeofJob - sizeof(U16) ); + recordCRC = *(U16*)spec.structCRCPtr; + + // If the CRCs do not match, break out of loop since POST will be failed + // regardless of the rest of the results + if ( calcCRC != recordCRC ) + { +#ifndef DISABLE_CAL_CHECK + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_NVDATAMGMT_GROUP_RECORD_CRC_INVALID, i ); + status = FALSE; +#endif + } + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isPolynomialRecordValid function checks whether the records are + * still valid by calculating the CRCs and comparing it to the strucutre's + * CRC. + * @details Inputs: none + * @details Outputs: none + * @param record: pointer to a polynomial payload. The actual calibration + * data to be checked + * @param isRecordNeeded: TRUE is the calibration record is need in the firmware + * right now otherwise, FALSE + * @return TRUE if the records' data is valid otherwise FALSE + *************************************************************************/ +static BOOL isPolynomialRecordValid( POLYNOMIAL_CAL_PAYLOAD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(POLYNOMIAL_CAL_PAYLOAD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + 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; + // Recalculate the CRC with the default values + record->crc = crc16 ( (U08*)record, sizeof(POLYNOMIAL_CAL_PAYLOAD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +#ifdef _DG_ +/*********************************************************************//** + * @brief + * The isDGCalibrationRecordValid function calls other functions to check + * the validity of DG calibration record. + * @details Inputs: dgCalibrationRecord + * @details Outputs: none + * @return TRUE if the DG calibration record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGCalibrationRecordValid( void ) +{ + U32 i; + POLYNOMIAL_CAL_PAYLOAD_T* record; + BOOL isHardwareRecordValid = TRUE; + BOOL isCalRecordValid = TRUE; + + // Get the calibration record of the hardware (i.e. pressure sensor) + DG_PRES_SENSORS_CAL_RECORD_T* pressure = &dgCalibrationRecord.dgCalibrationGroups.presSensorsCalRecord; + // The ones that are an array, are looped through + for ( i = 0; i < NUM_OF_CAL_DATA_PRES_SENSORS; i++ ) + { + // Get calibration payload and assign it to a pointer + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&pressure->pressureSensors[ i ]; + // Check in the validity of the calibration data + // If the variable is already FALSE, let it be FALSE. Even if one record is not + // valid, the values should be set to benign values. This variable is used to decide + // whether a write should be scheduled or not so it should not be overwritten with a TRUE + // once a record set it to FALSE + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_FLOW_SENSORS_CAL_RECORD_T* flow = &dgCalibrationRecord.dgCalibrationGroups.flowSensorsCalRecord; + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&flow->flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_LOAD_CELLS_CAL_RECORD_T* load = &dgCalibrationRecord.dgCalibrationGroups.loadCellsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_LOAD_CELLS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&load->loadCells[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_TEMP_SENSORS_CAL_RECORD_T* temperature = &dgCalibrationRecord.dgCalibrationGroups.tempSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_TEMP_SENSORS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&temperature->tempSensors[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_COND_SENSORS_CAL_RECORD_T* cond = &dgCalibrationRecord.dgCalibrationGroups.condSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_COND_SENSORS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&cond->condSensors[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_CONC_PUMPS_CAL_RECORD_T* concPump = &dgCalibrationRecord.dgCalibrationGroups.concentratePumpsRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_DG_CONC_PUMPS; i++ ) + { + isHardwareRecordValid = isDGConcPumpRecordValid( &concPump->concentratePumps[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_DRAIN_PUMP_CAL_RECORD_T* drainPump = &dgCalibrationRecord.dgCalibrationGroups.drainPumpRecord; + isCalRecordValid = isDGDrainPumpRecordValid( drainPump ) != TRUE ? FALSE : isCalRecordValid; + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_RO_PUMP_CAL_RECORD_T* roPump = &dgCalibrationRecord.dgCalibrationGroups.roPumpRecord; + isHardwareRecordValid = isDGROPumpRecordValid( roPump ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_DRAIN_LINE_VOLUME_T* drainLineVol = &dgCalibrationRecord.dgCalibrationGroups.drainLineVolumeRecord; + isHardwareRecordValid = isDGDrainLineVolRecordValid( drainLineVol ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_RESERVOIR_VOLUME_RECORD_T* reservoirVol = &dgCalibrationRecord.dgCalibrationGroups.reservoirVolumesRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_RSRVRS; i++ ) + { + isHardwareRecordValid = isDGReservoirVolRecordValid( &reservoirVol->reservoir[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_GENERIC_VOLUME_RECORD_T* genericVol = &dgCalibrationRecord.dgCalibrationGroups.genericVolumeRecord; + for ( i = 0; i < 4; i++ ) + { + isHardwareRecordValid = isDGGenericVolRecordValid( &genericVol->genericVolume[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_ACID_CONCENTRATES_RECORD_T* acidConc = &dgCalibrationRecord.dgCalibrationGroups.acidConcentratesRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_ACID_CONCENTRATES; i++ ) + { + isHardwareRecordValid = isDGAcidConcentrateRecordValid( &acidConc->acidConcentrate[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_BICARB_CONCENTRATES_RECORD_T* bicarbConc = &dgCalibrationRecord.dgCalibrationGroups.bicarbConcentratesRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_BICARB_CONCENTRATES; i++ ) + { + isHardwareRecordValid = isDGBicarbConcentrateRecordValid( &bicarbConc->bicarbConcentrate[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + DG_FILTER_CAL_RECORD_T* roFilter = &dgCalibrationRecord.dgCalibrationGroups.filtersRecord.roFilter; + isHardwareRecordValid = isDGFilterRecordValid( roFilter ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_FILTER_CAL_RECORD_T* ultraFilter = &dgCalibrationRecord.dgCalibrationGroups.filtersRecord.ultraFilter; + isHardwareRecordValid = isDGFilterRecordValid( ultraFilter ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_FILTER_CAL_RECORD_T* sedimentFilter = &dgCalibrationRecord.dgCalibrationGroups.filtersRecord.sedimentFilter; + isHardwareRecordValid = isDGFilterRecordValid( sedimentFilter ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_FILTER_CAL_RECORD_T* carbonFilter = &dgCalibrationRecord.dgCalibrationGroups.filtersRecord.carbonFilter; + isHardwareRecordValid = isDGFilterRecordValid( carbonFilter ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_FILTER_CAL_RECORD_T* carbonPolishFilter = &dgCalibrationRecord.dgCalibrationGroups.filtersRecord.carbonPolishFilter; + isHardwareRecordValid = isDGFilterRecordValid( carbonPolishFilter ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_FANS_CAL_RECORD_T* fan = &dgCalibrationRecord.dgCalibrationGroups.fansRecord; + isHardwareRecordValid = isDGFanRecordValid( &fan->fan1 ); + + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + isHardwareRecordValid = isDGFanRecordValid( &fan->fan2 ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + DG_ACCELEROMETER_SENSOR_CAL_RECORD_T* accelerometer = &dgCalibrationRecord.dgCalibrationGroups.accelerometerCalRecord; + isHardwareRecordValid = isDGAccelerometerSensorRecordValid( accelerometer ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + return isCalRecordValid; +} + +/*********************************************************************//** + * @brief + * The isDGConcPumpRecordValid function checks whether the calibration + * record of concentrate pump is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_CONC_PUMPS_CAL_DATA_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGConcPumpRecordValid( DG_CONC_PUMPS_CAL_DATA_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_CONC_PUMPS_CAL_DATA_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->stepSpeed2FlowRatio = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_CONC_PUMPS_CAL_DATA_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGDrainPumpRecordValid function checks whether the calibration + * record of drain pump is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_DRAIN_PUMP_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGDrainPumpRecordValid( DG_DRAIN_PUMP_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_DRAIN_PUMP_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->stepSpeed2FlowRatio = RECORD_DEFAULT_RATIO; + record->voltage2SpeedRatio = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_DRAIN_PUMP_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGROPumpRecordValid function checks whether the calibration + * record of RO pump is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_RO_PUMP_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGROPumpRecordValid( DG_RO_PUMP_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_RO_PUMP_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->gain1Ratio = RECORD_DEFAULT_RATIO; + record->gain2Ratio = RECORD_DEFAULT_RATIO; + record->gain3Ratio = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_RO_PUMP_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGDrainLineVolRecordValid function checks whether the calibration + * record of drain line volume is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_DRAIN_LINE_VOLUME_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGDrainLineVolRecordValid( DG_DRAIN_LINE_VOLUME_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_DRAIN_LINE_VOLUME_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->volume = RECORD_DEFAULT_CONST; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_DRAIN_LINE_VOLUME_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGReservoirVolRecordValid function checks whether the calibration + * record of reservoir volume is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_RESERVOIR_VOLUME_DATA_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGReservoirVolRecordValid( DG_RESERVOIR_VOLUME_DATA_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_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 = RECORD_DEFAULT_CONST; + record->rsrvrVolume = RECORD_DEFAULT_CONST; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_RESERVOIR_VOLUME_DATA_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGGenericVolRecordValid function checks whether the calibration + * record of generic volume is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_GENERIC_VOLUME_DATA_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGGenericVolRecordValid( DG_GENERIC_VOLUME_DATA_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_GENERIC_VOLUME_DATA_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->volume = RECORD_DEFAULT_CONST; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_GENERIC_VOLUME_DATA_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGAcidConcentrateRecordValid function checks whether the calibration + * record of acid concentrate is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_ACID_CONCENTRATE_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGAcidConcentrateRecordValid( DG_ACID_CONCENTRATE_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_ACID_CONCENTRATE_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->startVolume = RECORD_DEFAULT_CONST; + record->reserverdSpace = RECORD_DEFAULT_CONST; + record->acidConcMixRatio = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_ACID_CONCENTRATE_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGBicarbConcentrateRecordValid function checks whether the + * calibration record of bicarb concentrate is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_BICARB_CONCENTRATE_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGBicarbConcentrateRecordValid( DG_BICARB_CONCENTRATE_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_BICARB_CONCENTRATE_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->startVolume = RECORD_DEFAULT_CONST; + record->reservedSpace = RECORD_DEFAULT_CONST; + record->bicarbConcMixRatio = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_BICARB_CONCENTRATE_T) - sizeof(U16) ); + + // Alarm if the CRC did not pass + activateAlarmNoData( ALARM_ID_NVDATAMGMT_INDIVIDUAL_RECORD_CRC_INVALID ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGFilterRecordValid function checks whether the calibration + * record of filter is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_FILTER_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGFilterRecordValid( DG_FILTER_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_FILTER_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->reservedSpace1 = RECORD_DEFAULT_CONST; + record->reservedSpace2 = RECORD_DEFAULT_CONST; + record->reservedSpace3 = RECORD_DEFAULT_CONST; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_FILTER_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGFanRecordValid function checks whether the calibration record + * of fan is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_FAN_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGFanRecordValid( DG_FAN_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_FAN_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->reservedSpace1 = RECORD_DEFAULT_CONST; + record->reservedSpace2 = RECORD_DEFAULT_CONST; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_FAN_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isDGAccelerometerSensorRecordValid function checks whether the + * calibration record of accelerometer sensor is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: DG_ACCELEROMETER_SENSOR_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isDGAccelerometerSensorRecordValid( DG_ACCELEROMETER_SENSOR_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(DG_ACCELEROMETER_SENSOR_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->accelXOffset = RECORD_DEFAULT_OFFSET; + record->accelYOffset = RECORD_DEFAULT_OFFSET; + record->accelZOffset = RECORD_DEFAULT_OFFSET; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(DG_ACCELEROMETER_SENSOR_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} +#endif +#ifdef _HD_ +/*********************************************************************//** + * @brief + * The isHDCalibrationRecordValid function checks whether HD calibration + * record is valid or not. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isHDCalibrationRecordValid( void ) +{ + U32 i; + POLYNOMIAL_CAL_PAYLOAD_T* record; + BOOL isHardwareRecordValid = TRUE; + BOOL isCalRecordValid = TRUE; + + HD_PUMPS_CAL_RECORD_T* pump = &hdCalibrationRecord.hdCalibrationGroups.pumpsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_HD_PUMPS; i++ ) + { + isHardwareRecordValid = isHDPumpRecordValid( &pump->hdPumps[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + HD_VALVES_CAL_RECORD_T* valve = &hdCalibrationRecord.hdCalibrationGroups.valvesCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_HD_VALVES; i++ ) + { + isHardwareRecordValid = isHDValveRecordValid( &valve->hdvalves[ i ] ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + HD_OCCLUSION_SENSORS_CAL_RECORD_T* occlusion = &hdCalibrationRecord.hdCalibrationGroups.occlusionSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_OCCLUSION_SENSORS; i++ ) + { + // Get calibration payload and assign it to a pointer + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&occlusion->hdOcclusionSensors[ i ]; + // Check in the validity of the calibration data + // If the variable is already FALSE, let it be FALSE. Even if one record is not + // valid, the values should be set to benign values. This variable is used to decide + // whether a write should be scheduled or not so it should not be overwritten with a TRUE + // once a record set it to FALSE + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + HD_FLOW_SENSORS_CAL_RECORD_T* flow = &hdCalibrationRecord.hdCalibrationGroups.flowSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_HD_FLOW_SENSORS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&flow->hdFlowSensors[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + HD_PRESSURE_SENSORS_CAL_RECORD_T* pressure = &hdCalibrationRecord.hdCalibrationGroups.pressureSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_HD_PRESSURE_SESNSORS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&pressure->hdPressureSensors[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + } + + HD_TEMP_SENSORS_CAL_RECORD_T* temperature = &hdCalibrationRecord.hdCalibrationGroups.tempSensorsCalRecord; + for ( i = 0; i < NUM_OF_CAL_DATA_HD_TEMP_SENSORS; i++ ) + { + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&temperature->hdTemperatureSensors[ i ]; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE :isHardwareRecordValid; + } + + HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T* heparinForce = &hdCalibrationRecord.hdCalibrationGroups.heparinForceSensorCalRecord; + record = (POLYNOMIAL_CAL_PAYLOAD_T*)&heparinForce->hdHeparinForceSensor; + isHardwareRecordValid = isPolynomialRecordValid( record ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + + HD_ACCELEROMETER_SENSOR_CAL_RECORD_T* accelerometer = &hdCalibrationRecord.hdCalibrationGroups.accelerometerCalRecord; + isHardwareRecordValid = isHDAccelerometerSensorValid( accelerometer ); + isCalRecordValid = isCalRecordValid == FALSE ? FALSE : isHardwareRecordValid; + + return isCalRecordValid; +} + +/*********************************************************************//** + * @brief + * The isHDPumpRecordValid function checks whether the calibration record + * of HD pump(s) is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: HD_PUMP_CAL_PAYLOAD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isHDPumpRecordValid( HD_PUMP_CAL_PAYLOAD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(HD_PUMP_CAL_PAYLOAD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->maxCurrentLimit = RECORD_DEFAULT_OFFSET; + record->minCurrentLimit = RECORD_DEFAULT_OFFSET; + record->pwm2Speed = RECORD_DEFAULT_RATIO; + record->speed2Flow = RECORD_DEFAULT_RATIO; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(HD_PUMP_CAL_PAYLOAD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isHDValveRecordValid function checks whether the calibration record + * of HD valve is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: HD_VALVE_CAL_PAYLOAD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isHDValveRecordValid( HD_VALVE_CAL_PAYLOAD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(HD_VALVE_CAL_PAYLOAD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->counts2Position = RECORD_DEFAULT_OFFSET; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(HD_VALVE_CAL_PAYLOAD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The isHDAccelerometerSensorValid function checks whether the + * calibration record of accelerometer sensor is valid or not. + * @details Inputs: none + * @details Outputs: none + * @param record: HD_ACCELEROMETER_SENSOR_CAL_RECORD_T pointer + * @return TRUE if the record is valid otherwise FALSE + *************************************************************************/ +static BOOL isHDAccelerometerSensorValid( HD_ACCELEROMETER_SENSOR_CAL_RECORD_T* record ) +{ + BOOL status = TRUE; + U16 calcCRC = crc16 ( (U08*)record, sizeof(HD_ACCELEROMETER_SENSOR_CAL_RECORD_T) - sizeof(U16) ); + U16 recordCRC = record->crc; + + if ( calcCRC != recordCRC ) + { + // CRC did not pass so set all values to default + record->accelXOffset = RECORD_DEFAULT_OFFSET; + record->accelYOffset = RECORD_DEFAULT_OFFSET; + record->accelZOffset = RECORD_DEFAULT_OFFSET; + record->calibrationTime = RECORD_DEFAULT_TIME; + record->crc = crc16 ( (U08*)record, sizeof(HD_ACCELEROMETER_SENSOR_CAL_RECORD_T) - sizeof(U16) ); + + // Set the to FALSE since the record is not valid + status = FALSE; + } + + return status; +} +#endif + +/*********************************************************************//** + * @brief + * The enqueueRecordJob function enqueues a new record job. + * @details Inputs: queueFrontIndex, queueCount, recordJobQueue + * @details Outputs: queueFrontIndex, queueCount, recordJobQueue + * @param ops: memory operation (i.e write, read) + * @param location: memory location which are either EEPROM or RTC RAM + * @param job: type of job (i.e write calibration data) + * @return none + *************************************************************************/ +static void enqueueRecordJob( NVDATAMGMT_OPERATION_STATE_T ops, NVDATAMGMT_LOCATION_STATE_T location, RECORD_JOBS_STATE_T job ) +{ + PROCESS_RECORD_JOB_T currentJob; + + currentJob.memoryLocation = location; + currentJob.memoryOperation = ops; + currentJob.recordJob = job; + + recordJobQueue[ recordQueueRearIndex ] = currentJob; + + recordQueueCount++; + recordQueueRearIndex = INC_WRAP( recordQueueRearIndex, 0, QUEUE_MAX_SIZE - 1 ); +} + +/*********************************************************************//** + * @brief + * The dequeueRecordJob increments the front index counter and if it is + * equal to rear index, it sets it to -1, meaning that the queue is empty. + * @details Inputs: recordQueueFrontIndex, recordQueueCount, recordCurrentJob, + * recordJobQueue + * @details Outputs: recordQueueFrontIndex, recordQueueCount, recordCurrentJob + * @return none + *************************************************************************/ +static void dequeueRecordJob( void ) +{ + U32 tempIndex; + + _disable_IRQ(); + tempIndex = recordQueueFrontIndex; + + if ( !isRecordQueueEmpty() ) + { + recordQueueFrontIndex = INC_WRAP( recordQueueFrontIndex, 0, QUEUE_MAX_SIZE - 1 ); + recordCurrentJob = recordJobQueue[ tempIndex ]; + } + if ( recordQueueCount > 0 ) + { + recordQueueCount--; + } + _enable_IRQ(); +} + +/*********************************************************************//** + * @brief + * The isRecordQueueEmpty checks whether the queue is empty and if it is + * empty, it will return a false. + * @details Inputs: recordQueueCount + * @details Outputs: none + * @return TRUE if queue is not empty + *************************************************************************/ +static BOOL isRecordQueueEmpty( void ) +{ + BOOL isEmpty = TRUE; + + if ( recordQueueCount > 0 ) + { + isEmpty = FALSE; + } + + return isEmpty; +} + +/*********************************************************************//** + * @brief + * The getAvailableRecordQueueCount returns the number of available record + * queues. + * @details Inputs: recordQueueCount + * @details Outputs: none + * @return available record queues + *************************************************************************/ +static U32 getAvailableRecordQueueCount( void ) +{ + return QUEUE_MAX_SIZE - recordQueueCount; +} + +/*********************************************************************//** + * @brief + * The enqueueSector0Records checks whether there are enough jobs available + * to be able to enqueue to the records. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if the job were successfully enqueued otherwise, FLASE + *************************************************************************/ +static BOOL enqueueSector0Records( void ) +{ + BOOL status = FALSE; + + if ( getAvailableRecordQueueCount() >= MIN_JOBS_NEEDED_FOR_SECTOR_0 ) + { + enqueueRecordJob( NVDATAMGMT_ERASE_SECTOR, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, NVDATAMGMT_CALIBRATION_RECORD ); + enqueueRecordJob( NVDATAMGMT_WRITE, NVDATAMGMT_EEPROM, NVDATAMGMT_SYSTEM_RECORD ); + + status = TRUE; + } + + return status; +} + /**@}*/