Index: firmware/.launches/DG.launch =================================================================== diff -u -rf3aae110ab3efde68897d0224f799dc039ac84f5 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/.launches/DG.launch (.../DG.launch) (revision f3aae110ab3efde68897d0224f799dc039ac84f5) +++ firmware/.launches/DG.launch (.../DG.launch) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -1,5 +1,11 @@ + + + + + + @@ -17,4 +23,5 @@ + Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r5adaa0ae1236d34fca1fc8def7fa107ec470115e -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 5adaa0ae1236d34fca1fc8def7fa107ec470115e) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -14,6 +14,7 @@ * @date (original) 13-Jul-2020 * ***************************************************************************/ +#include // Used for calculating the polynomial calibration equation. #include "ConductivitySensors.h" #include "FPGA.h" @@ -106,17 +107,20 @@ static BOOL packageStarted = FALSE; ///< Flag to indicate the start of a package measurement data. static U08 packageIndex = 0U; ///< Current package measurement data bytes index. static U08 package[ 50 ]; ///< Storage of package bytes until ready to process. +static DG_COND_SENSORS_CAL_RECORD_T condSensorsCalRecord; ///< Conductivity sensors' calibration record. // ********** private function prototypes ********** -static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature); +static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ); static void calcRORejectionRatio( void ); static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); static U32 prefixStrToSIFactor( U08 prefix ); static void processMeasurementDataPackage( U32 sensorId ); static void processCD1CD2SensorRead( U16 fpgaReadCount, U08 fpgaErrorCount ); static U32 getConductivityDataPublishInterval( void ); +static BOOL processCalibrationData( void ); +static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ); /*********************************************************************//** * @brief @@ -155,11 +159,19 @@ * The execConductivitySensors function gets conductivity sensors' latest * readings from FPGA and advertises them over CAN. * @details Inputs: none - * @details Outputs: Conductivity sensors' latest reading is updated and advertised. + * @details Outputs: Conductivity sensors' latest reading is updated and + * advertised. * @return none *************************************************************************/ void execConductivitySensors( void ) { + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + } + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); processCD1CD2SensorRead( getFPGAEmstatRxFifoCount(), getFPGAEmstatRxErrCount() ); @@ -179,7 +191,32 @@ broadcastConductivityData( &data ); } +} +/*********************************************************************//** + * @brief + * The execConductivitySensorsSelfTest function executes the conductivity + * sensors' self-test. + * @details Inputs: none + * @details Outputs: none + * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execConductivitySensorsSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + BOOL calStatus = processCalibrationData(); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + + return result; } /*********************************************************************//** @@ -264,7 +301,8 @@ BOOL isDialysateConductivityInRange( void ) { F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL const isConductivityInRange = isAcidConductivityInRange() && ( MIN_DIALYSATE_CONDUCTIVITY <= bicarbConductivity ) && ( bicarbConductivity <= MAX_DIALYSATE_CONDUCTIVITY ); + BOOL const isConductivityInRange = isAcidConductivityInRange() && ( MIN_DIALYSATE_CONDUCTIVITY <= bicarbConductivity ) && + ( bicarbConductivity <= MAX_DIALYSATE_CONDUCTIVITY ); return isConductivityInRange; } @@ -357,15 +395,17 @@ *************************************************************************/ static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) { - if ( ( fpgaErrorCount == 0 ) && ( fpgaSensorFault == 0 ) ) + if ( ( 0 == fpgaErrorCount ) && ( 0 == fpgaSensorFault ) ) { if ( ( readCount[ sensorId ] != fpgaReadCount ) ) { F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); F32 const conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); + F32 const compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + readCount[ sensorId ] = fpgaReadCount; internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = calcCompensatedConductivity( conductivity, temperature ); + compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); } else { @@ -439,9 +479,10 @@ F32 const resistance = ( ( F32 )( hexStrToDec( measurementPtr->value, sizeof( measurementPtr->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); F32 const conductivity = ( 1 / resistance * SIEMENS_TO_MICROSIEMENS_CONVERSION ); + F32 const compensatedCond = calcCompensatedConductivity( conductivity, temperature ); internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = calcCompensatedConductivity( conductivity, temperature ); + compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); } else { @@ -537,7 +578,69 @@ return result; } +/*********************************************************************//** + * @brief + * The processCalibrationData function gets the calibration data and makes + * sure it is valid by checking the calibration date. The calibration date + * should not be 0. + * @details Inputs: none + * @details Outputs: condSensorsCalRecord + * @return TRUE if the calibration record is valid, otherwise FALSE + *************************************************************************/ +static BOOL processCalibrationData( void ) +{ + BOOL status = TRUE; + U32 sensor; + // Get the calibration record from NVDataMgmt + DG_COND_SENSORS_CAL_RECORD_T calData = getDGConducitivitySensorsCalibrationRecord(); + + for ( sensor = 0; sensor < NUM_OF_CAL_DATA_COND_SENSORS; sensor++ ) + { +#ifndef SKIP_CAL_CHECK + // Check if the calibration data that was received from NVDataMgmt is legitimate + // The calibration date item should not be zero. If the calibration date is 0, + // then the data is not stored in the NV memory or it was corrupted. + if ( 0 == calData.condSensors[ sensor ].calibrationTime ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD, (U32)sensor ); + status = FALSE; + } +#endif + + // The calibration data was valid, update the local copy + condSensorsCalRecord.condSensors[ sensor ].fourthOrderCoeff = calData.condSensors[ sensor ].fourthOrderCoeff; + condSensorsCalRecord.condSensors[ sensor ].thirdOrderCoeff = calData.condSensors[ sensor ].thirdOrderCoeff; + condSensorsCalRecord.condSensors[ sensor ].secondOrderCoeff = calData.condSensors[ sensor ].secondOrderCoeff; + condSensorsCalRecord.condSensors[ sensor ].gain = calData.condSensors[ sensor ].gain; + condSensorsCalRecord.condSensors[ sensor ].offset = calData.condSensors[ sensor ].offset; + } + + return status; +} + +/*********************************************************************//** + * @brief + * The getCalibrationAppliedConductivityValue function gets the temperature + * compensated conductivity value and applies calibration to it. + * @details Inputs: condSensorsCalRecord + * @details Outputs: none + * @param sensorId which is the conductivity sensor ID + * @param compensatedValue which is the temperature compensated conductivity + * value of the conductivity sensor + * @return the calibration applied conductivity value + *************************************************************************/ +static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ) +{ + F32 conductivity = pow(compensatedValue, 4) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].fourthOrderCoeff + + pow(compensatedValue, 3) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].thirdOrderCoeff + + pow(compensatedValue, 2) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].secondOrderCoeff + + compensatedValue * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].gain + + condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].offset; + return conductivity; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -32,9 +32,11 @@ #define FANS_SELF_TEST_WAIT_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans self test wait time for the fans to get to RPM. #define FANS_SELF_TEST_TARGET_PWM 0.5 ///< Fans self test target PWM for testing the fans are running. #define FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ( 3 * MS_PER_SECOND ) ///< Fans max allowed RPM out of range time interval. -#define FANS_MAX_ALLOWED_RPM 5000 ///< Fans max allowed RPM value. +#define FANS_MAX_ALLOWED_RPM 5500 ///< Fans max allowed RPM value. #define FANS_MIN_ALLOWED_RPM 150 ///< Fans max allowed RPM value. #define FANS_MONITOR_INTERVAL_COUNT ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Fans monitor time interval in counts. +#define FANS_MIN_RPM_OUT_OF_RANGE_TOL 0.25 ///< Fans min RPM out of range tolerance. +#define FANS_MAX_RPM_OUT_OF_RANGE_TOL 0.5 ///< Fans max RPM out of range tolerance. /// Fans self test states typedef enum fans_Self_Test @@ -61,12 +63,11 @@ } FAN_STATUS_T; static FAN_STATUS_T fansStatus; ///< Fans status. -static SELF_TEST_STATUS_T fansSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; ///< Fans self test result. -static FANS_SELF_TEST_STATES_T fansSelfTestState = FANS_SELF_TEST_START_STATE; ///< Fans self test state. static FANS_EXEC_STATES_T fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; ///< Fans exec state. static U32 fansControlCounter = 0; ///< Fans control interval counter. static U32 fansPublishCounter = 0; ///< Fans data publish interval counter. static U32 fansMonitorCounter = 0; ///< Fans monitor interval counter. +static BOOL isPOSTComplete = FALSE; ///< Flag that indicates whether POST is complete or not. /// Temperature to duty cycle conversion slope (duty cycle not in percent) static const F32 SLOPE = ( FANS_MAX_DUTY_CYCLE - FANS_MIN_DUTY_CYCLE ) / ( MAX_ALLOWED_AMBINET_TEMPERATURE - MIN_ALLOWED_AMBIENT_TEMPERATURE ); @@ -76,9 +77,6 @@ static OVERRIDE_U32_T fansPublishInterval = { FANS_DATA_PUBLISH_INTERVAL, FANS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Fans publish time interval override -static FANS_SELF_TEST_STATES_T handleSelfTestStart( void ); -static FANS_SELF_TEST_STATES_T handleSelfTestCheckRPM( void ); - static FANS_EXEC_STATES_T handleExecStateWaitForPOST( void ); static FANS_EXEC_STATES_T handleExecStateRun( void ); @@ -93,22 +91,20 @@ /*********************************************************************//** * @brief * The initFans function initializes the fans module. - * @details Inputs: fansExecState, fansSelfTestReslt, fansSelfTestState, - * fansStatus, fansControlCounter, fansPublishCounter - * @details Outputs: fansExecState, fansSelfTestReslt, fansSelfTestState, - * fansStatus, fansControlCounter, fansPublishCounter + * @details Inputs: fansExecState, fansStatus, fansControlCounter, + * fansPublishCounter + * @details Outputs: fansExecState, fansStatus, fansControlCounter, + * fansPublishCounter * @return none *************************************************************************/ void initFans( void ) { // Initialize the variables fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; - fansSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - fansSelfTestState = FANS_SELF_TEST_START_STATE; - fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; fansControlCounter = 0; fansPublishCounter = 0; fansMonitorCounter = 0; + isPOSTComplete = FALSE; // Initialize a persistent alarm for fans RPM out of range initPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ); @@ -117,34 +113,21 @@ /*********************************************************************//** * @brief * The execFansSelfTest function executes the fans self test. - * @details Inputs: fansSelfTestState, fansSelfTestReslt - * @details Outputs: fansSelfTestState, fansSelfTestReslt + * @details Inputs: none + * @details Outputs: isPOSTComplete * @return Status of self test *************************************************************************/ SELF_TEST_STATUS_T execFansSelfTest( void ) { - switch ( fansSelfTestState ) - { - case FANS_SELF_TEST_START_STATE: - fansSelfTestState = handleSelfTestStart(); - break; + SELF_TEST_STATUS_T status = SELF_TEST_STATUS_IN_PROGRESS; - case FANS_SELF_TEST_CHECK_RPM_STATE: - fansSelfTestState = handleSelfTestCheckRPM(); - break; + // TODO implement the calibration processing function. + // It returns a pass for now - case FAN_SELF_TEST_COMPLETE_STATE: - // Done with POST. Do nothing - break; + isPOSTComplete = TRUE; + status = SELF_TEST_STATUS_PASSED; - default: - // Wrong state called - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_FAN_INVALID_SELF_TEST_STATE, fansSelfTestState ); - fansSelfTestState = FAN_SELF_TEST_COMPLETE_STATE; - break; - } - - return fansSelfTestResult; + return status; } /*********************************************************************//** @@ -157,7 +140,7 @@ void execFans( void ) { // Monitor the fans - monitorFans(); + //monitorFans(); TODO uncomment. this is to investigate why the fans RPM are out of range switch ( fansExecState ) { @@ -205,69 +188,6 @@ /*********************************************************************//** * @brief - * The handleSelfTestStart function handles the start state of the fans' - * self test. - * @details Inputs: none - * @details Outputs: none - * @return next state of self test - *************************************************************************/ -static FANS_SELF_TEST_STATES_T handleSelfTestStart( void ) -{ - FANS_SELF_TEST_STATES_T state = FANS_SELF_TEST_CHECK_RPM_STATE; - - // Set the fans to the target PWM for the next stage - setInletFansDutyCycle( FANS_SELF_TEST_TARGET_PWM ); - setOutletFansDutyCycle( FANS_SELF_TEST_TARGET_PWM ); - state = FANS_SELF_TEST_CHECK_RPM_STATE; - - return state; -} - -/*********************************************************************//** - * @brief - * The handleSelfTestCheckRPM function handles the check RPM state of the - * fans' self test. - * @details Inputs: fansStatus - * @details Outputs: none - * @return next state of self test - *************************************************************************/ -static FANS_SELF_TEST_STATES_T handleSelfTestCheckRPM( void ) -{ - FANS_SELF_TEST_STATES_T state = FANS_SELF_TEST_CHECK_RPM_STATE; - - FAN_NAMES_T fan; - - // Wait for the fans to run for a certain period of time before checking their RPM - if ( ++fansControlCounter > FANS_SELF_TEST_WAIT_INTERVAL ) - { - // Assuming the test will pass - fansSelfTestResult = SELF_TEST_STATUS_PASSED; - - convertTogglePeriod2RPM(); - - // Loop through all the fans to check their RPM. They should be above the specified RPM - for( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) - { - if ( fansStatus.rpm[ fan ] < MIN_TARGET_RPM_IN_SELF_TEST ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, fan, fansStatus.rpm[ fan ] ); - - fansSelfTestResult = SELF_TEST_STATUS_FAILED; - } - } - - // Turn off the fans, done with self test - setInletFansDutyCycle( 0.0 ); - setOutletFansDutyCycle( 0.0 ); - - state = FAN_SELF_TEST_COMPLETE_STATE; - } - - return state; -} - -/*********************************************************************//** - * @brief * The handleFansExecStateStart function handles the start state of the * fans exec state machine. * @details Inputs: none @@ -279,7 +199,7 @@ FANS_EXEC_STATES_T state = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; // Wait for the self test to finish before starting the fans - if ( fansSelfTestState == FAN_SELF_TEST_COMPLETE_STATE ) + if ( TRUE == isPOSTComplete ) { // Start the fans with minimum PWM. The control will decide the next PWM automatically. setInletFansDutyCycle( FANS_MIN_DUTY_CYCLE ); @@ -313,10 +233,6 @@ // Get the maximum temperature among all the thermistors and temperature sensors to run fan from the hottest temperature F32 temperature = getMaximumTemperature(); - //TODO REMOVE FOR TESTING - temperature = getThermistorTemperatureValue( THERMISTOR_ONBOARD_NTC ); - //TODO REMOVE FOR TESTING only - // Solve the linear equation to calculate the duty cycle from temperature F32 dutyCycle = ( SLOPE * ( temperature - MIN_ALLOWED_AMBIENT_TEMPERATURE ) ) + FANS_MIN_DUTY_CYCLE; @@ -477,11 +393,18 @@ if ( ++fansMonitorCounter >= FANS_MONITOR_INTERVAL_COUNT ) { + // The RPM is expected to be 5500 @ 100% duty cycle + // The nominal RPM = duty cycle * 5500 / 1.0 + // The RPM tolerance is -25% to +50% of the nominal RPM + F32 fansNominalRPM = fansStatus.targetDutyCycle * FANS_MAX_ALLOWED_RPM; + F32 fansMinAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MIN_RPM_OUT_OF_RANGE_TOL ); + F32 fansMaxAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MAX_RPM_OUT_OF_RANGE_TOL ); + convertTogglePeriod2RPM(); for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) { - BOOL const fanRpmOutOfRange = ( fansStatus.rpm[ fan ] >= FANS_MAX_ALLOWED_RPM ) || ( fansStatus.rpm[ fan ] <= FANS_MIN_ALLOWED_RPM ); + BOOL const fanRpmOutOfRange = ( fansStatus.rpm[ fan ] < fansMinAllowedRPM ) || ( fansStatus.rpm[ fan ] > fansMaxAllowedRPM ); checkPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, fanRpmOutOfRange, fansStatus.rpm[ fan ], FANS_MAX_ALLOWED_RPM ); } Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r97e0100921ccad633b39b509a93a7237e4d80446 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 97e0100921ccad633b39b509a93a7237e4d80446) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -890,7 +890,7 @@ { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { U32 interval = value / TASK_PRIORITY_INTERVAL; @@ -914,7 +914,7 @@ { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { result = TRUE; heatersDataPublishInterval.override = OVERRIDE_RESET; Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -21,9 +21,10 @@ #include "mibspi.h" #include "FPGA.h" +#include "NVDataMgmt.h" #include "OperationModes.h" -#include "PIControllers.h" #include "PersistentAlarm.h" +#include "PIControllers.h" #include "Pressures.h" #include "ROPump.h" #include "SafetyShutdown.h" @@ -131,6 +132,7 @@ static S32 measuredFlowReadingsSum = 0; ///< Raw flow reading sums for averaging. static U32 flowFilterCounter = 0; ///< Flow filtering counter. +static DG_FLOW_SENSORS_CAL_RECORD_T flowSensorsCalRecord; ///< Flow sensors calibration record. // ********** private function prototypes ********** @@ -145,6 +147,7 @@ static void stopROPump( void ); static void publishROPumpData( void ); static U32 getPublishROPumpDataInterval( void ); +static BOOL processCalibrationData( void ); /*********************************************************************//** * @brief @@ -331,20 +334,38 @@ BOOL isPressureMax = actualPressure >= MAX_ALLOWED_MEASURED_PRESSURE_PSI; checkPersistentAlarm( ALARM_ID_RO_PUMP_PRESSURE_OUT_OF_RANGE, isPressureMax, actualPressure, MAX_ALLOWED_MEASURED_PRESSURE_PSI ); + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + } + // Read flow at the control set if ( ++flowFilterCounter >= FLOW_SAMPLES_TO_AVERAGE ) { - F32 avgROFlow = (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER; + U32 sensor; + F32 flow = RO_FLOW_ADC_TO_LPM_FACTOR / ( (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER ); + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that // the flow is 0. Otherwise, convert the count to flow rate in mL/min - if ( ( roFlowReading == FLOW_SENSOR_ZERO_READING ) || ( roFlowReading == 0 ) ) + if ( ( FLOW_SENSOR_ZERO_READING == roFlowReading ) || ( 0 == roFlowReading ) ) { measuredROFlowRateLPM.data = 0.0; } else { - measuredROFlowRateLPM.data = RO_FLOW_ADC_TO_LPM_FACTOR / avgROFlow; + // Right now there is only one flow sensor but a for loop is used here to be able to automatically accommodate + // the future flow sensors + for( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) + { + measuredROFlowRateLPM.data = pow(flow, 4) * flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff + + pow(flow, 3) * flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff + + pow(flow, 2) * flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff + + flow * flowSensorsCalRecord.flowSensors[ sensor ].gain + + flowSensorsCalRecord.flowSensors[ sensor ].offset; + } } measuredFlowReadingsSum = 0; @@ -368,7 +389,6 @@ checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_UPPER_RANGE, isFlowOutOfUpperRange, currentFlow, targetFlow ); checkPersistentAlarm( ALARM_ID_FLOW_RATE_OUT_OF_LOWER_RANGE, isFlowOutOfLowerRange, currentFlow, targetFlow ); } -#endif // If the pump is off and PPi + 5psi < PPo for a certain period of time, activate safety shutdown if ( FALSE == isROPumpOn ) @@ -384,6 +404,7 @@ activateSafetyShutdown(); } } +#endif // Publish RO pump data on interval publishROPumpData(); @@ -449,6 +470,31 @@ /*********************************************************************//** * @brief + * The execROPumpSelfTest function executes the RO pump's self-test. + * @details Inputs: none + * @details Outputs: none + * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execROPumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + BOOL calStatus = processCalibrationData(); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + + return result; +} + +/*********************************************************************//** + * @brief * The isROPumpRunning function returns the on/off status of RO pump. * @details Inputs: isROPumpOn * @details Outputs: none @@ -462,6 +508,51 @@ /*********************************************************************//** * @brief + * The getTargetROPumpFlowRate function gets the current target RO pump + * flow rate. + * @details Inputs: targetROPumpFlowRate + * @details Outputs: targetROPumpFlowRate + * @return the current target RO flow rate (in L/min). + *************************************************************************/ +F32 getTargetROPumpFlowRate( void ) +{ + return targetROPumpFlowRate; +} + +/*********************************************************************//** + * @brief + * The getMeasuredROFlowRate function gets the measured RO pump flow rate. + * @details Inputs: measuredROFlowRateLPM + * @details Outputs: measuredROFlowRateLPM + * @return the current RO pump flow rate (in L/min). + *************************************************************************/ +F32 getMeasuredROFlowRate( void ) +{ + F32 result = measuredROFlowRateLPM.data; + + if ( OVERRIDE_KEY == measuredROFlowRateLPM.override ) + { + result = measuredROFlowRateLPM.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTargetROPumpPressure function gets the current target RO pump + * pressure. + * @details Inputs: targetROPumpPressure + * @details Outputs: targetROPumpPressure + * @return the current target RO targetROPumpPressure in psi. + *************************************************************************/ +F32 getTargetROPumpPressure( void ) +{ + return targetROPumpMaxPressure; +} + +/*********************************************************************//** + * @brief * The handleROPumpOffState function handles the RO pump off state of the * controller state machine. * @details Inputs: roPumpControlMode, roPumpPWMDutyCyclePctSet, @@ -717,51 +808,48 @@ /*********************************************************************//** * @brief - * The getTargetROPumpFlowRate function gets the current target RO pump - * flow rate. - * @details Inputs: targetROPumpFlowRate - * @details Outputs: targetROPumpFlowRate - * @return the current target RO flow rate (in L/min). + * The processCalibrationData function gets the calibration data and makes + * sure it is valid by checking the calibration date. The calibration date + * should not be 0. + * @details Inputs: none + * @details Outputs: flowSensorsCalRecord + * @return TRUE if the calibration record is valid, otherwise FALSE *************************************************************************/ -F32 getTargetROPumpFlowRate( void ) +static BOOL processCalibrationData( void ) { - return targetROPumpFlowRate; -} + BOOL status = TRUE; + U32 sensor; -/*********************************************************************//** - * @brief - * The getMeasuredROFlowRate function gets the measured RO pump flow rate. - * @details Inputs: measuredROFlowRateLPM - * @details Outputs: measuredROFlowRateLPM - * @return the current RO pump flow rate (in L/min). - *************************************************************************/ -F32 getMeasuredROFlowRate( void ) -{ - F32 result = measuredROFlowRateLPM.data; + // Get the calibration record from NVDataMgmt + DG_FLOW_SENSORS_CAL_RECORD_T calData = getDGFlowSensorsCalibrationRecord(); - if ( OVERRIDE_KEY == measuredROFlowRateLPM.override ) + for ( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) { - result = measuredROFlowRateLPM.ovData; +#ifndef SKIP_CAL_CHECK + // Check if the calibration data that was received from NVDataMgmt is legitimate + // The calibration date item should not be zero. If the calibration date is 0, + // then the flow sensors data is not stored in the NV memory or it was corrupted. + if ( 0 == calData.flowSensors[ sensor ].calibrationTime ) + { + + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_FLOW_SENSORS_INVALID_CAL_RECORD, (U32)sensor ); + status = FALSE; + } +#endif + + // The calibration data was valid, update the local copy + flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff = calData.flowSensors[ sensor ].fourthOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff = calData.flowSensors[ sensor ].thirdOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff = calData.flowSensors[ sensor ].secondOrderCoeff; + flowSensorsCalRecord.flowSensors[ sensor ].gain = calData.flowSensors[ sensor ].gain; + flowSensorsCalRecord.flowSensors[ sensor ].offset = calData.flowSensors[ sensor ].offset; } - return result; + return status; } /*********************************************************************//** * @brief - * The getTargetROPumpPressure function gets the current target RO pump - * pressure. - * @details Inputs: targetROPumpPressure - * @details Outputs: targetROPumpPressure - * @return the current target RO targetROPumpPressure in psi. - *************************************************************************/ -F32 getTargetROPumpPressure( void ) -{ - return targetROPumpMaxPressure; -} - -/*********************************************************************//** - * @brief * The publishROPumpData function publishes RO pump data at the set interval. * @details Inputs: roPumpDataPublicationTimerCounter * @details Outputs: roPumpDataPublicationTimerCounter @@ -785,6 +873,7 @@ } } + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -r2fff37fa585181917705645494549b5fd4a4d522 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 2fff37fa585181917705645494549b5fd4a4d522) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -48,7 +48,7 @@ { UV_REACTOR_STATE_T execState; ///< UV reactor executive state PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state - SWITCH_STATES_T switchState; ///< UV reactor turn on/turn off state + UV_REACTOR_STATES_T switchState; ///< UV reactor turn on/turn off state U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1 OVERRIDE_U32_T healthStatus; ///< UV reactor current health status Index: firmware/App/DGCommon.h =================================================================== diff -u -rb93d59e35abc7a815cb108831ffca93635321028 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision b93d59e35abc7a815cb108831ffca93635321028) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -51,7 +51,7 @@ // #define DISABLE_RO_RATIO_CHECK 1 #define DISABLE_COND_SENSOR_CHECK 1 #define DISABLE_MIXING 1 - #define DISABLE_WATER_QUALITY_CHECK 1 +// #define DISABLE_WATER_QUALITY_CHECK 1 #define DISABLE_RTC_CONFIG 1 //#define V_2_SYSTEM 1 #define THD_USING_TRO_CONNECTOR 1 Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r2fff37fa585181917705645494549b5fd4a4d522 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 2fff37fa585181917705645494549b5fd4a4d522) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include "ConcentratePumps.h" #include "DrainPump.h" #include "Heaters.h" #include "LoadCell.h" @@ -39,33 +40,36 @@ // General defines #define FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode flush data publish interval in counts. -#define RO_PUMP_TARGET_FLOW_RATE_LPM 0.8 ///< RO pump target flow rate during flush/fill in L/min. TODO original flow was 0.8 -#define RO_PUMP_MAX_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. -#define DRAIN_PUMP_TARGET_RPM 2200 ///< Drain pump target RPM during drain. +#define RO_PUMP_TARGET_FLOW_RATE_LPM 0.8 ///< RO pump target flow rate during flush/fill in L/min. +#define RO_PUMP_MAX_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. +#define DRAIN_PUMP_TARGET_RPM 2200 ///< Drain pump target RPM during drain. // Drain R1 & R2 states defines -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time is 2 minutes +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. // Flush dialysate state defines #define FLUSH_DIALYSATE_WAIT_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. // Flush concentrate straws state defines -#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. TODO original time is 3 minutes +#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. +#define ACID_PUMP_SPEED_ML_PER_MIN -30.0 ///< Acid pump speed in mL/min. +// The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during flush +#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6 ///< Bicarb pump speed in mL/min. // Flush and drain R1 and R2 state defines -#define RSRVRS_FULL_VOL_ML 1650.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 -#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0 ///< Reservoirs 1 & 2 partial volume in mL. +#define RSRVRS_FULL_VOL_ML 1800.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0 ///< Reservoirs 1 & 2 partial volume in mL. #define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. -#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 minutes +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. #define RSRVRS_PARTIAL_FILL_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. -#define RSRVRS_DRAIN_TIMEOUT_MS ( 3 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. TODO original value was 2 minutes -#define FINAL_DRAIN_RO_PUMP_FLOW_LPM 0.6 ///< Final drain RO pump flow rate in L/min. This is used to flush the drain line during drain. +#define RSRVRS_DRAIN_TIMEOUT_MS ( 3 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. +#define FINAL_DRAIN_RO_PUMP_FLOW_LPM 0.6 ///< Final drain RO pump flow rate in L/min. This is used to flush the drain line during drain. // Flush drain line state defines -#define FLUSH_DRAIN_LINE_VOLUME_L 0.1 ///< Water volume to flush in liters. +#define FLUSH_DRAIN_LINE_VOLUME_L 0.1 ///< Water volume to flush in liters. #define FLUSH_DRAIN_LINE_TIMEOUT_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush drain lines timeout in milliseconds. // Flush circulation state defines @@ -78,6 +82,7 @@ static DG_FLUSH_STATE_T flushState = DG_FLUSH_STATE_START; ///< Current active flush state. static DG_FLUSH_STATE_T prevFlushState = DG_FLUSH_STATE_START; ///< Previous flush state. +static DG_FLUSH_UI_STATE_T flushUIState = FLUSH_UI_STATE_NOT_RUNNING; ///< Current UI flush state. static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. static U32 overallFlushElapsedTimeStart = 0; ///< Overall flush mode elapsed time start. static U32 stateTimerStart = 0; ///< State timer start. @@ -126,6 +131,7 @@ // Initialize the variables flushState = DG_FLUSH_STATE_START; prevFlushState = DG_FLUSH_STATE_START; + flushUIState = FLUSH_UI_STATE_NOT_RUNNING; rsrvrFillStableTimeCounter = 0; overallFlushElapsedTimeStart = 0; isThisInitialDrain = TRUE; @@ -308,6 +314,7 @@ setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; stateTimerStart = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; state = DG_FLUSH_STATE_DRAIN_R1; @@ -409,10 +416,12 @@ #else setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); #endif + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); 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 ); + flushUIState = FLUSH_UI_STATE_FLUSH_RECIRCULATION_PATH; state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; } @@ -474,7 +483,14 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) { - // TODO turn on the concentrate pumps + // Turn the pumps on in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); + + // Turn on the concentrate pumps + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); + stateTimerStart = getMSTimerCount(); state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; @@ -498,14 +514,18 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) { - // TODO turn off the concentrate pumps + // Done with flushing the concentrate pumps line + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); stateTimerStart = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + flushUIState = FLUSH_UI_STATE_FLUSH_RESERVOIRS; state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; } @@ -660,6 +680,7 @@ stateTimerStart = getMSTimerCount(); isThisInitialDrain = FALSE; rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + flushUIState = FLUSH_UI_STATE_DRAIN_RESERVOIRS; state = DG_FLUSH_STATE_DRAIN_R1; } // Check if reservoir 1 fill timed out @@ -710,7 +731,6 @@ #endif setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); stateTimerStart = getMSTimerCount(); @@ -774,7 +794,7 @@ if ( TRUE == didTimeout( stateTimerStart, FLUSH_WITH_FRESH_WATER_WAIT_TIME_MS ) ) { deenergizeActuators(); - + flushUIState = FLUSH_UI_STATE_COMPLETE; state = DG_FLUSH_STATE_COMPLETE; } @@ -798,6 +818,8 @@ // deenergize all the actuators failFlushMode(); + flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + return state; } @@ -841,6 +863,8 @@ // Start the drain pump setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + // Start the timer for drain timeout stateTimerStart = getMSTimerCount(); } @@ -1026,6 +1050,7 @@ data.overallElapsedTime = calcTimeSince( overallFlushElapsedTimeStart ); data.stateElapsedTime = calcTimeSince( stateTimerStart ); data.drainLineVolume = flushLinesVolumeL; + data.flushUIState = (U32)flushUIState; broadcastFlushData( &data ); Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r2fff37fa585181917705645494549b5fd4a4d522 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 2fff37fa585181917705645494549b5fd4a4d522) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -64,7 +64,9 @@ #define FLUSH_CICRCULATION_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush/rinse circulation path wait time in milliseconds. TODO original time was 30 seconds #define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 50.0 ///< Maximum flush circulation temperature difference tolerance in C. TODO original difference was 3.0 degrees #define NUM_OF_TEMP_SENSORS_TO_AVG 4.0 ///< Number of temperature sensors to average to check the difference. -#define CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN -30.0 ///< Concentrate pumps reverse speed in mL/min. +#define ACID_PUMP_SPEED_ML_PER_MIN -30.0 ///< Acid concentrate pump speed in mL/min. +// The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during heat disinfect +#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6 ///< Bicarb concentrate pump speed in mL/min. // Flush and drain R1 and R2 #define RSRVRS_FULL_VOL_ML 1750.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 @@ -118,7 +120,8 @@ /// Heat disinfect status typedef enum Heat_disinfect_status { - HEAT_DISINFECT_IN_PROGRESS = 0, ///< Heat disinfect in progress. + HEAT_DISINFECT_HEAT_UP_IN_PROGRESS = 0, ///< Heat disinfect in progress. + HEAT_DISINFECT_DISINFECT_IN_PROGRESS, ///< Heat disinfect disinfect in progress. HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT, ///< Heat disinfect reservoirs leak timeout. HEAT_DISINFECT_HEAT_UP_TIMEOUT, ///< Heat disinfect heat up timeout. HEAT_DISINFECT_COMPLETE, ///< Heat disinfect complete. @@ -153,6 +156,7 @@ static U32 ROFCirculationTimer = 0; ///< RO filter circulation timer. static U32 ROFCoolingTimer = 0; ///< RO filter cooling timer. static BOOL hasROFCirculationBeenStarted = FALSE; ///< Flag to indicate the water in RO filter has been recirculated. +static U32 targetDisinfectTime = 0; ///< Target disinfect time. // ********** private function prototypes ********** @@ -196,8 +200,8 @@ * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, - * hasROFCirculationBeenStarted, ROFCirculationTimer, - * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer + * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime + * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -222,6 +226,7 @@ ROFCoolingTimer = 0; hasROFCirculationBeenStarted = FALSE; concentratePumpsPrimeTimer = 0; + targetDisinfectTime = 0; } /*********************************************************************//** @@ -700,8 +705,8 @@ areTempSensorsInRange = TRUE; #ifndef IGNORE_CONC_PUMP_IN_HEAT_DISINFECT // Turn the pumps on in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, ACID_PUMP_SPEED_ML_PER_MIN ); // Turn on the concentrate pumps requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); @@ -719,7 +724,7 @@ rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - // Done with priming the concentrate pumps line + // Done with flushing the concentrate pumps line requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP2_BICARB ); @@ -1122,6 +1127,10 @@ state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; break; + case HEAT_DISINFECT_DISINFECT_IN_PROGRESS: + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_1; + break; + case HEAT_DISINFECT_COMPLETE: requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -1145,9 +1154,9 @@ state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; break; - case HEAT_DISINFECT_IN_PROGRESS: + case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: default: - // Do nothing, heat disinfect is in progress + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; break; } @@ -1221,6 +1230,7 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; switch ( status ) { @@ -1237,7 +1247,7 @@ state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; break; - case HEAT_DISINFECT_IN_PROGRESS: + case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: default: // Do nothing heat disinfect is in progress. break; @@ -1628,8 +1638,8 @@ setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); #ifndef IGNORE_CONC_PUMP_IN_HEAT_DISINFECT // Turn the pumps on in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, ACID_PUMP_SPEED_ML_PER_MIN ); // Turn on the concentrate pumps requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); @@ -1964,7 +1974,7 @@ *************************************************************************/ static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ) { - HEAT_DISINFECT_STATUS_T status = HEAT_DISINFECT_IN_PROGRESS; + HEAT_DISINFECT_STATUS_T status = HEAT_DISINFECT_HEAT_UP_IN_PROGRESS; F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); @@ -1984,7 +1994,7 @@ // If the volume is out of range and it has timed out, exit else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) { - areRsrvrsLeaking = FALSE; + areRsrvrsLeaking = FALSE; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; } @@ -2002,7 +2012,7 @@ // Keep reseting the disinfect timer so the elapsed time is always 0 until disinfect truly starts heatDisinfectTimer = getMSTimerCount(); isPartialDisinfectInProgress = FALSE; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; + targetDisinfectTime = 0; if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) { @@ -2016,32 +2026,37 @@ // The temperature of the coldest spot is in range to start the disinfect timer heatDisinfectTimer = getMSTimerCount(); isPartialDisinfectInProgress = TRUE; + targetDisinfectTime = HEAT_DISINFECT_TIME_MS; + status = HEAT_DISINFECT_DISINFECT_IN_PROGRESS; - // Set the heat disinfect UI state + // In disinfect R1 to R2, concentrate pumps are also run if ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) { - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_1; #ifndef IGNORE_CONC_PUMP_IN_HEAT_DISINFECT // Turn the pumps on in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMPS_REVERSE_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); // During R1 to R2 disinfect, the concentrate pumps turn on requestConcentratePumpsOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpsOn( CONCENTRATEPUMPS_CP2_BICARB ); #endif } - else - { - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; - } } + else if ( ( TRUE == isPartialDisinfectInProgress ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) + { + status = HEAT_DISINFECT_DISINFECT_IN_PROGRESS; + } // If heat disinfect temperature has been reached, check if this stage of heat disinfect is done if ( ( TRUE == isPartialDisinfectInProgress ) && ( TRUE == didTimeout( heatDisinfectTimer, HEAT_DISINFECT_TIME_MS ) ) ) { // Done with this stage of heat disnfect. Reset the variables - status = HEAT_DISINFECT_COMPLETE; + // Target disinfect time is the time that is published to the UI and when there is + // no disinfect count down, this variable is set to 0. When the target time is 0, the UI + // hides the timer on the UI disinfect screen + targetDisinfectTime = 0; + status = HEAT_DISINFECT_COMPLETE; isPartialDisinfectInProgress = FALSE; } @@ -2073,8 +2088,12 @@ if ( ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) || ( DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 == heatDisinfectState ) ) { - uiData.heatDisinfectTargetTime = HEAT_DISINFECT_TIME_MS; - uiData.heatDisinfectCountdownTime = HEAT_DISINFECT_TIME_MS - calcTimeSince( heatDisinfectTimer ); + // If the disinfect target time is 0, meaning the actual disinfect has not started, set the count down to 0, otherwise, publish + // the actual value + U32 countDown = ( HEAT_DISINFECT_TIME_MS == targetDisinfectTime ? ( targetDisinfectTime - calcTimeSince( heatDisinfectTimer) ) : 0 ); + + uiData.heatDisinfectTargetTime = targetDisinfectTime; + uiData.heatDisinfectCountdownTime = countDown / 1000; // The count down is converted into seconds since the UI does not work with milliseconds data.R1FillLevel = R1HeatDisinfectVol; data.R2FillLevel = R2HeatDisinfectVol; } Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r2fff37fa585181917705645494549b5fd4a4d522 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 2fff37fa585181917705645494549b5fd4a4d522) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -16,6 +16,8 @@ ***************************************************************************/ #include "Accel.h" +#include "ConcentratePumps.h" +#include "ConductivitySensors.h" #include "CPLD.h" #include "DrainPump.h" #include "Fans.h" @@ -26,6 +28,8 @@ #include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" +#include "Reservoirs.h" +#include "ROPump.h" #include "RTC.h" #include "SystemCommMessages.h" #include "TemperatureSensors.h" @@ -98,10 +102,6 @@ #ifdef SKIP_POST postState = DG_POST_STATE_COMPLETED; #endif -#ifdef DONT_SKIP_NV_POST - // Only run NVDataMgmt POST - postState = DG_POST_STATE_NVDATAMGMT; -#endif break; case DG_POST_STATE_FW_COMPATIBILITY: @@ -129,14 +129,12 @@ postState = handlePOSTStatus( testStatus ); break; + // NOTE: all the actuators and sensors must execute their POST after NVDataMgmt + // NVDataMgmt must load all the calibration data into RAM so the actuators + // can query their corresponding calibration values successfully case DG_POST_STATE_TEMPERATURE_SENSORS: -#ifdef DONT_SKIP_NV_POST - // Skip the rest of the POSTs - postState = DG_POST_STATE_COMPLETED; -#else testStatus = execTemperatureSensorsSelfTest(); postState = handlePOSTStatus( testStatus ); -#endif break; case DG_POST_STATE_ACCELEROMETER: @@ -153,29 +151,46 @@ postState = handlePOSTStatus( testStatus ); break; -#ifdef _VECTORCAST_ - case DG_POST_DRAIN_PUMP: + case DG_POST_STATE_RO_PUMP: + testStatus = execROPumpSelfTest(); + postState = handlePOSTStatus( testStatus ); + break; + + case DG_POST_STATE_DRAIN_PUMP: testStatus = execDrainPumpSelfTest(); postState = handlePOSTStatus( testStatus ); break; -// To be able to run integration test in VectorCAST. -// Not all the fans and thermistors have been implemented so POST might fail - case DG_POST_STATE_THERMISTORS: - testStatus = execThermistorsSelfTest(); + + case DG_POST_STATE_CONCENTRATE_PUMPS: + testStatus = execConcenratePumpsSelfTest(); postState = handlePOSTStatus( testStatus ); break; - case DG_POST_STATE_FANS: - testStatus = execFansSelfTest(); + case DG_POST_STATE_CONDUCTIVITY_SENSORS: + testStatus = execConductivitySensorsSelfTest(); postState = handlePOSTStatus( testStatus ); break; + case DG_POST_STATE_RESERVOIRS: + testStatus = execReservoirsSelfTest(); + postState = handlePOSTStatus( testStatus ); + break; + case DG_POST_STATE_UV_REACTORS: testStatus = execUVReactorsSelfTest(); postState = handlePOSTStatus( testStatus ); break; -#endif + case DG_POST_STATE_THERMISTORS: + testStatus = execThermistorsSelfTest(); + postState = handlePOSTStatus( testStatus ); + break; + + case DG_POST_STATE_FANS: + testStatus = execFansSelfTest(); + postState = handlePOSTStatus( testStatus ); + break; + case DG_POST_STATE_WATCHDOG: testStatus = execWatchdogTest(); postState = handlePOSTStatus( testStatus ); @@ -184,7 +199,8 @@ // 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 + handlePOSTStatus( testStatus ); + // Ignoring return value because last test if ( TRUE == tempPOSTPassed ) { postState = DG_POST_STATE_COMPLETED; Index: firmware/App/Modes/ModeRecirculate.c =================================================================== diff -u -rc2fe204db1b8926994b5eee78afa1b516c97d02c -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision c2fe204db1b8926994b5eee78afa1b516c97d02c) +++ firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -93,6 +93,10 @@ setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); +#ifndef V_2_SYSTEM + setValveStateDelayed( VRD1, VALVE_STATE_CLOSED, 0 ); + setValveStateDelayed( VRD2, VALVE_STATE_CLOSED, 0 ); +#endif signalDrainPumpHardStop(); requestConcentratePumpsOff( CONCENTRATEPUMPS_CP1_ACID ); @@ -105,7 +109,7 @@ // NOTE: The target flow rate should be set prior to setting the start primary heater // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters - setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); + setROPumpTargetFlowRate( TARGET_FLUSH_LINES_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); startPrimaryHeater(); #ifndef _VECTORCAST_ Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r8b0c842f94e3c94cecf62f0f913e429def8e5efa -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 8b0c842f94e3c94cecf62f0f913e429def8e5efa) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -63,11 +63,11 @@ SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL, SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, - SW_FAULT_ID_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, // 35 - SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, + SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, // 35 SW_FAULT_ID_HEATERS_SELF_TEST_INVALID_STATE, SW_FAULT_ID_HEATERS_PRIMARY_HEATER_EXEC_INVALID_STATE, - SW_FAULT_ID_HEATERS_TRIMMER_HEATER_EXEC_INVALID_STATE, + SW_FAULT_ID_HEATERS_TRIMMER_HEATER_EXEC_INVALID_STATE, + SW_FAULT_ID_DG_PRESSURES_INVALID_SELF_TEST_STATE, SW_FAULT_ID_VALVES_INVALID_VALVE_STATE_NAME, // 40 SW_FAULT_ID_VALVES_INVALID_VALVE_ID, SW_FAULT_ID_CAN_PARITY_ERROR, @@ -89,10 +89,10 @@ SW_FAULT_ID_UV_REACTORS_INVALID_EXEC_STATE, SW_FAULT_ID_UV_REACTORS_INVALID_SELF_TEST_STATE, SW_FAULT_ID_THERMISTORS_INVALID_EXEC_STATE, // 60 - SW_FAULT_ID_THERMISTORS_INVALID_SELF_TEST_STATE, SW_FAULT_ID_INVALID_THERMISTOR_SELECTED, SW_FAULT_ID_FAN_INVALID_EXEC_STATE, - SW_FAULT_ID_FAN_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_DG_CHEM_DISINFECT_INVALID_EXEC_STATE, + SW_FAULT_ID_DG_INVALID_SWITCH_ID, SW_FAULT_ID_INVALID_FAN_SELECTED, // 65 SW_FAULT_ID_RO_PUMP_INVALID_EXEC_STATE, SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, @@ -124,7 +124,6 @@ SW_FAULT_ID_INVALID_VOLTAGE_MONITOR_STATE, SW_FAULT_ID_INVALID_MONITORED_VOLTAGE_ID, SW_FAULT_ID_INVALID_LOAD_CELL_ID, // 95 - SW_FAULT_ID_DG_CHEM_DISINFECT_INVALID_EXEC_STATE, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -79,6 +79,11 @@ #define FPGA_FLUIDLEAK_STATE_MASK 0x0004 ///< Bit mask for fluid leak detector. +#define FLUID_DOOR_SWITCH_MASK 0x08 ///< Fluid door switch bit mask. +#define DIALYSATE_CAP_SWITCH_MASK 0x10 ///< Dialysate cap switch bit mask. +#define CONCENTRATE_CAP_SWITCH_MASK 0x1A ///< Concentrate cap switch bit mask. +#define FPGA_POWER_STATUS_MASK 0x40 ///< FPGA power status bit mask. + // FPGA header struct. #pragma pack(push,1) typedef struct @@ -245,6 +250,7 @@ static void startDMAReceiptOfReadResp( void ); static void consumeUnexpectedData( void ); +static void monitorFPGAPowerStatus( void ); /*********************************************************************//** * @brief @@ -922,6 +928,11 @@ } } +static void monitorFPGAPowerStatus( void ) +{ + BOOL isFPGAPowered = (BOOL)( fpgaSensorReadings.fpgaGPIO & FPGA_POWER_STATUS_MASK ); +} + /*********************************************************************//** * @brief * The setFPGAValveStates function sets the DG valve states with a 16-bit @@ -1843,4 +1854,43 @@ return ( 0 == noFluidLeakDetected ? FALSE : TRUE ); } +/*********************************************************************//** + * @brief + * The getFPGAGFluidDoorStatus function gets the FPGA fluid door status + * bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return fluid door status bit + *************************************************************************/ +U08 getFPGAGFluidDoorStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & FLUID_DOOR_SWITCH_MASK ); +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateCapStatus function gets the FPGA dialysate cap status + * bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return dialysate cap status bit + *************************************************************************/ +U08 getFPGADialysateCapStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & DIALYSATE_CAP_SWITCH_MASK ); +} + +/*********************************************************************//** + * @brief + * The getFPGAConcentrateCapStatus function gets the FPGA concentrate cap + * status bit. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return concentrate cap status bit + *************************************************************************/ +U08 getFPGAConcentrateCapStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & CONCENTRATE_CAP_SWITCH_MASK ); +} + /**@}*/ Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -134,8 +134,12 @@ U16 getFPGATimerCount( void ); -BOOL noFPGAFluidLeakDetected( void); +BOOL noFPGAFluidLeakDetected( void ); +U08 getFPGAGFluidDoorStatus( void ); +U08 getFPGADialysateCapStatus( void ); +U08 getFPGAConcentrateCapStatus( void ); + /**@}*/ #endif Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rc55d371408bdf962de525a47bc8541d5b43414a3 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision c55d371408bdf962de525a47bc8541d5b43414a3) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -249,14 +249,6 @@ { canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); } -#ifdef DEBUG_ENABLED - { - char debugStr[100]; - strcpy( debugStr, "SystemComm-DG resend Last Frame.\n" ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); - sendDebugDataToUI( (U08*)debugStr ); - } -#endif } // we must be only node on CAN bus - nobody is ACKing our transmitted frames else @@ -265,11 +257,6 @@ canXmitRetryCtr = MAX_XMIT_RETRIES; signalCANXmitsCompleted(); // clear pending xmit flag clearCANXmitBuffers(); // clear xmit buffers - nothing is going out right now -#ifdef DEBUG_ENABLED - char debugStr[100]; - strcpy( debugStr, "SystemComm-DG is only node.\n" ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); -#endif } // end - are we retrying xmit or are we alone on CAN bus } // end - pending xmit timeout? } // end - transmit in progress or not @@ -567,13 +554,12 @@ else { signalCANXmitsCompleted(); - // TODO - shouldn't get here, but let's see if we do - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)mBox ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_CAN_TX_FAULT, (U32)mBox ) } } else - { // TODO - shouldn't get here - just testing - set first data to new s/w fault enum later - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)buffer, (U32)dataSize ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_SIZE, (U32)dataSize ) } } @@ -839,9 +825,7 @@ if ( TRUE == didTimeout( timeOfLastHDCheckIn, HD_COMM_TIMEOUT_IN_MS ) ) { hdIsCommunicating = FALSE; -#ifndef DEBUG_ENABLED - activateAlarmNoData( ALARM_ID_HD_COMM_TIMEOUT ); // TODO - add this alarm if we're in middle of a treatment? or if in a mode that comm loss would impact badly? -#endif + activateAlarmNoData( ALARM_ID_HD_COMM_TIMEOUT ); } } @@ -860,14 +844,6 @@ { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_COMM_TOO_MANY_BAD_CRCS, 2 ); // 2 for DG } -#ifdef DEBUG_ENABLED - { - char debugStr[100]; - - strcpy( debugStr, "SystemComm-DG-Bad Msg CRC.\n" ); - sendDebugDataToUI( (U08*)debugStr ); - } -#endif } /*********************************************************************//** @@ -1057,6 +1033,10 @@ handleUIClockSyncRequest( message ); break; + case MSG_ID_HD_DG_POST_RESULT_REQUEST: + handleDGPOSTResultRequest( message ); + break; + case MSG_ID_UI_REQUEST_SERVICE_INFO: handleDGServiceScheduleRequest( message ); break; @@ -1288,6 +1268,10 @@ handleSetFluidLeakStateDetectorOverrideRequest( message ); break; + case MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE: + handleFilterFlushTimePeriodOverride(message); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rc2fe204db1b8926994b5eee78afa1b516c97d02c -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision c2fe204db1b8926994b5eee78afa1b516c97d02c) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -761,13 +761,17 @@ *************************************************************************/ void handleAlarmClear( MESSAGE_T *message ) { + BOOL result = FALSE; + if ( message->hdr.payloadLen == sizeof( U32 ) ) { U32 alarmId; + result = TRUE; memcpy(&alarmId, message->payload, sizeof( U32 ) ); clearAlarm( (ALARM_ID_T)alarmId ); } + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** @@ -3233,6 +3237,40 @@ /*********************************************************************//** * @brief +* The handleDGPOSTResultRequest function handles a request to report DG +* POST results. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleDGPOSTResultRequest( MESSAGE_T *message ) +{ + BOOL status = FALSE; + BOOL result = FALSE; + U08* payloadPtr = message->payload; + + if ( 0 == message->hdr.payloadLen ) + { + if ( TRUE == isPOSTCompleted() ) + { + status = TRUE; + if ( TRUE == isPOSTPassed() ) + { + result = TRUE; + } + sendPOSTFinalResult( result ); + } + } + // If can't respond to request, NAK the message + if ( status != TRUE ) + { + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); + } +} + +/*********************************************************************//** +* @brief * The handleSetDGCalibrationRecord function handles a request to set the DG * calibration data record. * @details Inputs: none @@ -3503,6 +3541,38 @@ } /*********************************************************************//** + * @brief + * The handleFilterFlushTimePeriodOverride function handles a request + * to override the filter flush time period value. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleFilterFlushTimePeriodOverride( 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 = testSetFilterFlushTimePeriodOverride( payload.state.u32 ); + } + else + { + result = testResetFilterFlushTimePeriodOverride(); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** * @brief * The handleStartStopDGChemicalDisinfect function handles a request to start * or stop DG chemical disinfect mode. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rc55d371408bdf962de525a47bc8541d5b43414a3 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision c55d371408bdf962de525a47bc8541d5b43414a3) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -109,6 +109,9 @@ // MSG_ID_DG_UV_REACTORS_DATA BOOL broadcastUVReactorsData( UV_REACTORS_DATA_T *uvReactorsData ); +// MSG_ID_DG_HEAT_DISINFECT_DATA +BOOL broadcastHeatDisinfectData( MODE_HEAT_DISINFECT_DATA_T *heatDisinfectData ); + // MSG_ID_DG_FILTER_FLUSH_PROGRESS BOOL broadcastFilterFlushData( U32 timeout, U32 countdown ); @@ -178,12 +181,6 @@ // MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD void handleStartStopTrimmerHeaterCmd( MESSAGE_T *message ); -// MSG_ID_DG_UV_REACTORS_DATA -BOOL broadcastUVReactorsData( UV_REACTORS_DATA_T *uvReactorsData ); - -// MSG_ID_DG_HEAT_DISINFECT_DATA -BOOL broadcastHeatDisinfectData( MODE_HEAT_DISINFECT_DATA_T *heatDisinfectData ); - // MSG_ID_DG_SEND_CALIBRATION_DATA BOOL sendDGCalibrationRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* calRcrdAddress ); @@ -357,6 +354,9 @@ // MSG_ID_UI_DG_SET_RTC_REQUEST void handleUIClockSyncRequest( MESSAGE_T *message ); +// MSG_ID_HD_DG_POST_RESULT_REQUEST +void handleDGPOSTResultRequest( MESSAGE_T *message ); + // MSG_ID_DG_SET_CALIBRATION_DATA void handleSetDGCalibrationRecord( MESSAGE_T *message ); @@ -384,6 +384,9 @@ // MSG_ID_DG_START_STOP_CHEM_DSINFECT BOOL handleStartStopDGChemicalDisinfect( MESSAGE_T *message ); +// MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE +void handleFilterFlushTimePeriodOverride( MESSAGE_T *message ); + /**@}*/ #endif Index: firmware/App/Services/WatchdogMgmt.c =================================================================== diff -u -r97e0100921ccad633b39b509a93a7237e4d80446 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 97e0100921ccad633b39b509a93a7237e4d80446) +++ firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -15,7 +15,9 @@ * ***************************************************************************/ -#include "CPLD.h" +#include "CPLD.h" +#include "InternalADC.h" +#include "OperationModes.h" #include "SystemCommMessages.h" #include "Timers.h" #include "WatchdogMgmt.h" @@ -28,9 +30,13 @@ // ********** private definitions ********** #define MIN_WATCHDOG_PET_INTERVAL_MS 45 ///< Minimum watchdog pet interval. -#define WATCHDOG_POST_TIMEOUT_MS 100 ///< Watchdog POST timeout in ms. -#define WATCHDOG_RECOVERY_TIME_MS 250 ///< Watchdog recovery time in ms. +#define WATCHDOG_POST_TIMEOUT_MS 500 ///< Watchdog POST timeout in ms. +#define WATCHDOG_RECOVERY_TIME_MS 500 ///< Watchdog recovery time in ms. + +#define MAX_24V_LEVEL_ON_WATCHDOG_EXPIRED 5.0 ///< Maximum voltage on 24V line when watchdog is expired. // TODO - check w/ Systems. Takes time for V to bleed off. Had to raise to 5V. +#define MIN_24V_LEVEL_ON_WATCHDOG_RECOVER 22.6 ///< Minimum voltage on 24V line when watchdog is recovered. + /// List of watchdog states. typedef enum Button_Self_Test_States { @@ -111,7 +117,8 @@ if ( PIN_SIGNAL_LOW == getCPLDWatchdogExpired() ) { // ignore expired watchdog until after watchdog POST - if ( WATCHDOG_SELF_TEST_STATE_COMPLETE == watchdogSelfTestState ) + if ( ( WATCHDOG_SELF_TEST_STATE_COMPLETE == watchdogSelfTestState ) || + ( getCurrentOperationMode() != DG_MODE_INIT ) ) { #ifndef DEBUG_ENABLED activateAlarmNoData( ALARM_ID_WATCHDOG_EXPIRED ); @@ -163,20 +170,42 @@ } if ( PIN_SIGNAL_LOW == getCPLDWatchdogExpired() ) { - watchdogSelfTestStatus = SELF_TEST_STATUS_PASSED; + F32 v24 = getIntADCVoltageConverted( INT_ADC_MAIN_24_VOLTS ); + + // Verify 24V is down when w.d. expired + if ( v24 > MAX_24V_LEVEL_ON_WATCHDOG_EXPIRED ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_WATCHDOG_POST_TEST_FAILED, 2.0, v24 ); + watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; + } } else { - activateAlarmNoData( ALARM_ID_WATCHDOG_POST_TEST_FAILED ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_WATCHDOG_POST_TEST_FAILED, 1 ); watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; } - watchdogSelfTestTimerCount = getMSTimerCount(); - watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_RECOVER; + watchdogSelfTestTimerCount = getMSTimerCount(); + watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_RECOVER; break; case WATCHDOG_SELF_TEST_STATE_RECOVER: if ( TRUE == didTimeout( watchdogSelfTestTimerCount, WATCHDOG_RECOVERY_TIME_MS ) ) { + if ( getCPLDWatchdogExpired() == PIN_SIGNAL_HIGH ) + { + F32 v24 = getIntADCVoltageConverted( INT_ADC_MAIN_24_VOLTS ); + + // Verify 24V is down when w.d. recovered + if ( v24 < MIN_24V_LEVEL_ON_WATCHDOG_RECOVER ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_WATCHDOG_POST_TEST_FAILED, 3.0, v24 ); + watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; + } + else + { + watchdogSelfTestStatus = SELF_TEST_STATUS_PASSED; + } + } result = watchdogSelfTestStatus; watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_COMPLETE; } @@ -266,7 +295,7 @@ } else { - activateAlarmNoData( ALARM_ID_DG_SOFTWARE_FAULT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TASK, task ); } return result; Index: firmware/source/sys_main.c =================================================================== diff -u -r2fff37fa585181917705645494549b5fd4a4d522 -ra79db345deaaeef0f1b619dc49d031fdae22d7e6 --- firmware/source/sys_main.c (.../sys_main.c) (revision 2fff37fa585181917705645494549b5fd4a4d522) +++ firmware/source/sys_main.c (.../sys_main.c) (revision a79db345deaaeef0f1b619dc49d031fdae22d7e6) @@ -85,6 +85,7 @@ #include "ROPump.h" #include "RTC.h" #include "SafetyShutdown.h" +#include "Switches.h" #include "SystemComm.h" #include "TaskBG.h" #include "TemperatureSensors.h" @@ -192,6 +193,7 @@ initUVReactors(); initAccel(); initRTC(); + initSwitches(); initCommBuffers(); initMsgQueues(); initSystemComm();