Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -111,6 +111,10 @@ static BOOL hasClosedLoopBeenRequested = FALSE; ///< Closed loop pump control flag. static U32 currentDrainPumpRPM = 0; ///< Current drain pump RPM from feedback. +static DRAIN_PUMP_STATE_T pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; ///< Delayed (pending) drain pump command. +static F32 pendingDrainPumpCmdTarget = 0.0; ///< Delayed (pending) drain pump command target (rpm or PSI depending on command). +static U32 pendingDrainPumpCmdCountDown = 0; ///< Delayed (pending) drain pump command count down timer (in task intervals). + /* TODO These variables are used for POST. POST will be implemented later static DRAIN_PUMP_SELF_TEST_STATE_T drainPumpSelfTestState = DRAIN_PUMP_SELF_TEST_STATE_START; ///< Current drain pump self test state. static U32 drainPumpSelfTestTimerCount = 0; ///< Timer counter for drain pump self test. @@ -187,8 +191,38 @@ /*********************************************************************//** * @brief - * The setDrainPumpTargetOutletPressure function sets the target drain pump - * outlet pressure. + * The setDrainPumpTargetRPMDelayed function sets a new target RPM for the + * drain pump with delayed start. + * @details Inputs: drainPumpDAC, targetDrainPumpSpeed, drainPumpControlMode, + * drainPumpControlModeSet + * @details Outputs: pendingDrainPumpCmd, pendingDrainPumpCmdTarget, pendingDrainPumpCmdCountDown + * @param rpm new drain pump target RPM + * @param delayMs delay duration (in ms) before drain pump started + * @return TRUE if new target RPM is set, FALSE if not + *************************************************************************/ +BOOL setDrainPumpTargetRPMDelayed( U32 rpm, U32 delayMs ) +{ + BOOL result = FALSE; + + if ( ( 0 == rpm ) || ( ( rpm >= MIN_DRAIN_PUMP_RPM ) && ( rpm <= MAX_DRAIN_PUMP_RPM ) ) ) + { + pendingDrainPumpCmd = DRAIN_PUMP_OPEN_LOOP_STATE; + pendingDrainPumpCmdTarget = (F32)rpm; + pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; + result = TRUE; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_RPM_SELECTED, rpm ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setDrainPumpTargetOutletPressure function sets the drain pump to start + * with given target PDr pressure. * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, @@ -221,6 +255,38 @@ /*********************************************************************//** * @brief + * The setDrainPumpTargetOutletPressureDelayed function sets the drain pump + * to start with given target PDr pressure after given delay. + * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, + * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet + * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, + * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet + * @param pressure new target drain pump outlet pressure + * @param delayMS delay duration (in ms) before drain pump started + * @return TRUE if new target speed is set, FALSE if not + *************************************************************************/ +BOOL setDrainPumpTargetOutletPressureDelayed( F32 pressure, U32 delayMs ) +{ + BOOL result = FALSE; + + // Check the delta pressure is in range + if ( ( pressure >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( pressure <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) + { + pendingDrainPumpCmd = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; + pendingDrainPumpCmdTarget = pressure; + pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; + result = TRUE; + } + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, pressure ) + } + + return result; +} + +/*********************************************************************//** + * @brief * The signalDrainPumpHardStop function stops the Drain pump immediately. * @details Inputs: targetDrainPumpSpeed, drainPumpState, drainPumpControlMode, * hasClosedLoopBeenRequested, drainControlTimerCounter @@ -311,6 +377,33 @@ *************************************************************************/ void execDrainPumpController( void ) { + // Handle pending drain pump command + if ( pendingDrainPumpCmdCountDown > 0 ) + { + pendingDrainPumpCmdCountDown--; + if ( 0 == pendingDrainPumpCmdCountDown ) + { + if ( DRAIN_PUMP_CONTROL_TO_TARGET_STATE == pendingDrainPumpCmd ) + { + targetDrainPumpOutletPressure = pendingDrainPumpCmdTarget; + hasClosedLoopBeenRequested = TRUE; + drainPumpDAC = DRAIN_PUMP_MIN_DAC; + drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + drainPumpControlModeSet = drainPumpControlMode; + } + else if ( DRAIN_PUMP_OPEN_LOOP_STATE == pendingDrainPumpCmd ) + { + drainPumpDAC = (U32)(pendingDrainPumpCmdTarget * DRP_SPEED_RPM_TO_ADC_FACTOR + FLOAT_TO_INT_ROUNDUP_OFFSET); + targetDrainPumpRPM = (U32)pendingDrainPumpCmdTarget; + drainPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; + drainPumpControlModeSet = drainPumpControlMode; + } + pendingDrainPumpCmdTarget = 0.0; + pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; + } + } + + // Execute drain pump state machine switch ( drainPumpState ) { case DRAIN_PUMP_OFF_STATE: @@ -378,6 +471,18 @@ /*********************************************************************//** * @brief + * The isDrainPumpOn function determines whether the drain pump is on. + * @details Inputs: drainPumpDACSet + * @details Outputs: none + * @return TRUE if drain pump is on, FALSE if not. + *************************************************************************/ +BOOL isDrainPumpOn( void ) +{ + return ( drainPumpDACSet > 0 ? TRUE : FALSE ); +} + +/*********************************************************************//** + * @brief * The handleDrainPumpOffState function handles the drain pump off state of * the drain pump controller state machine. * @details Inputs: drainPumpControlModeSet, drainPumpDACSet, drainPumpDAC @@ -391,7 +496,7 @@ // If the target drain pump speed was not 0 and the control mode // is open loop, set the drain pump to open loop - if ( getTargetDrainPumpRPM() > 0 && drainPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) + if ( ( getTargetDrainPumpRPM() > 0 ) && ( drainPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) ) { // Set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); @@ -404,7 +509,7 @@ } // If the drain pump is set to closed loop, call the proper state // It is checked for the value of delta pressure because it can be anything including 0 - else if ( drainPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP && hasClosedLoopBeenRequested ) + else if ( ( drainPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) && ( hasClosedLoopBeenRequested ) ) { // set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r7b6b599a6f98241bc51bbee65b736b92cb881f01 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 7b6b599a6f98241bc51bbee65b736b92cb881f01) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -37,7 +37,7 @@ #define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. /// Conversion factor from ADC counts to grams. static const F32 ADC2GRAM = (0.0894 * 1.1338); -#define LOAD_CELL_ZERO_OFFSET -1500.0 ///< Zero offset (in grams). TODO - right now, this is empty reservoir weight. + #define LOAD_CELL_FILTER_ALPHA 0.05 ///< Alpha factor for the alpha filter used on load cell readings. #define SIZE_OF_SMALL_LOAD_CELL_AVG 100 ///< Small load cell moving average has 100 raw samples @ 10ms intervals (1-second). @@ -48,18 +48,18 @@ /// Load cell data structure. typedef struct { - U32 rawReading; ///< Latest raw load cell reading - OVERRIDE_F32_T weight; ///< Latest load cell weight + U32 rawReading; ///< Latest raw load cell reading. + OVERRIDE_F32_T weight; ///< Latest load cell weight. F32 autoCalOffset; ///< Load cell auto-calibration offset F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. - F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average - F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average - F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight + F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. + F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. + F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. - F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average - F32 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average - F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight + F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. + F32 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average. + F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight. } LOADCELL_T; // ********** private data ********** @@ -74,8 +74,6 @@ static U32 largeReadingsIdx; ///< Index for next sample in load cell large rolling average sample array. static DG_LOAD_CELLS_CAL_RECORD_T loadCellsCalRecord; ///< Load cells calibration record. -// TODO - gain and offset for load cells should be read from NV Data calibration record. - // ********** private function prototypes ********** static U32 getLoadCellDataPublishInterval( void ); @@ -174,10 +172,31 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, ( a1 | a2 | b1 | b2 ) ) } + // Check if a new calibration is available + if ( isNewCalibrationRecordAvailable() == TRUE ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + + // Zero the current tare values when new calibration data is available + loadcells[ LOAD_CELL_RESERVOIR_1_PRIMARY ].autoCalOffset = 0.0; + loadcells[ LOAD_CELL_RESERVOIR_1_BACKUP ].autoCalOffset = 0.0; + loadcells[ LOAD_CELL_RESERVOIR_2_PRIMARY ].autoCalOffset = 0.0; + loadcells[ LOAD_CELL_RESERVOIR_2_BACKUP ].autoCalOffset = 0.0; + } + // Rolling average of last 100 raw samples in small filter for ( ii = 0; ii < NUM_OF_LOAD_CELLS; ++ii ) { - loadcells[ ii ].weight.data = (F32)loadcells[ ii ].rawReading * ADC2GRAM + LOAD_CELL_ZERO_OFFSET - loadcells[ ii ].autoCalOffset; + loadcells[ ii ].weight.data = (F32)loadcells[ ii ].rawReading * ADC2GRAM; + // Apply the calibration factors to the data. + // load_cell_weight = fourth_order_coeff * (load_cell^4) + third_order_coeff * (load_cell^3) + second_order_coeff * (load_cell^2) + gain * load_cell + offset + loadcells[ ii ].weight.data = pow(loadcells[ ii ].weight.data, 4) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].fourthOrderCoeff + + pow(loadcells[ ii ].weight.data, 3) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].thirdOrderCoeff + + pow(loadcells[ ii ].weight.data, 2) * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].secondOrderCoeff + + loadcells[ ii ].weight.data * loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].gain + + loadCellsCalRecord.loadCells[ (CAL_DATA_DG_LOAD_CELLS_T)ii ].offset; + loadcells[ ii ].weight.data = loadcells[ ii ].weight.data - loadcells[ ii ].autoCalOffset; loadcells[ ii ].loadCellVelocity_g_min = ( getLoadCellWeight( (LOAD_CELL_ID_T)ii ) - loadcells[ ii ].smallFilterReadings[ smallReadingsIdx ] ) * (F32)SEC_PER_MIN; // Update small filter with new weight sample Index: firmware/App/Controllers/Pressures.c =================================================================== diff -u -rbdf2072247c8779596c6bcf418c5a7ae4d9f9848 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision bdf2072247c8779596c6bcf418c5a7ae4d9f9848) +++ firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -35,7 +35,7 @@ #define PUMP_PRESSURE_ZERO 777 ///< ADC counts equivalent to 0 PSI for pump in/out pressure sensors. #define PUMP_PRESSURE_PSIA_PER_COUNT 0.06434 ///< PSIA per ADC count conversion factor for pump in/out pressure sensors. -#define PUMP_PRESSURE_PSIA_TO_PSI_OFFSET 14.7 ///< Subtract this offset to convert PSIA to PSI. +#define PUMP_PRESSURE_PSIA_TO_PSI_OFFSET 14.7 ///< Subtract this offset to convert PSIA to PSI. TODO - use barometric sensor when available. #define PRESSURE_SAMPLES_TO_AVERAGE ( 200 / TASK_PRIORITY_INTERVAL ) ///< Averaging pressure data over the reporting interval. #define PRESSURE_AVERAGE_MULTIPLIER ( 1.0 / (F32)PRESSURE_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r8467f8ff09e382e0991f14d02683080dc811e24e -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 8467f8ff09e382e0991f14d02683080dc811e24e) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -113,6 +113,10 @@ static F32 roPumpDutyCyclePctSet = 0.0; ///< Currently set RO pump PWM duty cycle. static PUMP_CONTROL_MODE_T roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Requested RO pump control mode. +static F32 pendingROPumpCmdMaxPressure = 0.0; ///< Delayed (pending) RO pump max pressure (in PSI) setting. +static F32 pendingROPumpCmdTargetFlow = 0.0; ///< Delayed (pending) RO pump target flow rate (in mL/min) setting. +static U32 pendingROPumpCmdCountDown = 0; ///< Delayed (pending) RO pump command count down timer (in task intervals). + static F32 targetROPumpFlowRate = 0.0; ///< Target RO flow rate (in L/min). static F32 targetROPumpMaxPressure = 0.0; ///< Target RO max allowed pressure (in PSI). @@ -169,7 +173,8 @@ initPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, FLOW_OUT_OF_RANGE_PERSISTENT_INTERVAL, FLOW_OUT_OF_RANGE_PERSISTENT_INTERVAL ); // Initialize the persistent alarm for max allowed pressure out of range - initPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL, MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL ); + initPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL, + MAX_PRESSURE_OUT_OF_RANGE_PERSISTENT_INTERVAL ); // Initialize the persistent alarm for not turning off the pump initPersistentAlarm( ALARM_ID_RO_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); @@ -237,6 +242,49 @@ /*********************************************************************//** * @brief + * The setROPumpTargetFlowRateDelayed function sets a new target flow rate for the + * RO pump to be set after given delay. + * @details Inputs: none + * @details Outputs: pendingROPumpCmdMaxPressure, pendingROPumpCmdTargetFlow, + * pendingROPumpCmdCountDown + * @param roFlowRate which is target RO flow rate + * @param maxPressure which is the maximum allowed pressure that the RO pump + * can reach + * @param delayMs delay duration (in ms) before RO pump started + * @return TRUE if new target flow rate is set successfully, FALSE if not + *************************************************************************/ +BOOL setROPumpTargetFlowRateDelayed( F32 roFlowRate, U32 maxPressure, U32 delayMs ) +{ + BOOL result = FALSE; + + // First of all, the flow rate must be in range + if ( ( roFlowRate <= MAX_RO_FLOWRATE_LPM ) && ( roFlowRate >= MIN_RO_FLOWRATE_LPM ) ) + { + // Then the max pressure that we are allowed to reach must be in range + if ( ( maxPressure >= MIN_ALLOWED_PRESSURE_PSI ) && ( maxPressure <= MAX_ALLOWED_PRESSURE_PSI ) ) + { + pendingROPumpCmdMaxPressure = (F32)maxPressure; + pendingROPumpCmdTargetFlow = roFlowRate; + pendingROPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; + result = TRUE; + } + // Requested max pressure is out of range + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, maxPressure ) + } + } + // Requested flow rate is out of range + else + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, roFlowRate ) + } + + return result; +} + +/*********************************************************************//** + * @brief * The signalROPumpHardStop function stops the RO pump immediately and * resets all the variables associated with the RO pump run. * @details Inputs: targetROPumpFlowRate, roPumpState, roPumpPWMDutyCyclePct, @@ -350,6 +398,26 @@ *************************************************************************/ void execROPumpController( void ) { + // Handle pending delayed RO pump command + if ( pendingROPumpCmdCountDown > 0 ) + { + pendingROPumpCmdCountDown--; + if ( 0 == pendingROPumpCmdCountDown ) + { + targetROPumpMaxPressure = pendingROPumpCmdMaxPressure; + targetROPumpFlowRate = pendingROPumpCmdTargetFlow; + pendingROPumpCmdMaxPressure = 0.0; + pendingROPumpCmdTargetFlow = 0.0; + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + roPumpState = RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE; + // Get the initial guess of the duty cycle + roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( targetROPumpFlowRate ); + roControlTimerCounter = 0; + isROPumpOn = TRUE; + } + } + + // Execute RO pump control state machine switch ( roPumpState ) { case RO_PUMP_OFF_STATE: @@ -381,13 +449,13 @@ /*********************************************************************//** * @brief - * The isReverseOsmosisPumpOn function returns the on/off status of RO pump. + * The isROPumpRunning function returns the on/off status of RO pump. * @details Inputs: isROPumpOn * @details Outputs: none * @return isROPumpOn the boolean flag that is TRUE if the pump is on and * FALSE if it is off *************************************************************************/ -BOOL isReverseOsmosisPumpOn( void ) +BOOL isROPumpRunning( void ) { return isROPumpOn; } Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -r8467f8ff09e382e0991f14d02683080dc811e24e -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 8467f8ff09e382e0991f14d02683080dc811e24e) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -51,10 +51,11 @@ void execROPumpController( void ); BOOL setROPumpTargetFlowRate( F32 roFlowRate, U32 maxPressure ); +BOOL setROPumpTargetFlowRateDelayed( F32 roFlowRate, U32 maxPressure, U32 delayMs ); void signalROPumpHardStop( void ); -BOOL isReverseOsmosisPumpOn( void ); +BOOL isROPumpRunning( void ); F32 getTargetROPumpFlowRate( void ); F32 getMeasuredROFlowRate( void ); Index: firmware/App/DGCommon.h =================================================================== diff -u -rbd8fa3f754c8a8fd797d1828c416f73680924b64 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision bd8fa3f754c8a8fd797d1828c416f73680924b64) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -37,8 +37,8 @@ // #define SIMULATE_UI 1 // #define TASK_TIMING_OUTPUT_ENABLED 1 // re-purposes drain pump enable pin for task timing // #define DISABLE_HEATERS_AND_TEMPS 1 - #define DISABLE_ACCELS 1 - #define SKIP_POST 1 +// #define DISABLE_ACCELS 1 +// #define SKIP_POST 1 #define DISABLE_CAL_CHECK 1 // #define ENABLE_DIP_SWITCHES 1 // #define EMC_TEST_BUILD 1 @@ -50,7 +50,7 @@ #define IGNORE_HEATERS_MONITOR 1 #define IGNORE_RO_PUMP_MONITOR 1 #define IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT 1 - #define DISABLE_RO_RATIO_CHECK 1 +// #define DISABLE_RO_RATIO_CHECK 1 #define DISABLE_COND_SENSOR_CHECK 1 #define DISABLE_MIXING 1 // #define DISABLE_WATER_QUALITY_CHECK 1 Index: firmware/App/Drivers/InternalADC.c =================================================================== diff -u -r08e11fb11f818dd326617362ca7361b2fae1662a -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Drivers/InternalADC.c (.../InternalADC.c) (revision 08e11fb11f818dd326617362ca7361b2fae1662a) +++ firmware/App/Drivers/InternalADC.c (.../InternalADC.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -164,14 +164,21 @@ { // process readings from last conversion for ( i = 0; i < adcRawReadingsCount; i++ ) - { - U32 ch = adcChannelNum2ChannelId[ adcRawReadings[ i ].id ]; // TODO - need to range check .id? + { + if ( adcRawReadings[ i ].id < NUM_OF_INT_ADC_CHANNELS ) + { + U32 ch = adcChannelNum2ChannelId[ adcRawReadings[ i ].id ]; - adcReadingsTotals[ ch ] -= adcReadings[ ch ][ adcReadingsIdx[ ch ] ]; - adcReadings[ ch ][ adcReadingsIdx[ ch ] ] = adcRawReadings[i].value; - adcReadingsTotals[ ch ] += adcRawReadings[ i ].value; - adcReadingsAvgs[ ch ] = adcReadingsTotals[ ch ] >> ROLLING_AVG_SHIFT_DIVIDER; - adcReadingsIdx[ ch ] = INC_WRAP( adcReadingsIdx[ ch ], 0, SIZE_OF_ROLLING_AVG - 1 ); + adcReadingsTotals[ ch ] -= adcReadings[ ch ][ adcReadingsIdx[ ch ] ]; + adcReadings[ ch ][ adcReadingsIdx[ ch ] ] = adcRawReadings[i].value; + adcReadingsTotals[ ch ] += adcRawReadings[ i ].value; + adcReadingsAvgs[ ch ] = adcReadingsTotals[ ch ] >> ROLLING_AVG_SHIFT_DIVIDER; + adcReadingsIdx[ ch ] = INC_WRAP( adcReadingsIdx[ ch ], 0, SIZE_OF_ROLLING_AVG - 1 ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_INT_ADC_CHANNEL_NUMBER, adcRawReadings[ i ].id ) + } } } else Index: firmware/App/Modes/ModeFault.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -21,6 +21,7 @@ #include "ModeFault.h" #include "OperationModes.h" #include "ROPump.h" +#include "SystemCommMessages.h" #include "UVReactors.h" #include "Valves.h" @@ -59,6 +60,13 @@ void transitionToFaultMode( void ) { deenergizeActuators(); + + // Publish POST failure status to UI if fault triggered in Init/POST mode + if ( DG_MODE_INIT == getPreviousOperationMode() ) + { + // Broadcast final POST failed + sendPOSTFinalResult( FALSE ); + } } /*********************************************************************//** @@ -115,7 +123,7 @@ setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -376,15 +376,15 @@ { // Set the actuators to flush drain setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); state = DG_FLUSH_STATE_FLUSH_DRAIN; } else { // Set the actuators to pull fresh water in to drain the circulation line setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setROPumpTargetFlowRate( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); @@ -416,7 +416,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); // Turn on the UV reactors @@ -664,7 +664,7 @@ { // Set the actuators to transition to flush circulation // The valves are set to do flush drain and flush circulation - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); @@ -699,7 +699,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_CIRCULATION_WAIT_TIME_MS ) ) { - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); @@ -776,7 +776,7 @@ // Set the actuators setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); // Set both reservoirs to be considered as full rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -420,8 +420,13 @@ setValveState( VPI, VALVE_STATE_CLOSED ); // Request a tare for reservoir 1 tareReservoir(); +#ifndef V_2_SYSTEM // Set the actuators to drain R1 + setValveState( VRD1, VALVE_STATE_OPEN ); +#else + // Set the actuators to drain R1 setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); rsrvrFillStableTimeCounter = 0; @@ -460,7 +465,12 @@ // Set the valves to flush the recirculation line setValveState( VPI, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -480,9 +490,17 @@ rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; // Request a tare for reservoir 2 tareReservoir(); +#ifndef V_2_SYSTEM + // Done with draining R1, close it + setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2. // NOTE: Drain pump is already on and VDr is already on drain state + setValveState( VRD2, VALVE_STATE_OPEN ); +#else + // Set the actuators to drain R2. + // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; } @@ -521,13 +539,22 @@ { if ( TRUE == isThisLastDrain ) { +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; } else { signalDrainPumpHardStop(); +#ifndef V_2_SYSTEM + // Done with draining R2, close it + setValveState( VRD2, VALVE_STATE_CLOSED ); +#endif setValveState( VPI, VALVE_STATE_OPEN ); stateTrialCounter = 0; stateTimer = getMSTimerCount(); @@ -567,7 +594,11 @@ if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) { +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); stateTimer = getMSTimerCount(); stateTrialCounter = 0; @@ -714,7 +745,11 @@ setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); +#else setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); stateTimer = getMSTimerCount(); @@ -764,6 +799,10 @@ { // Done with draining R1 signalDrainPumpHardStop(); +#ifndef V_2_SYSTEM + // Close VRD1 + setValveState( VRD1, VALVE_STATE_CLOSED ); +#endif } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -804,10 +843,18 @@ // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); +#ifndef V_2_SYSTEM + setValveState( VRD2, VALVE_STATE_OPEN ); +#else setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); // Start the timer for drain timeout stateTimer = getMSTimerCount(); @@ -851,7 +898,12 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif // Start the timer for drain timeout stateTimer = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; @@ -893,12 +945,21 @@ // Prepare for filling the reservoirs and heating the water setValveState( VPI, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); +#else setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif // Turn on the RO pump setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); @@ -957,7 +1018,11 @@ // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); +#else setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); +#endif setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); @@ -1025,7 +1090,12 @@ //TODO turn off CP1 and CP2 // Set the valves to transfer hot water from R1 to R2 and fill up R2. setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); // Although there is fluid in both reservoirs, but they are set to empty @@ -1160,8 +1230,14 @@ // water does not enter the circulation path the membrane is cooling down setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_CLOSED ); +#else setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); +#endif + stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; } @@ -1223,6 +1299,9 @@ if ( ( TRUE == didTimeout( stateTimer, DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ) ) && ( isDrainPumpInMixDrainOn == FALSE ) ) { isDrainPumpInMixDrainOn = TRUE; +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); +#endif // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); @@ -1235,8 +1314,15 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { +#ifndef V_2_SYSTEM + // Done with draining reservoir 1 + setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the drain valve to reservoir 2 + setValveState( VRD2, VALVE_STATE_OPEN ); +#else + // Set the drain valve to reservoir 2 setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; stateTimer = getMSTimerCount(); @@ -1245,7 +1331,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } } @@ -1277,7 +1363,13 @@ // Set the valves to fill up R1 and overflow to R2 setValveState( VPI, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + // Done with draining reservoir 2 + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -1295,7 +1387,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -1328,7 +1420,11 @@ // Set the valves to rinse R2 to R1 and drain R1 setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_R1_C_TO_NC ); +#else setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -1377,6 +1473,9 @@ { // Done with draining R1 signalDrainPumpHardStop(); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_CLOSED ); +#endif } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -1401,10 +1500,18 @@ // De-energize all the valves and set the VDr to drain R2 setValveState( VPI, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); +#ifndef V_2_SYSTEM + setValveState( VRD2, VALVE_STATE_OPEN ); +#else setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -1515,7 +1622,11 @@ { // The fluid is hot so this is a mix drain. Set the VPd to direct the cold inlet fluid to drain setValveState( VPI, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); +#else setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); +#endif targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; cancellationMode = CANCELLATION_MODE_HOT; @@ -1540,8 +1651,13 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { +#ifndef V_2_SYSTEM // Set the drain valve to reservoir 1 + setValveState( VRD1, VALVE_STATE_OPEN ); +#else + // Set the drain valve to reservoir 1 setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); +#endif } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) @@ -1590,6 +1706,45 @@ /*********************************************************************//** * @brief + * The resetActuators function sets all the actuators to reset and + * de-energized state. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void resetActuators( void ) +{ + // UV reactors will not be used in the heat disinfection since their operating temperature + // range is below 85C and they might be damaged by the high temperature. + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + + // De-energize all the valves + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + + //TODO add the composition pumps + signalROPumpHardStop(); + signalDrainPumpHardStop(); + stopPrimaryHeater(); + stopTrimmerHeater(); +} + +/*********************************************************************//** + * @brief * The failHeatDisinfect function sets the alarm that failed the heat * disinfect mode. * @details Inputs: alarm, prevHeatDisinfectState @@ -1752,7 +1907,7 @@ status = HEAT_DISINFECT_HEAT_UP_TIMEOUT; } } - else if ( isPartialDisinfectInProgress != TRUE && ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) + else if ( ( isPartialDisinfectInProgress != TRUE ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) { // The temperature of the coldest spot is in range to start the disinfect timer heatDisinfectTimer = getMSTimerCount(); Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -rb57b5341e4dfe3a7b17cd333bfcfac9036d11e85 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision b57b5341e4dfe3a7b17cd333bfcfac9036d11e85) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -28,6 +28,7 @@ #include "OperationModes.h" #include "Pressures.h" #include "RTC.h" +#include "SystemCommMessages.h" #include "TemperatureSensors.h" #include "Thermistors.h" #include "UVReactors.h" @@ -48,6 +49,7 @@ // ********** private function prototypes ********** static DG_POST_STATE_T handlePOSTStatus( SELF_TEST_STATUS_T testStatus ); +static SELF_TEST_STATUS_T execFWCompatibilityTest( void ); /*********************************************************************//** * @brief @@ -93,7 +95,7 @@ switch ( postState ) { case DG_POST_STATE_START: - postState = DG_POST_STATE_FW_INTEGRITY; + postState = DG_POST_STATE_FW_COMPATIBILITY; #ifdef SKIP_POST postState = DG_POST_STATE_COMPLETED; #endif @@ -103,6 +105,11 @@ #endif break; + case DG_POST_STATE_FW_COMPATIBILITY: + testStatus = execFWCompatibilityTest(); + postState = handlePOSTStatus( testStatus ); + break; + case DG_POST_STATE_FW_INTEGRITY: testStatus = execIntegrityTest(); postState = handlePOSTStatus( testStatus ); @@ -123,11 +130,6 @@ postState = handlePOSTStatus( testStatus ); break; - case DG_POST_STATE_LOAD_CELL: - testStatus = execLoadCellsSelfTest(); - postState = handlePOSTStatus( testStatus ); - break; - case DG_POST_STATE_TEMPERATURE_SENSORS: #ifdef DONT_SKIP_NV_POST // Skip the rest of the POSTs @@ -138,11 +140,6 @@ #endif break; - case DG_POST_STATE_HEATERS: - testStatus = execHeatersSelfTest(); - postState = handlePOSTStatus( testStatus ); - break; - case DG_POST_STATE_ACCELEROMETER: #ifndef DISABLE_ACCELS testStatus = execAccelTest(); @@ -182,6 +179,12 @@ case DG_POST_STATE_WATCHDOG: testStatus = execWatchdogTest(); + postState = handlePOSTStatus( testStatus ); + break; + + // Should be last POST (and last POST test must be a test that completes in a single call) + case DG_POST_STATE_LOAD_CELL: + testStatus = execLoadCellsSelfTest(); handlePOSTStatus( testStatus ); // ignoring return value because last test if ( TRUE == tempPOSTPassed ) { @@ -194,17 +197,23 @@ break; case DG_POST_STATE_COMPLETED: - // set overall DG POST status to "passed" + // Set overall HD POST status to "passed" postPassed = TRUE; - // set overall DG POST completed status to TRUE + // Set overall HD POST completed status to TRUE postCompleted = TRUE; - // TODO - send POST status on CAN - // go to standby mode + // Broadcast final POST passed + sendPOSTFinalResult( TRUE ); + // Go to standby mode requestNewOperationMode( DG_MODE_STAN ); break; case DG_POST_STATE_FAILED: - // Should not get here - any failed post test should have already triggered a fault and taken us to fault mode + // Broadcast final POST failed + sendPOSTFinalResult( FALSE ); + // Will want POST faults to wait for us to get here before sending us to fault mode + requestNewOperationMode( DG_MODE_FAUL ); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_MODE_INIT_POST_INVALID_POST_STATE, postState ) postState = DG_POST_STATE_FAILED; @@ -254,7 +263,12 @@ if ( ( testStatus == SELF_TEST_STATUS_PASSED ) || ( testStatus == SELF_TEST_STATUS_FAILED ) ) { - result = (DG_POST_STATE_T)((int)postState + 1); // move on to next POST test + BOOL passed = ( testStatus == SELF_TEST_STATUS_PASSED ? TRUE : FALSE ); + + // Broadcast passed POST result + sendPOSTTestResult( (DG_POST_STATE_T)((int)postState), passed ); + // Move on to next POST test + result = (DG_POST_STATE_T)((int)postState + 1); if ( testStatus == SELF_TEST_STATUS_FAILED ) { tempPOSTPassed = FALSE; @@ -277,4 +291,20 @@ return postState; } +/*********************************************************************//** + * @brief + * The execFWCompatibilityTest function executes the firmware compatibility test. + * @details Inputs: none + * @details Outputs: none + * @return in progress, passed, or failed + *************************************************************************/ +static SELF_TEST_STATUS_T execFWCompatibilityTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + + // TODO - implement + + return result; +} + /**@}*/ Index: firmware/App/Modes/ModeRecirculate.c =================================================================== diff -u -r8467f8ff09e382e0991f14d02683080dc811e24e -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision 8467f8ff09e382e0991f14d02683080dc811e24e) +++ firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -85,6 +85,9 @@ // set initial actuator states setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#endif setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r64f7d82ff6637d6fb179d31b0c1481d68ed99143 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 64f7d82ff6637d6fb179d31b0c1481d68ed99143) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -101,7 +101,12 @@ // set initial actuator states setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); @@ -185,7 +190,11 @@ flushFilterRequest = FALSE; filterFlushStartTime = getMSTimerCount(); setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); +#else + setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 +#endif state = DG_STANDBY_MODE_STATE_FLUSH_FILTER; } else if ( TRUE == pendingStartDGRequest ) @@ -253,7 +262,11 @@ if ( TRUE == endSampleWaterRequest ) { setValveState( VPI, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); +#else setValveState( VPD, VALVE_STATE_CLOSED ); +#endif state = DG_STANDBY_MODE_STATE_IDLE; } @@ -276,7 +289,11 @@ if ( ( TRUE == stopSampleWaterRequest ) || ( TRUE == didTimeout( waterSampleStartTime, MAX_WATER_SAMPLE_TIME_MS ) ) ) { setValveState( VSP, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); +#else setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 +#endif state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; } Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r90b9d26ec61408366dcc745b583a69414a2271cd -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 90b9d26ec61408366dcc745b583a69414a2271cd) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -121,6 +121,9 @@ SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, // 90 SW_FAULT_ID_INVALID_PRESSURE_SENSOR_ID, SW_FAULT_ID_INVALID_TASK, + SW_FAULT_ID_INVALID_VOLTAGE_MONITOR_STATE, + SW_FAULT_ID_INVALID_MONITORED_VOLTAGE_ID, + SW_FAULT_ID_INVALID_LOAD_CELL_ID, // 95 NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r90b9d26ec61408366dcc745b583a69414a2271cd -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 90b9d26ec61408366dcc745b583a69414a2271cd) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -23,6 +23,7 @@ #include "FPGA.h" #include "Comm.h" +#include "Compatible.h" #include "SystemCommMessages.h" #include "Utilities.h" @@ -106,8 +107,8 @@ U32 fpgaTPiTemp; ///< Reg 292. ADC RTD channel 3 - conductivity sensor CPi temperature U32 fpgaRTDTemp; ///< Reg 296. ADC RTD channel 4 - internal temperature - U32 fpgaTHDo; ///< Reg 300. ADC THDo channel 0 - temperature - U32 fpgaTHDoTemp; ///< Reg 304. ADC THDo channel 1 - internal temperature + U32 fpgaTRo; ///< Reg 300. ADC TRo channel 0 - temperature + U32 fpgaTRoTemp; ///< Reg 304. ADC TRo channel 1 - internal temperature U32 fpgaTDi; ///< Reg 308. ADC TDi channel 0 - temperature U32 fpgaTDiTemp; ///< Reg 312. ADC TDi channel 1 - internal temperature @@ -140,8 +141,8 @@ U08 fpgaADC2ErrorCnt; ///< Reg 357. U08 fpgaRTDReadCnt; ///< Reg 358. Temperature sensors read count U08 fpgaRTDErrorCnt; ///< Reg 359. Temperature sensors error count - U08 fpgaTHDoReadCnt; ///< Reg 360. Redundant outlet temperature sensor read count - U08 fpgaTHDoErrorCnt; ///< Reg 361. Redundant outlet temperature sensor error count + U08 fpgaTRoReadCnt; ///< Reg 360. Redundant outlet temperature sensor read count + U08 fpgaTRoErrorCnt; ///< Reg 361. Redundant outlet temperature sensor error count U08 fpgaTDiReadCnt; ///< Reg 362. Dialysate inlet temperature sensor read count U08 fpgaTDiErrorCnt; ///< Reg 363. Dialysate inlet temperature sensor error count U08 fpgaPrimaryHeaterFlags; ///< Reg 364. Primary heater flags @@ -466,10 +467,15 @@ break; } - // if retries for commands exceeds limit, fault - if ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) + // if retries for commands exceeds limit or FPGA reports comm error, fault + if ( ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) +#ifdef _RELEASE_ + || ( fpgaSensorReadings.fpgaIOErrorCntProcessor > MAX_COMM_ERROR_RETRIES ) ) +#else + ) +#endif { - // TODO - FPGA comm fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_COMM_TIMEOUT, fpgaCommRetryCount, (U32)fpgaSensorReadings.fpgaIOErrorCntProcessor ) } // reset comm flags after processing incoming responses @@ -722,7 +728,23 @@ if ( 1 ) #endif { - result = SELF_TEST_STATUS_PASSED; + // Check FPGA compatibility w/ firmware + if ( fpgaHeader.fpgaRevMajor > MIN_DG_FPGA_MAJOR ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + if ( ( MIN_DG_FPGA_MAJOR == fpgaHeader.fpgaRevMajor ) && ( fpgaHeader.fpgaRevMinor >= MIN_DG_FPGA_MINOR ) ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaRevMajor, (U32)fpgaHeader.fpgaRevMinor ) + } + } } else { @@ -1047,49 +1069,57 @@ /*********************************************************************//** * @brief * The getFPGALoadCellA1 function gets the latest load cell A 1 reading. + * Least significant 24 bits are the reading. Most significant bit indicates + * CRC or status error. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last load cell A 1 reading *************************************************************************/ U32 getFPGALoadCellA1( void ) { - return ( fpgaSensorReadings.fpgaLCA1 & MASK_OFF_U32_MSB ); + return fpgaSensorReadings.fpgaLCA1; } /*********************************************************************//** * @brief * The getFPGALoadCellA2 function gets the latest load cell A 2 reading. + * Least significant 24 bits are the reading. Most significant bit indicates + * CRC or status error. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last load cell A 2 reading *************************************************************************/ U32 getFPGALoadCellA2( void ) { - return ( fpgaSensorReadings.fpgaLCA2 & MASK_OFF_U32_MSB ); + return fpgaSensorReadings.fpgaLCA2; } /*********************************************************************//** * @brief * The getFPGALoadCellB1 function gets the latest load cell B 1 reading. + * Least significant 24 bits are the reading. Most significant bit indicates + * CRC or status error. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last load cell B 1 reading *************************************************************************/ U32 getFPGALoadCellB1( void ) { - return ( fpgaSensorReadings.fpgaLCB1 & MASK_OFF_U32_MSB ); + return fpgaSensorReadings.fpgaLCB1; } /*********************************************************************//** * @brief * The getFPGALoadCellB2 function gets the latest load cell B 2 reading. + * Least significant 24 bits are the reading. Most significant bit indicates + * CRC or status error. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last load cell B 2 reading *************************************************************************/ U32 getFPGALoadCellB2( void ) { - return ( fpgaSensorReadings.fpgaLCB2 & MASK_OFF_U32_MSB ); + return fpgaSensorReadings.fpgaLCB2; } /*********************************************************************//** @@ -1210,37 +1240,37 @@ * @brief * The getFPGATRoTemp function gets the latest redundant sensor outlet * temperature reading in ADC. - * @details Inputs: fpgaSensorReadings.fpgaTHDoTemp + * @details Inputs: fpgaSensorReadings.fpgaTRo * @details Outputs: none * @return Last redundant sensor outlet temperature reading *************************************************************************/ -U32 getFPGATHDoTemp( void ) +U32 getFPGATRoTemp( void ) { - return fpgaSensorReadings.fpgaTHDo; + return fpgaSensorReadings.fpgaTRo; } /*********************************************************************//** * @brief - * The getFPGATHDoErrorCount gets the error count of the THDo (redundant) temperature sensor. - * @details Inputs: fpgaSensorReadings.fpgaTHDoErrorCnt + * The getFPGATRoErrorCount gets the error count of the THDo (redundant) temperature sensor. + * @details Inputs: fpgaSensorReadings.fpgaTRoErrorCnt * @details Outputs: none * @return Last redundant sensor outlet temperature error count *************************************************************************/ -U08 getFPGATHDoErrorCount( void ) +U08 getFPGATRoErrorCount( void ) { - return fpgaSensorReadings.fpgaTHDoErrorCnt; + return fpgaSensorReadings.fpgaTRoErrorCnt; } /*********************************************************************//** * @brief - * The getFPGATHDoReadCount gets the read count of the THDo (redundant) temperature sensor. - * @details Inputs: fpgaSensorReadings.fpgaTHDoReadCnt + * The getFPGATRoReadCount gets the read count of the THDo (redundant) temperature sensor. + * @details Inputs: fpgaSensorReadings.fpgaTRoReadCnt * @details Outputs: none * @return Last redundant sensor outlet temperature error count reading *************************************************************************/ -U08 getFPGATHDoReadCount( void ) +U08 getFPGATRoReadCount( void ) { - return fpgaSensorReadings.fpgaTHDoReadCnt; + return fpgaSensorReadings.fpgaTRoReadCnt; } /*********************************************************************//** @@ -1703,14 +1733,14 @@ /*********************************************************************//** * @brief - * The getFPGATHDoInternalTemp function gets THDo internal temperature reading. + * The getFPGATRoInternalTemp function gets TRo internal temperature reading. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return THDo internal temperature reading in ADC counts + * @return TRo internal temperature reading in ADC counts *************************************************************************/ -U32 getFPGATHDoInternalTemp( void ) +U32 getFPGATRoInternalTemp( void ) { - return fpgaSensorReadings.fpgaTHDoTemp; + return fpgaSensorReadings.fpgaTRoTemp; } /*********************************************************************//** Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r0d46714bc22f87f7027c6e82ad59cef1a01ff69b -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 0d46714bc22f87f7027c6e82ad59cef1a01ff69b) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -68,10 +68,10 @@ U08 getFPGARTDErrorCount( void ); U08 getFPGARTDReadCount( void ); -U32 getFPGATHDoTemp( void ); +U32 getFPGATRoTemp( void ); -U08 getFPGATHDoErrorCount( void ); -U08 getFPGATHDoReadCount( void ); +U08 getFPGATRoErrorCount( void ); +U08 getFPGATRoReadCount( void ); U32 getFPGATDiTemp( void ); @@ -122,7 +122,7 @@ U16 getFPGABoardTemp( void ); U32 getFPGALoadCellsA1B1Temp( void ); U32 getFPGALoadCellsA2B2Temp( void ); -U32 getFPGATHDoInternalTemp( void ); +U32 getFPGATRoInternalTemp( void ); U32 getFPGATDiInternalTemp( void ); U32 getFPGACondSnsrInternalTemp( void ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r64f7d82ff6637d6fb179d31b0c1481d68ed99143 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 64f7d82ff6637d6fb179d31b0c1481d68ed99143) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -1037,10 +1037,6 @@ handleStartStopTrimmerHeaterCmd( message ); break; - case MSG_ID_DG_TESTER_LOGIN_REQUEST: - handleTesterLogInRequest( message ); - break; - case MSG_ID_DG_START_STOP_FLUSH: handleStartStopDGFlush( message ); break; @@ -1049,6 +1045,14 @@ handleStartStopDGHeatDisinfect( message ); break; + case MSG_ID_UI_DG_SET_RTC_REQUEST: + handleUIClockSyncRequest( message ); + break; + + case MSG_ID_DG_TESTER_LOGIN_REQUEST: + handleTesterLogInRequest( message ); + break; + default: // unrecognized message ID received - ok, ignore - may be a test message handled below break; @@ -1151,6 +1155,14 @@ handleTestDGAccelBroadcastIntervalOverrideRequest( message ); break; + case MSG_ID_DG_MONITORED_VOLTAGES_SEND_INTERVAL_OVERRIDE: + handleTestMonitoredVoltagesSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_DG_MONITORED_VOLTAGES_OVERRIDE: + handleTestMonitoredVoltageOverrideRequest( message ); + break; + case MSG_ID_DRAIN_PUMP_SET_DELTA_PRESSURE_OVERRIDE: handleSetDrainPumpDeltaPressureOverrideRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r64f7d82ff6637d6fb179d31b0c1481d68ed99143 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 64f7d82ff6637d6fb179d31b0c1481d68ed99143) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -1025,6 +1025,34 @@ /*********************************************************************//** * @brief + * The broadcastVoltagesData function constructs a monitored voltages data msg to + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: monitored voltages data msg constructed and queued. + * @param data Latest monitored voltage values. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_VOLTAGES_DATA; + msg.hdr.payloadLen = sizeof( VOLTAGES_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( VOLTAGES_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + + /*********************************************************************//** + * @brief * The broadcastFlushData function sends out the flush mode data. * @details Inputs: none * @details Outputs: flush data msg constructed and queued @@ -1169,6 +1197,67 @@ /*********************************************************************//** * @brief + * The sendPOSTTestResult function constructs an DG POST test result message + * and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG POST test result msg constructed and queued. + * @param test ID of DG POST test + * @param passed TRUE if POST test passed, FALSE if not + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendPOSTTestResult( DG_POST_STATE_T test, BOOL passed ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U32 testID = (U32)test; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_POST_SINGLE_TEST_RESULT; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + + memcpy( payloadPtr, &passed, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &testID, sizeof( U32) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; + +} + +/*********************************************************************//** + * @brief + * The sendPOSTFinalResult function constructs an DG POST final result message + * and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: DG POST final result msg constructed and queued. + * @param passed TRUE if DG POST passed, FALSE if not + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendPOSTFinalResult( BOOL passed ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_POST_FINAL_TEST_RESULT; + msg.hdr.payloadLen = sizeof( BOOL ); + + memcpy( payloadPtr, &passed, sizeof( BOOL ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief * The sendCommandResponseMsg function constructs a command response to HD * and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none @@ -2199,6 +2288,70 @@ /*********************************************************************//** * @brief + * The handleTestMonitoredVoltagesSendIntervalOverrideRequest function handles a + * request to override the monitored DG voltages data publication interval. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestMonitoredVoltagesSendIntervalOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof(TEST_OVERRIDE_PAYLOAD_T) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); + if ( FALSE == payload.reset ) + { + result = testSetVoltagesDataPublishIntervalOverride( payload.state.u32 ); + } + else + { + result = testResetVoltagesDataPublishIntervalOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestMonitoredVoltageOverrideRequest function handles a + * request to override the monitored DG voltage override. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestMonitoredVoltageOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify payload length + if ( sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); + if ( FALSE == payload.reset ) + { + result = testSetLineLevelOverride( payload.index, payload.state.f32 ); + } + else + { + result = testResetLineLevelOverride( payload.index ); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief * The handleTestSetConductivityOverrideRequest function handles a * request to override a conductivity sensor's value * @details Inputs: none @@ -2813,6 +2966,51 @@ } /*********************************************************************//** + * @brief + * The handleUIClockSyncRequest function handles a UI clock sync message. + * @details Inputs: none + * @details Outputs: message handled, response constructed and queued for transmit. + * @param messagePtr pointer to the message to handle. + * @return none + *************************************************************************/ +void handleUIClockSyncRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + U32 rejReason = REQUEST_REJECT_REASON_NONE; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + if ( message->hdr.payloadLen == sizeof( U32 ) ) + { + U32 epoch; + + memcpy( &epoch, message->payload, sizeof( U32 ) ); + result = setRTCEpoch( epoch ); + if ( FALSE == result ) + { + rejReason = REQUEST_REJECT_REASON_INVALID_DATE_OR_TIME; + } + } + else + { + rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } + + // Create a response message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_UI_SET_RTC_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ); + memcpy( payloadPtr, &result, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_2_UI, ACK_REQUIRED ); + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_UI, result ); +} + +/*********************************************************************//** * @brief * The handleSetDGCalibrationRecord function handles a request to set the DG * calibration data record. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r64f7d82ff6637d6fb179d31b0c1481d68ed99143 -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 64f7d82ff6637d6fb179d31b0c1481d68ed99143) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) @@ -32,6 +32,7 @@ #include "TemperatureSensors.h" #include "Thermistors.h" #include "UVReactors.h" +#include "Voltages.h" /** * @defgroup SystemCommMessages SystemCommMessages @@ -111,6 +112,9 @@ // MSG_ID_DG_FLUID_LEAK_STATE BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state); +// MSG_ID_DG_VOLTAGES_DATA +BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ); + // MSG_ID_DG_FLUSH_DATA BOOL broadcastFlushData( MODE_FLUSH_DATA_T *flushData ); @@ -171,6 +175,12 @@ // MSG_ID_DG_SEND_SCHEDULED_RUNS_RECORD BOOL sendDGScheduledRunsRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* scheduledRcrdAddress ); +// MSG_ID_DG_POST_SINGLE_TEST_RESULT +BOOL sendPOSTTestResult( DG_POST_STATE_T test, BOOL passed ); + +// MSG_ID_DG_POST_FINAL_TEST_RESULT +BOOL sendPOSTFinalResult( BOOL passed ); + // *********** public test support message functions ********** #ifdef DEBUG_ENABLED @@ -254,6 +264,12 @@ // MSG_ID_DG_ACCEL_SEND_INTERVAL_OVERRIDE: void handleTestDGAccelBroadcastIntervalOverrideRequest( MESSAGE_T *message ); +// MSG_ID_DG_MONITORED_VOLTAGES_SEND_INTERVAL_OVERRIDE +void handleTestMonitoredVoltagesSendIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DG_MONITORED_VOLTAGES_OVERRIDE +void handleTestMonitoredVoltageOverrideRequest( MESSAGE_T *message ); + // MSG_ID_DG_START_STOP_INLET_UV_REACTOR void handleStartStopUVReactors( MESSAGE_T *message ); @@ -311,6 +327,9 @@ // MSG_ID_DG_START_STOP_HEAT_DISINFECT BOOL handleStartStopDGHeatDisinfect( MESSAGE_T *message ); +// MSG_ID_UI_DG_SET_RTC_REQUEST +void handleUIClockSyncRequest( MESSAGE_T *message ); + // MSG_ID_DG_SET_CALIBRATION_DATA void handleSetDGCalibrationRecord( MESSAGE_T *message );