Index: firmware/App/Controllers/DialysatePumps.c =================================================================== diff -u --- firmware/App/Controllers/DialysatePumps.c (revision 0) +++ firmware/App/Controllers/DialysatePumps.c (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -0,0 +1,1017 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file DialysatePumps.c +* +* @author (last) Vinayakam Mani +* @date (last) 02-Oct-2024 +* +* @author (original) Vinayakam Mani +* @date (original) 02-Oct-2024 +* +***************************************************************************/ + +#include + +#include "DialysatePumps.h" +#include "FpgaDD.h" +#include "MessageSupport.h" +#include "Messaging.h" +//#include "NVDataMgmt.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" +#include "PIControllers.h" +#include "Pressure.h" +#include "SafetyShutdown.h" +#include "TaskGeneral.h" +#include "TaskPriority.h" +#include "Timers.h" +#include "Utilities.h" + +/** + * @addtogroup DialysatePumps + * @{ + */ + +// ********** private definitions ********** + +#define DIALYSATE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the dialysate pump data is published on the CAN bus. +#define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. + +#define DP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate pump is controlled. +#define DIALYSATE_PUMP_CONTROL_RUN 0x01 ///< Dialysate pump control run pump. +#define DIALYSATE_PUMP_CONTROL_STOP 0x00 ///< Dialysate pump control stop pump. +#define DIALYSATE_PUMP_FORWARD_DIR 1 ///< Dialysate pump forward direction. reverse direction is not allowed. +#define DIALYSATE_PUMP_SPEED_INCREMENT 5.0F ///< Speed increase when controlling dialysate pump to target step speed. + +#define DIALYSATE_PUMP_MAX_CURRENT_WHEN_OFF_A 0.1F ///< Dialysate pump maximum current when the pump is off in amps. +#define DIALYSATE_PUMP_MAX_CURRENT_A 2.2F ///< Dialysate pump maximum current in amps. +#define DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Dialysate pump current out of range timeout in milliseconds. +#define DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Dialysate pump direction out of range timeout in milliseconds. +#define DIALYSATE_PUMP_DIR_BIT_MASK 0x80 ///< Dialysate pump direction bit clear mask. +#define DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK 0x3F ///< Dialysate pump direction error count bit mask. +#define DIALYSATE_PUMP_MIN_RPM_FOR_DIR_CHECK 100 ///< Dialysate pump minimum RPM for direction check. + +#define MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< FPGA dialysate pump direction fault window +#define MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES 10 ///< FPGA dialysate pump direction fault failures per MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS + +#define FRESH_DIALYSATE_TARGET_PRESSURE_PSI (-12.0F) ///< Fresh dialysate pump recommended pressure(Pn/PHo) in psi. +#define FRESH_DIALYSATE_MAX_PRESSURE_PSI (-15.0F) ///< Fresh dialysate pump maximum allowed (Pn/PHo) pressure in psi. +#define SPENT_DIALYSATE_TARGET_PRESSURE_PSI 25.0F ///< Spent dialysate pump recommended pressure(PDs) in psi. +#define SPENT_DIALYSATE_MAX_PRESSURE_PSI 30.0F ///< Spent dialysate pump maximum allowed (PDs) pressure in psi. +#define DIALYSATE_PUMP_MIN_PRESSURE_PSI 0.0F ///< Minimum dialysate pump pressure in psi. +#define DIALYSATE_PUMP_MAX_PRESSURE_PSI 40.0F ///< Maximum dialysate pump pressure in psi. +#define DIALYSATE_PUMP_SPEED_ZERO_RPM 0 ///< Dialysate pump zero RPM speed. + +#define DIALYSATE_PUMP_P_COEFFICIENT 1.0F ///< P term for dialysate pump delta pressure control. +#define DIALYSATE_PUMP_I_COEFFICIENT 1.0F ///< I term for dialysate pump delta pressure control. + +#define MAX_ALLOWED_RPM_OUT_OF_RANGE 300 ///< Maximum allowed RPM out of range from target RPM in open loop. +#define RPM_OUT_OF_RANGE_TIME_OUT ( 10 * MS_PER_SECOND ) ///< Open loop RPM out of range time out in ms. +#define SAFETY_SHUTDOWN_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Dialysate pump safety shutdown activation timeout. + +/// Enumeration of dialysate pump states. +typedef enum DialysatePump_States +{ + DIALYSATE_PUMP_OFF_STATE = 0, ///< Dialysate pump off state + DIALYSATE_PUMP_RAMP_UP_STATE, ///< Dialysate pump ramp up state + DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE, ///< Dialysate pump control to target state + NUM_OF_DIALYSATE_PUMP_STATES ///< Number of dialysate pump states +} DIALYSATE_PUMP_STATE_T; + +/// Enumeration of dialysate pump self-test states. +typedef enum DialysatePump_Self_Test_States +{ + DIALYSATE_PUMP_SELF_TEST_STATE_START = 0, ///< Dialysate pump self-test start state + DIALYSATE_PUMP_TEST_STATE_IN_PROGRESS, ///< Dialysate pump self-test in progress state + DIALYSATE_PUMP_TEST_STATE_COMPLETE, ///< Dialysate pump self-test completed state + NUM_OF_DIALYSATE_PUMP_SELF_TEST_STATES ///< Number of dialysate pump self-test states +} DIALYSATE_PUMP_SELF_TEST_STATE_T; + +/// Dialysate pump data structure +typedef struct +{ + U32 controlTimerCounter; ///< Timer counter to perform control on dialysate pump. + DIALYSATE_PUMP_STATE_T dialysatePumpState; ///< Current state of dialysate pump controller state machine. + BOOL isDialPumpOn; ///< Flag indicates dialysate pump On or Off state + OVERRIDE_F32_T pumpTargetSpeed; ///< Target dialysate pumps' speed (mL/min). + F32 currentPumpSpeed; ///< Current controlled dialysate pumps' speed (mL/min). + OVERRIDE_F32_T measuredPumpSpeed; ///< Measured dialysate pump speed (mL/min). + OVERRIDE_F32_T dialysatePumpMeasuredCurrentA; ///< Measured dialysate pump current feedback. + OVERRIDE_U32_T measuredDirection; ///< Measured dialysate pump direction. + U32 directionErrorCount; ///< dialysate pump direction error count from power up. + U32 lastDirectionErrorCount; ///< last dialysate pump direction error count from power up. + OVERRIDE_F32_T pumpTargetPressure; ///< Target dialysate pumps' pressure (PSI). + U08 control; ///< Dialysate pump control +} DIALYSATE_PUMP_DATA_T; + +// ********** private data ********** + +static U32 dialysatePumpDataPublicationTimerCounter; ///< Used to schedule dialysate pump data publication to CAN bus. +static OVERRIDE_U32_T dialysatePumpDataPublishInterval = { DIALYSATE_PUMP_DATA_PUB_INTERVAL, + DIALYSATE_PUMP_DATA_PUB_INTERVAL, + 0, 0 }; ///< Interval (in ms) at which to publish dialysate pump data to CAN bus. + +//static DD_DIALYSATE_PUMP_CAL_RECORD_T dialysatePumpCalRecord; ///< Dialysate pump calibration record. +static DIALYSATE_PUMP_DATA_T dialysatePumps[ NUM_OF_DIALYSATE_PUMPS ]; ///< Array of dialysate pumps data structure. + +//TODO : Validate once HDD defines the conversion. +static const F32 CURRENT_CONVERSION_COEFF = (F32)( 2.5F / ( BITS_12_FULL_SCALE - 1.0F ) ); + +// ********** private function prototypes ********** + +static void publishDialysatePumpsData( void ); +static void stopDialysatePump( DIALYSATE_PUMPS_T pumpId ); +static DIALYSATE_PUMP_STATE_T handleDialysatePumpControlToTargetState( DIALYSATE_PUMPS_T pumpId ); +static BOOL stepDialysatePumpToTargetSpeed( DIALYSATE_PUMPS_T pumpId ); +static DIALYSATE_PUMP_STATE_T handleDialysatePumpRampToTargetState( DIALYSATE_PUMPS_T pumpId ); +static DIALYSATE_PUMP_STATE_T handleDialysatePumpOffState( DIALYSATE_PUMPS_T pumpId ); +static void monitorPumpDirectionErrorCount( DIALYSATE_PUMPS_T pumpId ); + +/*********************************************************************//** + * @brief + * The initDialysatePump function initializes the DialysatePumps unit. + * @details \b Inputs: none + * @details \b Outputs: Dialysate unit variables initialized. + * @return none + *************************************************************************/ +void initDialysatePump( void ) +{ + DIALYSATE_PUMPS_T pumpId; + + dialysatePumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + + for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) + { + dialysatePumps[ pumpId ].controlTimerCounter = 0; + dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; + dialysatePumps[ pumpId ].isDialPumpOn = FALSE; + dialysatePumps[ pumpId ].measuredPumpSpeed.data = 0.0F; + dialysatePumps[ pumpId ].measuredPumpSpeed.ovInitData = 0.0F; + dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0F; + dialysatePumps[ pumpId ].pumpTargetSpeed.ovInitData = 0.0F; + dialysatePumps[ pumpId ].measuredDirection.data = DIALYSATE_PUMP_FORWARD_DIR; + dialysatePumps[ pumpId ].measuredDirection.ovInitData = DIALYSATE_PUMP_FORWARD_DIR; + dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.data = 0.0F; + dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA.ovInitData = 0.0F; + dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; + dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; + dialysatePumps[ pumpId ].directionErrorCount = 0; + dialysatePumps[ pumpId ].lastDirectionErrorCount = 0; + signalDialysatePumpHardStop( pumpId ); + } + + dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.data = FRESH_DIALYSATE_TARGET_PRESSURE_PSI; + dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.ovInitData = FRESH_DIALYSATE_TARGET_PRESSURE_PSI; + dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.ovData = 0.0F; + dialysatePumps[FRESH_DIALYSATE_PUMP].pumpTargetPressure.override = OVERRIDE_RESET; + + dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.data = SPENT_DIALYSATE_TARGET_PRESSURE_PSI; + dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.ovInitData = SPENT_DIALYSATE_TARGET_PRESSURE_PSI; + dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.ovData = 0.0F; + dialysatePumps[SPENT_DIALYSATE_PUMP].pumpTargetPressure.override = OVERRIDE_RESET; + + // Initialize the fresh dialysate pump PI controller + initializePIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_P_COEFFICIENT, DIALYSATE_PUMP_I_COEFFICIENT, + DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_MAX_PRESSURE_PSI ); + + // Initialize spent dialysate pump PI controller + initializePIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_P_COEFFICIENT, DIALYSATE_PUMP_I_COEFFICIENT, + DIALYSATE_PUMP_MIN_PRESSURE_PSI, DIALYSATE_PUMP_MAX_PRESSURE_PSI ); + + // Initialize the persistent alarms for fresh dialysate pump + initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, RPM_OUT_OF_RANGE_TIME_OUT, RPM_OUT_OF_RANGE_TIME_OUT ); + initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); + initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ); + + //Initialize the persistent alarms for spent dialysate pump + initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, RPM_OUT_OF_RANGE_TIME_OUT, RPM_OUT_OF_RANGE_TIME_OUT ); + initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); + initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS, DIALYSATE_PUMP_DIR_OF_RANGE_TIMEOUT_MS ); + + // initialize FPGA dialysate pump hall sensor error + initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_FRESH_DIALYSATE_PUMP_HALL_SENSOR_ERROR, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ); + initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_SPENT_DIALYSATE_PUMP_HALL_SENSOR_ERROR, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_WINDOW_MS ); +} + +/*********************************************************************//** + * @brief + * The setDialysatePumpTargetSpeed function sets a new target RPM for the + * dialysate pump. + * @details \b Inputs: none + * @details \b Outputs: pumpTargetSpeed. + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump id supplied. + * @param pumpId pump id to set the new speed. + * @param rpm new dialysate pump target RPM + * @return TRUE if new target RPM is set, FALSE if not + *************************************************************************/ +BOOL setDialysatePumpTargetRPM( DIALYSATE_PUMPS_T pumpId, U32 rpm ) +{ + BOOL result = FALSE; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + if ( ( MIN_DIALYSATE_PUMP_RPM <= rpm ) && ( rpm <= MAX_DIALYSATE_PUMP_RPM ) ) + { + dialysatePumps[ pumpId ].pumpTargetSpeed.data = rpm; + } + else if ( rpm < MIN_DIALYSATE_PUMP_RPM ) + { + dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0; + } + else + { + dialysatePumps[ pumpId ].pumpTargetSpeed.data = MAX_DIALYSATE_PUMP_RPM; + } + + result = TRUE; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The signalDialysatePumpHardStop function stops the Dialysate pump immediately. + * @details \b Inputs: none + * @details \b Outputs: currentPumpSpeed,pumpTargetSpeed,dialysatePumpState, + * controlTimerCounter,isDialPumpOn. + * @param pumpId pump id to stop the given dialysate pump + * @return none + *************************************************************************/ +void signalDialysatePumpHardStop( DIALYSATE_PUMPS_T pumpId ) +{ + stopDialysatePump( pumpId ); + + // Reset all the variables to stop mode + dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; + dialysatePumps[ pumpId ].pumpTargetSpeed.data = 0.0F; + dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; + dialysatePumps[ pumpId ].controlTimerCounter = 0; + dialysatePumps[ pumpId ].isDialPumpOn = FALSE; + + //Reset PI Controller + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + resetPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); + } + else + { + resetPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); + } +} + +/*********************************************************************//** + * @brief + * The monitorPumpDirectionErrorCount function monitors the given dialysate pumps + * direction error count and triggers the alarms if they are incrementing for + * certain count with in defined time. + * @details \b Inputs: directionErrorCount,lastDirectionErrorCount + * @details \b Outputs: lastDirectionErrorCount + * @details \b Alarm: ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT when + * the direction error count increments for certian count with in defined time. + * @details \b Alarm: ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT when + * the direction error count increments for certian count with in defined time. + * @param pumpId pump id to check the direction error count for the given dialysate + * pump + * @return none + *************************************************************************/ +static void monitorPumpDirectionErrorCount( DIALYSATE_PUMPS_T pumpId ) +{ + if ( dialysatePumps[ pumpId ].directionErrorCount != dialysatePumps[ pumpId ].lastDirectionErrorCount ) + { + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_FRESH_DIALYSATE_PUMP_HALL_SENSOR_ERROR ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, dialysatePumps[ pumpId ].directionErrorCount ) + } + } + else + { + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_SPENT_DIALYSATE_PUMP_HALL_SENSOR_ERROR ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_FPGA_FAULT, MAX_FPGA_DIALYSATE_PUMP_DIRECTION_FAULT_FAILURES, dialysatePumps[ pumpId ].directionErrorCount ) + } + } + dialysatePumps[ pumpId ].lastDirectionErrorCount = dialysatePumps[ pumpId ].directionErrorCount; + } +} + +/*********************************************************************//** + * @brief + * The execDialysatePumpMonitor function executes the dialysate pump monitor. + * @details \b Inputs: dialysate pumps speed, current and direction reported + * by FPGA + * @details \b Outputs: measuredPumpSpeed,dialysatePumpMeasuredCurrentA, + * measuredDirection,directionErrorCount + * @detail \b Alarms: ALARM_ID_DD_XXX_DIALYSATE_PUMP_RPM_OUT_OF_RANGE when + * speed mismatch occurs between set and measured speed. + * @detail \b Alarms: ALARM_ID_DD_XXX_DIALYSATE_PUMP_OFF_FAULT when dialysate + * pump runs at certain speed when not commanded to run. + * @detail \b Alarms: ALARM_ID_DD_XXX_DIALYSATE_PUMP_DIRECTION_INVALID when + * dialysate pump is not running in forward direction. + * @detail \b Alarms:ALARM_ID_DD_XXX_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE when + * dialysate pump is drawing more current than expected. + * @return none + *************************************************************************/ +void execDialysatePumpMonitor( void ) +{ + U16 freshDialCurrent = getFPGAFreshDialysatePumpCurrentFeedback(); + U16 spentDialCurrent = getFPGAFreshDialysatePumpCurrentFeedback(); + BOOL isOffCurrentOut = FALSE; + BOOL isCurrentOutOfRange = FALSE; + DIALYSATE_PUMPS_T pumpId; + + // Update the paramerters + dialysatePumps[ FRESH_DIALYSATE_PUMP ].measuredPumpSpeed.data = getFPGAFreshDialysatePumpSpeed(); + dialysatePumps[ SPENT_DIALYSATE_PUMP ].measuredPumpSpeed.data = getFPGASpentDialysatePumpSpeed(); + dialysatePumps[ FRESH_DIALYSATE_PUMP ].dialysatePumpMeasuredCurrentA.data = (F32)freshDialCurrent * CURRENT_CONVERSION_COEFF; + dialysatePumps[ SPENT_DIALYSATE_PUMP ].dialysatePumpMeasuredCurrentA.data = (F32)spentDialCurrent * CURRENT_CONVERSION_COEFF; + dialysatePumps[ FRESH_DIALYSATE_PUMP ].measuredDirection.data = (U32)( ( getFPGAFreshDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_BIT_MASK ) >> SHIFT_BITS_BY_7 ); + dialysatePumps[ SPENT_DIALYSATE_PUMP ].measuredDirection.data = (U32)( ( getFPGASpentDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_BIT_MASK ) >> SHIFT_BITS_BY_7 ); + dialysatePumps[ FRESH_DIALYSATE_PUMP ].directionErrorCount = (U32)( getFPGAFreshDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK ); + dialysatePumps[ SPENT_DIALYSATE_PUMP ].directionErrorCount = (U32)( getFPGASpentDialysatePumpHallDirectionStatus() & DIALYSATE_PUMP_DIR_ERROR_CNT_BIT_MASK ); + + // Monitor dialysate pumps + for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) + { + switch ( dialysatePumps[ pumpId ].dialysatePumpState ) + { + case DIALYSATE_PUMP_OFF_STATE: + { + BOOL isRPMTooHigh = FALSE; + + isOffCurrentOut = ( getDialysatePumpMeasuredCurrentA( pumpId ) > DIALYSATE_PUMP_MAX_CURRENT_WHEN_OFF_A ? TRUE : FALSE ); + isRPMTooHigh = ( getDialysatePumpMeasuredSpeed( pumpId ) > MIN_DIALYSATE_PUMP_RPM ? TRUE : FALSE ); + + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MAX_ALLOWED_RPM_OUT_OF_RANGE ); + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, isRPMTooHigh, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, FALSE, getDialysatePumpMeasuredDirection( pumpId ), DIALYSATE_PUMP_FORWARD_DIR ); + } + else + { + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MAX_ALLOWED_RPM_OUT_OF_RANGE ); + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, isRPMTooHigh, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, FALSE, getDialysatePumpMeasuredDirection( pumpId ), DIALYSATE_PUMP_FORWARD_DIR ); + } + + // If the direction off fault alarm has become active, trigger the safety shutdown + if ( ( TRUE == isAlarmActive( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT ) ) || + ( TRUE == isAlarmActive( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT ) ) ) + { + //activateSafetyShutdown(); + } + } + break; + + case DIALYSATE_PUMP_RAMP_UP_STATE: + case DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE: + { + U32 direction = getDialysatePumpMeasuredDirection( pumpId ); + U32 rpm = getDialysatePumpMeasuredSpeed( pumpId ); + BOOL isRPMOutOfRange = FALSE; + U32 rpmDiff = abs( getDialysatePumpTargetSpeed( pumpId ) - rpm ); + BOOL isDirInvalid = ( ( direction != DIALYSATE_PUMP_FORWARD_DIR ) && ( rpm > DIALYSATE_PUMP_MIN_RPM_FOR_DIR_CHECK ) ? TRUE : FALSE ); + + isRPMOutOfRange = ( rpmDiff > MAX_ALLOWED_RPM_OUT_OF_RANGE ? TRUE : FALSE ); + + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, isRPMOutOfRange, rpm, MAX_ALLOWED_RPM_OUT_OF_RANGE ); + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_OFF_FAULT, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_DIRECTION_INVALID, isDirInvalid, (F32)direction, DIALYSATE_PUMP_FORWARD_DIR ); + } + else + { + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_RPM_OUT_OF_RANGE, isRPMOutOfRange, rpm, MAX_ALLOWED_RPM_OUT_OF_RANGE ); + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_OFF_FAULT, FALSE, getDialysatePumpMeasuredSpeed( pumpId ), MIN_DIALYSATE_PUMP_RPM ); + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_DIRECTION_INVALID, isDirInvalid, (F32)direction, DIALYSATE_PUMP_FORWARD_DIR ); + } + } + break; + + default: + // do nothing + break; + } + + //Monitor Direction error count + monitorPumpDirectionErrorCount( pumpId ); + + // Check the persistent alarm for the maximum dialysate pump current + F32 currentA = getDialysatePumpMeasuredCurrentA( pumpId ); + isCurrentOutOfRange = ( currentA > DIALYSATE_PUMP_MAX_CURRENT_A ? TRUE : FALSE ) | isOffCurrentOut; + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + checkPersistentAlarm( ALARM_ID_DD_FRESH_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, isCurrentOutOfRange, currentA, DIALYSATE_PUMP_MAX_CURRENT_A ); + } + else + { + checkPersistentAlarm( ALARM_ID_DD_SPENT_DIALYSATE_PUMP_CURRENT_OUT_OF_RANGE, isCurrentOutOfRange, currentA, DIALYSATE_PUMP_MAX_CURRENT_A ); + } + } + + // Publish dialysate pumps data on interval + publishDialysatePumpsData(); +} + +/*********************************************************************//** + * @brief + * The execDialysatePumpController function executes the dialysate pumps controller. + * @details \b Inputs: dialysatePumpState + * @details \b Outputs: dialysatePumpState + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT if invalid dialysate pump + * state machine found. + * @return none + *************************************************************************/ +void execDialysatePumpController( void ) +{ + DIALYSATE_PUMPS_T pumpId; + + // Check if a new calibration is available +// if ( TRUE == isNewCalibrationRecordAvailable() ) +// { + // get updated record + //getNVRecord2Driver( GET_CAL_DIALYSATE_PUMP_RECORD, (U08*)&dialysatePumpCalRecord, sizeof( DD_DIALYSATE_PUMP_CAL_RECORD_T ), 0, + // ALARM_ID_DD_FRESH_DIALYSATE_PUMP_INVALID_CAL_RECORD ); +// } + + for ( pumpId = DIALYSATE_PUMPS_FIRST; pumpId < NUM_OF_DIALYSATE_PUMPS; pumpId++ ) + { + switch ( dialysatePumps[ pumpId ].dialysatePumpState ) + { + case DIALYSATE_PUMP_OFF_STATE: + dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpOffState( pumpId ); + break; + + case DIALYSATE_PUMP_RAMP_UP_STATE: + dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpRampToTargetState( pumpId ); + break; + + case DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE: + dialysatePumps[ pumpId ].dialysatePumpState = handleDialysatePumpControlToTargetState( pumpId ); + break; + +#ifndef _VECTORCAST_ + // The switch case is in a for loop so the default case cannot be covered in VectorCAST + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_EXEC_INVALID_STATE, pumpId ) + dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; + break; +#endif + } + } +} + +/*********************************************************************//** + * @brief + * The execDialysatePumpSelfTest function executes the dialysate pump's self-test. + * @details \b Inputs: Non volatile records. + * @details \b Outputs: none + * @return DialysatePumps SelfTest Result (SELF_TEST_STATUS_T) + *************************************************************************/ +SELF_TEST_STATUS_T execDialysatePumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + BOOL calStatus = FALSE; + + // This is only one record the number of items to check is 0 since the get NV data function does not do a for loop to check the calibration time +// calStatus |= getNVRecord2Driver( GET_CAL_FRESH_DIALYSATE_PUMP_RECORD, (U08*)&freshDialysatePumpRecord, sizeof( DD_FRESH_DIALYSATE_PUMP_RECORD_T ), 0, +// ALARM_ID_DD_FRESH_DIALYSATE_PUMP_INVALID_CAL_RECORD ); +// calStatus |= getNVRecord2Driver( GET_CAL_SPENT_DIALYSATE_PUMP_RECORD, (U08*)&spentDialysatePumpRecord, sizeof( DD_SPENT_DIALYSATE_PUMP_RECORD_T ), 0, +// ALARM_ID_DD_SPENT_DIALYSATE_PUMP_INVALID_CAL_RECORD ); +// +// calStatus |= getNVRecord2Driver( GET_CAL_DIALYSATE_PUMP_RECORD, (U08*)&dialysatePumpCalRecord, sizeof( DD_DIALYSATE_PUMP_CAL_RECORD_T ), 0, +// ALARM_ID_NO_ALARM ); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isDialysatePumpOn function determines whether the dialysate pump is on + * or Off state. + * @details \b Inputs: none + * @details \b Outputs: none + * @param pumpId dialysate pump id to return status of dialysate pump running state + * @return TRUE if dialysate pump is on, FALSE if not. + *************************************************************************/ +BOOL isDialysatePumpOn( DIALYSATE_PUMPS_T pumpId ) +{ + return ( dialysatePumps[ pumpId ].isDialPumpOn ); +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpOffState function handles the dialysate pump off state of + * the dialysate pump controller state machine. + * @details \b Inputs: pumpTargetSpeed + * @details \b Outputs: dialysatePumps[].control,isDialPumpOn + * @param pumpId dialysate pump id to run the dialysate pump + * @return next state for the controller state machine + *************************************************************************/ +static DIALYSATE_PUMP_STATE_T handleDialysatePumpOffState( DIALYSATE_PUMPS_T pumpId ) +{ + DIALYSATE_PUMP_STATE_T result = DIALYSATE_PUMP_OFF_STATE; + F32 targetSpeed = getDialysatePumpTargetSpeed( pumpId ); + + if ( targetSpeed > NEARLY_ZERO ) + { + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + // dialysate pump control run enable + dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_RUN; + setFPGAFreshDialysatePumpControl( dialysatePumps[ pumpId ].control ); + } + else + { + dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_RUN; + setFPGASpentDialysatePumpControl( dialysatePumps[ pumpId ].control ); + } + + dialysatePumps[ pumpId ].isDialPumpOn = TRUE; + result = DIALYSATE_PUMP_RAMP_UP_STATE; + } + else + { + dialysatePumps[ pumpId ].isDialPumpOn = FALSE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpRampToTargetState function handles the dialysate pump + * ramp to target state of the dialysate pump controller state machine. + * @details \b Inputs: pumpTargetSpeed + * @details \b Outputs: currentPumpSpeed + * @param pumpId dialysate pump id to increase current step speed + * @return next state for the controller state machine + *************************************************************************/ +static DIALYSATE_PUMP_STATE_T handleDialysatePumpRampToTargetState( DIALYSATE_PUMPS_T pumpId ) +{ + DIALYSATE_PUMP_STATE_T state = DIALYSATE_PUMP_RAMP_UP_STATE; + + if ( TRUE == stepDialysatePumpToTargetSpeed( pumpId ) ) + { + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + resetPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); + } + else + { + resetPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, DIALYSATE_PUMP_MIN_PRESSURE_PSI ); + } + state = DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The stepDialysatePumpToTargetSpeed function steps current step speed + * toward target speed for the given dialysate pump,with predefined step increase. + * @details \b Inputs: pumpTargetSpeed + * @details \b Outputs: currentPumpSpeed + * @param pumpId dialysate pump id to increase current step speed + * @return TRUE if the pump has reached to target otherwise, FALSE + *************************************************************************/ +static BOOL stepDialysatePumpToTargetSpeed( DIALYSATE_PUMPS_T pumpId ) +{ + F32 speedIncrease = 0.0F; + BOOL hasTgtBeenReached = FALSE; + F32 currentToTargetDiff = fabs( getDialysatePumpTargetSpeed( pumpId ) - dialysatePumps[ pumpId ].currentPumpSpeed ); + + if ( currentToTargetDiff > NEARLY_ZERO ) + { + if ( currentToTargetDiff > DIALYSATE_PUMP_SPEED_INCREMENT ) + { + speedIncrease = DIALYSATE_PUMP_SPEED_INCREMENT; + } + else + { + speedIncrease = currentToTargetDiff; + hasTgtBeenReached = TRUE; + } + + // Subtract current speed when target speed is smaller + if ( getDialysatePumpTargetSpeed( pumpId ) < dialysatePumps[ pumpId ].currentPumpSpeed ) + { + speedIncrease *= -1.0F; + } + + dialysatePumps[ pumpId ].currentPumpSpeed += speedIncrease; + + // If the pump's target speed is set to be 0, do not ramp down set it to zero immediately + if ( getDialysatePumpTargetSpeed( pumpId ) < NEARLY_ZERO ) + { + dialysatePumps[ pumpId ].currentPumpSpeed = 0.0F; + } + } + + if ( dialysatePumps[ pumpId ].currentPumpSpeed > NEARLY_ZERO ) + { + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + // Set fresh dialyate pump speed + setFPGAFreshDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); + } + else + { + // Set spent dialyate pump speed + setFPGASpentDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); + } + } + + return hasTgtBeenReached; +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpControlToTargetState function handles the control to + * target state of the dialysate pump controller state machine. + * @details \b Inputs: controlTimerCounter + * @details \b Outputs: currentPumpSpeed, controlTimerCounter + * @return next state of the controller state machine + *************************************************************************/ +static DIALYSATE_PUMP_STATE_T handleDialysatePumpControlToTargetState( DIALYSATE_PUMPS_T pumpId ) +{ + DIALYSATE_PUMP_STATE_T state = DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE; + + // control at set interval + if ( ++dialysatePumps[ pumpId ].controlTimerCounter >= DP_CONTROL_INTERVAL ) + { + // Control based on the measured and target pressure + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + F32 measuredPressure = getFilteredPressure( PRESSURE_SENSOR_FRESH_DIALYSATE ); + F32 targetPressure = getDialysatePumpTargetPressure( pumpId ); + + F32 control = runPIController( PI_CONTROLLER_ID_FRESH_DIALYSATE_PUMP, targetPressure, measuredPressure ); + // TODO : get the equivalent speed for the given control + F32 newSpeed = control * ( MAX_DIALYSATE_PUMP_RPM / DIALYSATE_PUMP_MAX_PRESSURE_PSI ); + + //Apply speed limit + newSpeed = MIN( newSpeed, MAX_DIALYSATE_PUMP_RPM ); + newSpeed = MAX( newSpeed, MIN_DIALYSATE_PUMP_RPM ); + + dialysatePumps[ pumpId ].currentPumpSpeed = newSpeed; + //Set fresh dialyate pump speed + setFPGAFreshDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); + } + else + { + F32 measuredPressure = getFilteredPressure( PRESSURE_SENSOR_SPENT_DIALYSATE ); + F32 targetPressure = getDialysatePumpTargetPressure( pumpId ); + + F32 control = runPIController( PI_CONTROLLER_ID_SPENT_DIALYSATE_PUMP, targetPressure, measuredPressure ); + // TODO : get the equivalent speed for the given control + F32 newSpeed = control * ( MAX_DIALYSATE_PUMP_RPM / DIALYSATE_PUMP_MAX_PRESSURE_PSI ); + + //Apply speed limit + newSpeed = MIN( newSpeed, MAX_DIALYSATE_PUMP_RPM ); + newSpeed = MAX( newSpeed, MIN_DIALYSATE_PUMP_RPM ); + + dialysatePumps[ pumpId ].currentPumpSpeed = newSpeed; + //Set spent dialyate pump speed + setFPGASpentDialysatePumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); + } + dialysatePumps[ pumpId ].controlTimerCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The stopDialysatePump function sets the given dialysate pump rpm to zero and stops + * the pump. + * @details \b Inputs: dialysatePumps + * @details \b Outputs: dialysatePumps + * @param pumpId dialysate pump id to set the diaylsate pump control + * @return none + *************************************************************************/ +static void stopDialysatePump( DIALYSATE_PUMPS_T pumpId ) +{ + //Update control to stop the dialysate pump + if ( FRESH_DIALYSATE_PUMP == pumpId ) + { + // dialysate pump control run enable + dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; + setFPGAFreshDialysatePumpControl( dialysatePumps[ pumpId ].control ); + setFPGAFreshDialysatePumpSpeed( DIALYSATE_PUMP_SPEED_ZERO_RPM ); + } + else + { + dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; + setFPGASpentDialysatePumpControl( dialysatePumps[ pumpId ].control ); + setFPGASpentDialysatePumpSpeed( DIALYSATE_PUMP_SPEED_ZERO_RPM ); + } +} + +/*********************************************************************//** + * @brief + * The getDialysatePumpTargetSpeed function gets the current target speed for the given + * dialysate pump. + * @details \b Inputs: pumpTargetSpeed + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. + * @param pumpId dialysate pump id to get the current target speed + * @return the current target speed for the given dialysate pump. + *************************************************************************/ +F32 getDialysatePumpTargetSpeed( DIALYSATE_PUMPS_T pumpId ) +{ + F32 speed = 0.0F; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + speed = getF32OverrideValue( &dialysatePumps[ pumpId ].pumpTargetSpeed ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return speed; +} + +/*********************************************************************//** + * @brief + * The getDialysatePumpMeasuredSpeed function gets the measured speed for the given + * dialysate pump. + * @details \b Inputs: measuredPumpSpeed + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. + * @param pumpId dialysate pump id to get the measured speed + * @return the measured speed for the given dialysate pump. + *************************************************************************/ +F32 getDialysatePumpMeasuredSpeed( DIALYSATE_PUMPS_T pumpId ) +{ + F32 speed = 0.0F; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + speed = getF32OverrideValue( &dialysatePumps[ pumpId ].measuredPumpSpeed ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return speed; +} + +/*********************************************************************//** + * @brief + * The getDialysatePumpTargetPressure function gets the target pressure for + * the given dialysate pump. + * @details \b Inputs: pumpTargetPressure + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. + * @param pumpId dialysate pump id to get the target pressure + * @return the target pressure for the given dialysate pump. + *************************************************************************/ +F32 getDialysatePumpTargetPressure( DIALYSATE_PUMPS_T pumpId ) +{ + F32 pressure = 0.0F; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + pressure = getF32OverrideValue( &dialysatePumps[ pumpId ].pumpTargetPressure ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return pressure; +} + +/*********************************************************************//** + * @brief + * The getDialysatePumpMeasuredCurrentA function returns the given dialysate + * pump current feedback. + * @details \b Inputs: dialysatePumpMeasuredCurrentA + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. + * @return the given dialysate pump current feedback + *************************************************************************/ +F32 getDialysatePumpMeasuredCurrentA( DIALYSATE_PUMPS_T pumpId ) +{ + F32 current = 0.0F; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + current = getF32OverrideValue( &dialysatePumps[ pumpId ].dialysatePumpMeasuredCurrentA ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return current; +} + +/*********************************************************************//** + * @brief + * The getDialysatePumpMeasuredDirection function returns the given dialysate pump + * direction. + * @details \b Inputs: measuredDirection + * @details \b Outputs: none + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT when invalid pump ID is seen. + * @return the given dialysate pump direction + *************************************************************************/ +U32 getDialysatePumpMeasuredDirection( DIALYSATE_PUMPS_T pumpId ) +{ + U32 direction = 0; + + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) + { + direction = getU32OverrideValue( &dialysatePumps[ pumpId ].measuredDirection ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID, pumpId ); + } + + return direction; +} + +/*********************************************************************//** + * @brief + * The publishDialysatePumpsData function publishes dialysate pumps data at the set + * interval. + * @details \b Inputs: dialysatePumpDataPublicationTimerCounter,dialysatePumps + * @details \b Outputs: dialPump + * @details \b Message \Sent: MSG_ID_DIALYSATE_PUMPS_DATA to pusblish dialysate + * pumps data. + * @return none + *************************************************************************/ +static void publishDialysatePumpsData( void ) +{ + // publish Dialysate pump data on interval + if ( ++dialysatePumpDataPublicationTimerCounter >= getU32OverrideValue( &dialysatePumpDataPublishInterval ) ) + { + DIALYSATE_PUMPS_PUBLISH_DATA_T dialPump; + + // Populate the data structure for publication + dialPump.freshDialPumpTargetRPM = getDialysatePumpTargetSpeed( FRESH_DIALYSATE_PUMP ); + dialPump.spentDialPumpTargetRPM = getDialysatePumpTargetSpeed( SPENT_DIALYSATE_PUMP ); + dialPump.freshDialPumpMeasuredSpeed = getDialysatePumpMeasuredSpeed( FRESH_DIALYSATE_PUMP ); + dialPump.spentDialPumpMeasuredSpeed = getDialysatePumpMeasuredSpeed( SPENT_DIALYSATE_PUMP ); + dialPump.freshDialPumpCurrentSpeed = dialysatePumps[ FRESH_DIALYSATE_PUMP ].currentPumpSpeed; + dialPump.spentDialPumpCurrentSpeed = dialysatePumps[ SPENT_DIALYSATE_PUMP ].currentPumpSpeed; + dialPump.freshDialPumpState = (U32)dialysatePumps[ FRESH_DIALYSATE_PUMP ].dialysatePumpState; + dialPump.spentDialPumpState = (U32)dialysatePumps[ SPENT_DIALYSATE_PUMP ].dialysatePumpState; + dialPump.freshDialPumpTargetPressure = getDialysatePumpTargetPressure( FRESH_DIALYSATE_PUMP ); + dialPump.spentDialPumpTargetPressure = getDialysatePumpTargetPressure( SPENT_DIALYSATE_PUMP ); + dialPump.freshDialPumpMeasuredPressure = getFilteredPressure( PRESSURE_SENSOR_FRESH_DIALYSATE ); + dialPump.spentDialPumpMeasuredPressure = getFilteredPressure( PRESSURE_SENSOR_SPENT_DIALYSATE ); + dialPump.freshDialPumpMeasuredCurrent = getDialysatePumpMeasuredCurrentA( FRESH_DIALYSATE_PUMP ); + dialPump.spentDialPumpMeasuredCurrent = getDialysatePumpMeasuredCurrentA( SPENT_DIALYSATE_PUMP ); + dialPump.freshDialPumpControl = (U32)dialysatePumps[ FRESH_DIALYSATE_PUMP ].control; + dialPump.spentDialPumpControl = (U32)dialysatePumps[ SPENT_DIALYSATE_PUMP ].control; + dialPump.freshDialPumpDirErrCnt = dialysatePumps[ FRESH_DIALYSATE_PUMP ].directionErrorCount; + dialPump.spentDialPumpDirErrCnt = dialysatePumps[ SPENT_DIALYSATE_PUMP ].directionErrorCount; + dialPump.freshDialPumpMeasuredDir = getDialysatePumpMeasuredDirection( FRESH_DIALYSATE_PUMP ); + dialPump.spentDialPumpMeasuredDir = getDialysatePumpMeasuredDirection( SPENT_DIALYSATE_PUMP ); + + broadcastData( MSG_ID_DIALYSATE_PUMPS_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&dialPump, sizeof( DIALYSATE_PUMPS_PUBLISH_DATA_T ) ); + + dialysatePumpDataPublicationTimerCounter = 0; + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testDialysatePumpsDataPublishIntervalOverride function overrides the + * dialysate pump data publish interval. + * @details \b Inputs: dialysatePumpDataPublishInterval + * @details \b Outputs: dialysatePumpDataPublishInterval + * @param Override message from Dialin which includes the interval + * (in ms) to override the dialysate pump data broadcast interval to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpsDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &dialysatePumpDataPublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testDialysatePumpTargetSpeedOverride function overrides the target + * speed value of given dialysate pump id. + * @details \b Inputs: none + * @details \b Outputs: pumpTargetSpeed + * @param message Override message from Dialin which includes an ID of + * the pump to override and the state to override the pump to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpTargetSpeedOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &dialysatePumps[0].pumpTargetSpeed, NUM_OF_DIALYSATE_PUMPS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testDialysatePumpMeasuredSpeedOverride function overrides the measured + * speed value of given dialysate pump id. + * @details \b Inputs: none + * @details \b Outputs: measuredPumpSpeed + * @param message Override message from Dialin which includes an ID of + * the pump to override and the state to override the pump to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpMeasuredSpeedOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &dialysatePumps[0].measuredPumpSpeed, NUM_OF_DIALYSATE_PUMPS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testDialysatePumpTargetPressureOverride function overrides the target + * pressure value of given dialysate pump id. + * @details \b Inputs: none + * @details \b Outputs: pumpTargetPressure + * @param message Override message from Dialin which includes an ID of + * the pump to override and the state to override the pump to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpTargetPressureOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &dialysatePumps[0].pumpTargetPressure, NUM_OF_DIALYSATE_PUMPS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testDialysatePumpMeasuredCurrentOverride function overrides the measured + * current value of given dialysate pump id. + * @details \b Inputs: none + * @details \b Outputs: dialysatePumpMeasuredCurrentA + * @param message Override message from Dialin which includes an ID of + * the pump to override and the state to override the pump to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpMeasuredCurrentOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &dialysatePumps[0].dialysatePumpMeasuredCurrentA, NUM_OF_DIALYSATE_PUMPS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testDialysatePumpMeasuredDirectionOverride function overrides the measured + * direction value of given dialysate pump id. + * @details \b Inputs: none + * @details \b Outputs: measuredDirection + * @param message Override message from Dialin which includes an ID of + * the pump to override and the state to override the pump to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDialysatePumpMeasuredDirectionOverride( MESSAGE_T *message ) +{ + BOOL result = u32ArrayOverride( message, &dialysatePumps[0].measuredDirection, NUM_OF_DIALYSATE_PUMPS - 1, 0, DIALYSATE_PUMP_FORWARD_DIR ); + + return result; +} + +/**@}*/ Index: firmware/App/Controllers/DialysatePumps.h =================================================================== diff -u --- firmware/App/Controllers/DialysatePumps.h (revision 0) +++ firmware/App/Controllers/DialysatePumps.h (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -0,0 +1,97 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file DialysatePumps.h +* +* @author (last) Vinayakam Mani +* @date (last) 02-Sep-2024 +* +* @author (original) Vinayakam Mani +* @date (original) 02-Sep-2024 +* +***************************************************************************/ + +#ifndef __DIALYSATE_PUMPS_H__ +#define __DIALYSATE_PUMPS_H__ + +#include "DDCommon.h" + +/** + * @defgroup DialysatePumps DialysatePumps + * @brief Dialysate Pumps monitor/controller module. Controls and monitors the dialysate pumps. + * Dialysate pump manufacturer: Diener Silencer Series Gear Pumps, PN: 01483-PM-3-RA. + * The pump shall produce flow rates of 50-4500 ml/min. + * + * @addtogroup DialysatePumps + * @{ + */ + +// ********** public definitions ********** + +#define MIN_DIALYSATE_PUMP_RPM 300 ///< Minimum RPM target for dialysate pump (though zero is allowed if turning pump off). +#define MAX_DIALYSATE_PUMP_RPM 4500 ///< Maximum RPM target for dialysate pump. + +/// Enumeration of dialysate pumps. +typedef enum DialysatePumps +{ + FRESH_DIALYSATE_PUMP = 0, ///< Fresh dialysate pump + DIALYSATE_PUMPS_FIRST = FRESH_DIALYSATE_PUMP, ///< First dialysate pump in list + SPENT_DIALYSATE_PUMP, ///< Spent dialysate pump + NUM_OF_DIALYSATE_PUMPS ///< Number of dialysate pumps +} DIALYSATE_PUMPS_T; + +/// Dialysate pumps data publish +typedef struct +{ + F32 freshDialPumpTargetRPM; ///< Fresh dialysate pump speed set point. + F32 spentDialPumpTargetRPM; ///< Spent dialysate pump speed set point. + F32 freshDialPumpMeasuredSpeed; ///< Fresh dialysate pump measured speed. + F32 spentDialPumpMeasuredSpeed; ///< Spent dialysate pump measured speed. + F32 freshDialPumpCurrentSpeed; ///< Fresh dialysate pump current speed. + F32 spentDialPumpCurrentSpeed; ///< Spent dialysate pump current speed. + U32 freshDialPumpState; ///< Fresh dialysate pump state machine state. + U32 spentDialPumpState; ///< Spent state machine state. + F32 freshDialPumpTargetPressure; ///< Fresh dialysate pump target pressure. + F32 spentDialPumpTargetPressure; ///< Spent dialysate pump target pressure. + F32 freshDialPumpMeasuredPressure; ///< Fresh dialysate pump measured pressure. + F32 spentDialPumpMeasuredPressure; ///< Spent dialysate pump measured pressure. + F32 freshDialPumpMeasuredCurrent; ///< Fresh dialysate pump measured current. + F32 spentDialPumpMeasuredCurrent; ///< Spent dialysate pump measured current. + U32 freshDialPumpControl; ///< Fresh dialysate pump control to check run/stop state. + U32 spentDialPumpControl; ///< Spent dialysate pump control to check run/stop state. + U32 freshDialPumpDirErrCnt; ///< Fresh dialysate pump direction error count. + U32 spentDialPumpDirErrCnt; ///< Spent dialysate pump direction error count. + U32 freshDialPumpMeasuredDir; ///< Fresh dialysate pump direction. + U32 spentDialPumpMeasuredDir; ///< Spent dialysate pump direction. +} DIALYSATE_PUMPS_PUBLISH_DATA_T; + +// ********** public function prototypes ********** + +void initDialysatePump( void ); +void execDialysatePumpMonitor( void ); +void execDialysatePumpController( void ); +SELF_TEST_STATUS_T execDialysatePumpSelfTest( void ); + +F32 getDialysatePumpTargetSpeed( DIALYSATE_PUMPS_T pumpId ); +F32 getDialysatePumpMeasuredSpeed( DIALYSATE_PUMPS_T pumpId ); +F32 getDialysatePumpTargetPressure( DIALYSATE_PUMPS_T pumpId ); +F32 getDialysatePumpMeasuredCurrentA( DIALYSATE_PUMPS_T pumpId ); +U32 getDialysatePumpMeasuredDirection( DIALYSATE_PUMPS_T pumpId ); +BOOL isDialysatePumpOn( DIALYSATE_PUMPS_T pumpId ); +void signalDialysatePumpHardStop( DIALYSATE_PUMPS_T pumpId ); +BOOL setDialysatePumpTargetRPM( DIALYSATE_PUMPS_T pumpId, U32 rpm ); + +BOOL testDialysatePumpsDataPublishIntervalOverride( MESSAGE_T *message ); +BOOL testDialysatePumpTargetSpeedOverride( MESSAGE_T *message ); +BOOL testDialysatePumpMeasuredSpeedOverride( MESSAGE_T *message ); +BOOL testDialysatePumpTargetPressureOverride( MESSAGE_T *message ); +BOOL testDialysatePumpMeasuredCurrentOverride( MESSAGE_T *message ); +BOOL testDialysatePumpMeasuredDirectionOverride( MESSAGE_T *message ); + +/**@}*/ + +#endif Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -rfefb47e88a5285e99498efb830fdceb9e95c2c3e -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision fefb47e88a5285e99498efb830fdceb9e95c2c3e) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -118,6 +118,12 @@ SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED1 = 87, SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED2 = 88, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE = 89, + SW_FAULT_ID_PI_CTRL_INVALID_CONTROLLER = 90, + SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL = 91, + SW_FAULT_ID_PI_CTRL_INVALID_STEP_LIMIT = 92, + SW_FAULT_ID_DIALYSATE_PUMP_INVALID_RPM_SELECTED = 93, + SW_FAULT_ID_DIALYSATE_PUMP_EXEC_INVALID_STATE = 94, + SW_FAULT_ID_DIALYSATE_PUMP_INVALID_PUMP_ID = 95, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/FpgaDD.c =================================================================== diff -u -rfefb47e88a5285e99498efb830fdceb9e95c2c3e -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision fefb47e88a5285e99498efb830fdceb9e95c2c3e) +++ firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -87,6 +87,9 @@ #define FPGA_READ_V3_START_BYTE_NUM 256 ///< FPGA V3 read sensors start byte number. #define FPGA_READ_V3_END_BYTE_NUM 430 ///< FPGA V3 read sensors end byte number. +#define FPGA_DGP_PUMP_ERROR_BIT 0x01 ///< Fresh dialysate pump error bit mask. +#define FPGA_SDP_PUMP_ERROR_BIT 0x02 ///< Spent dialysate pump error bit mask. + /// FPGA size of V3 read bytes. #define FPGA_SIZE_OF_V3_READ_BYTES ( FPGA_READ_V3_END_BYTE_NUM - FPGA_READ_V3_START_BYTE_NUM ) @@ -205,6 +208,13 @@ U32 fpgaBaroPressure; ///< Reg 396. Barometric sensor pressure value U32 fpgaBaroTemperature; ///< Reg 400. Barometric sensor temperature sensor + U16 fpgaDGPMeasuredSpeed; ///< Reg 404. Fresh dialysate pump measured speed + U16 fpgaSDPMeasuredSpeed; ///< Reg 406. Spent dialysate pump measured speed + U08 fpgaDGPSDPPumpStatus; ///< Reg 408. Dialysate pumps Error status + U16 fpgaDGPCurrentFeedback; ///< Reg 409. Fresh dialysate pump current feedback + U16 fpgaSDPCurrentFeedback; ///< Reg 411. Spent dialysate pump current feedback + U08 fpgaDGPHallStatus; ///< Reg 413. Fresh dialysate pump hall sensor direction status + U08 fpgaSDPHallStatus; ///< Reg 413. Spent dialysate pump hall sensor direction status } DD_FPGA_SENSORS_T; typedef struct @@ -473,56 +483,70 @@ /*********************************************************************//** * @brief - * The setFPGADialysateOutPumpSpeed function sets the speed period for - * dialysate out pump (SDP). + * The setFPGASpentDialysatePumpSpeed function sets the speed for the + * spent dialysate pump (SDP). * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaSDPSpeed - * @param speed The dialysate out pump speed period + * @param speed The spent dialysate pump speed * @return none *************************************************************************/ -void setFPGADialysateOutPumpSpeed( U16 speed ) +void setFPGASpentDialysatePumpSpeed( U16 speed ) { fpgaActuatorSetPoints.fpgaSDPSpeed = speed; } /*********************************************************************//** * @brief - * The setFPGADialysateInPumpSpeed function sets the speed period for - * dialysate In pump (DGP). + * The setFPGAFreshDialysatePumpSpeed function sets the speed for the + * fresh dialysate pump (DGP). * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaDGPSpeed - * @param speed The dialysate In pump speed period + * @param speed The fresh dialysate pump speed * @return none *************************************************************************/ -void setFPGADialysateInPumpSpeed( U16 speed ) +void setFPGAFreshDialysatePumpSpeed( U16 speed ) { fpgaActuatorSetPoints.fpgaDGPSpeed = speed; } /*********************************************************************//** * @brief - * The setFPGADialysateOutPumpControl function sets the controls for - * dialysate out pump (SDP). bit definitions To be defined(TBD) + * The setFPGASpentDialysatePumpControl function sets the controls for + * dialysate out pump (SDP). + * bit 7: TBD + * bit 6: TBD + * bit 5: TBD + * bit 4: TBD + * bit 3: TBD + * bit 1-2: TBD + * bit 0: Run (1), stop (0) * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaSDPControl * @param control The dialysate out pump controls * @return none *************************************************************************/ -void setFPGADialysateOutPumpControl( U08 control ) +void setFPGASpentDialysatePumpControl( U08 control ) { fpgaActuatorSetPoints.fpgaSDPControl = control; } /*********************************************************************//** * @brief - * The setFPGADialysateInPumpControl function sets the controls for - * dialysate In pump (DGP). bit definitions To be defined(TBD) + * The setFPGAFreshDialysatePumpControl function sets the controls for + * dialysate In pump (DGP). + * bit 7: TBD + * bit 6: TBD + * bit 5: TBD + * bit 4: TBD + * bit 3: TBD + * bit 1-2: TBD + * bit 0: Run (1), stop (0) * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaDGPControl * @param control The dialysate In pump controls * @return none *************************************************************************/ -void setFPGADialysateInPumpControl( U08 control ) +void setFPGAFreshDialysatePumpControl( U08 control ) { fpgaActuatorSetPoints.fpgaDGPControl = control; } @@ -1218,44 +1242,162 @@ /*********************************************************************//** * @brief - * The getFPGADialysateOutPumpControl function gets the status of the + * The getFPGASpentDialysatePumpControl function gets the status of the * dialysate out pump control status bits. * bit 7: TBD * bit 6: TBD * bit 5: TBD * bit 4: TBD * bit 3: TBD - * bit 0-2: TBD + * bit 1-2: TBD + * bit 0: Run (1), stop (0) * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaSDPControl * @return Dialysate Out pump control status bit *************************************************************************/ -U08 getFPGADialysateOutPumpControl( void ) +U08 getFPGASpentDialysatePumpControl( void ) { return fpgaActuatorSetPoints.fpgaSDPControl; } /*********************************************************************//** * @brief - * The getFPGADialysateInPumpControl function gets the status of the + * The getFPGAFreshDialysatePumpControl function gets the status of the * dialysate Inlet pump control status bits. * bit 7: TBD * bit 6: TBD * bit 5: TBD * bit 4: TBD * bit 3: TBD - * bit 0-2: TBD + * bit 1-2: TBD + * bit 0: Run (1), stop (0) * @details \b Inputs: none * @details \b Outputs: fpgaActuatorSetPoints.fpgaDGPControl * @return Dialysate Inlet pump control status bit *************************************************************************/ -U08 getFPGADialysateInPumpControl( void ) +U08 getFPGAFreshDialysatePumpControl( void ) { return fpgaActuatorSetPoints.fpgaDGPControl; } /*********************************************************************//** * @brief + * The getFPGASpentDialysatePumpSpeed function gets the spent dialysate + * pump speed. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaSDPMeasuredSpeed + * @return Spent dialysate pump measured speed. + *************************************************************************/ +U16 getFPGASpentDialysatePumpSpeed( void ) +{ + return fpgaSensorReadings.fpgaSDPMeasuredSpeed; +} + +/*********************************************************************//** + * @brief + * The getFPGAFreshDialysatePumpSpeed function gets the fresh dialysate + * pump speed. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaDGPMeasuredSpeed + * @return fresh dialysate pump measured speed. + *************************************************************************/ +U16 getFPGAFreshDialysatePumpSpeed( void ) +{ + return fpgaSensorReadings.fpgaDGPMeasuredSpeed; +} + +/*********************************************************************//** + * @brief + * The getFPGAFreshDialysatePumpErrorStatus function gets the fresh dialysate + * pump error status. + * bit 7-2: TBD + * bit 1 : spent dialysate pump error (1), no error(0) + * bit 0 : fresh dialysate pump error (1), no error(0) + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaDGPSDPPumpStatus + * @return fresh dialysate pump error status. + *************************************************************************/ +BOOL getFPGAFreshDialysatePumpErrorStatus( void ) +{ + U08 mask = fpgaSensorReadings.fpgaDGPSDPPumpStatus & FPGA_DGP_PUMP_ERROR_BIT; + BOOL result = ( mask > 0 ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getFPGASpentDialysatePumpErrorStatus function gets the spent dialysate + * pump error status. + * bit 7-2: TBD + * bit 1 : spent dialysate pump error (1), no error(0) + * bit 0 : fresh dialysate pump error (1), no error(0) + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaDGPSDPPumpStatus + * @return spent dialysate pump error status. + *************************************************************************/ +BOOL getFPGASpentDialysatePumpErrorStatus( void ) +{ + U08 mask = fpgaSensorReadings.fpgaDGPSDPPumpStatus & FPGA_SDP_PUMP_ERROR_BIT; + BOOL result = ( mask > 0 ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getFPGAFreshDialysatePumpCurrentFeedback function gets the fresh dialysate + * pump current consumption. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaDGPCurrentFeedback + * @return fresh dialysate pump measured current. + *************************************************************************/ +U16 getFPGAFreshDialysatePumpCurrentFeedback( void ) +{ + return fpgaSensorReadings.fpgaDGPCurrentFeedback; +} + +/*********************************************************************//** + * @brief + * The getFPGASpentDialysatePumpCurrentFeedback function gets the spent dialysate + * pump current consumption. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaSDPCurrentFeedback + * @return spent dialysate pump measured current. + *************************************************************************/ +U16 getFPGASpentDialysatePumpCurrentFeedback( void ) +{ + return fpgaSensorReadings.fpgaSDPCurrentFeedback; +} + +/*********************************************************************//** + * @brief + * The getFPGAFreshDialysatePumpHallDirectionStatus function gets the fresh dialysate + * pump hall sensor based direction error status. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaDGPHallStatus + * @return fresh dialysate pump hall sensor based direction status. + *************************************************************************/ +U08 getFPGAFreshDialysatePumpHallDirectionStatus( void ) +{ + return fpgaSensorReadings.fpgaDGPHallStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGASpentDialysatePumpHallDirectionStatus function gets the spent dialysate + * pump hall sensor based direction error status. + * @details \b Inputs: none + * @details \b Outputs: fpgaSensorReadings.fpgaSDPHallStatus + * @return spent dialysate pump hall sensor based direction status. + *************************************************************************/ +U08 getFPGASpentDialysatePumpHallDirectionStatus( void ) +{ + return fpgaSensorReadings.fpgaSDPHallStatus; +} + +/*********************************************************************//** + * @brief * The getFPGAAcidPumpControlStatus function gets the status of the * acid pump control status bits. * bit 7: Park (set in different function) Index: firmware/App/Services/FpgaDD.h =================================================================== diff -u -rfefb47e88a5285e99498efb830fdceb9e95c2c3e -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Services/FpgaDD.h (.../FpgaDD.h) (revision fefb47e88a5285e99498efb830fdceb9e95c2c3e) +++ firmware/App/Services/FpgaDD.h (.../FpgaDD.h) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -137,12 +137,21 @@ U16 getFPGACPAHallSensePulseWidth( void ); U16 getFPGACPBHallSensePulseWidth( void ); -void setFPGADialysateOutPumpSpeed( U16 speed ); -void setFPGADialysateOutPumpControl( U08 control ); -void setFPGADialysateInPumpControl( U08 control ); +void setFPGASpentDialysatePumpSpeed( U16 speed ); +void setFPGAFreshDialysatePumpSpeed( U16 speed ); +void setFPGASpentDialysatePumpControl( U08 control ); +void setFPGAFreshDialysatePumpControl( U08 control ); -U08 getFPGADialysateOutPumpControl( void ); -U08 getFPGADialysateInPumpControl( void ); +U08 getFPGASpentDialysatePumpControl( void ); +U08 getFPGAFreshDialysatePumpControl( void ); +U16 getFPGASpentDialysatePumpSpeed( void ); +U16 getFPGAFreshDialysatePumpSpeed( void ); +BOOL getFPGAFreshDialysatePumpErrorStatus( void ); +BOOL getFPGASpentDialysatePumpErrorStatus( void ); +U16 getFPGAFreshDialysatePumpCurrentFeedback( void ); +U16 getFPGASpentDialysatePumpCurrentFeedback( void ); +U08 getFPGAFreshDialysatePumpHallDirectionStatus( void ); +U08 getFPGASpentDialysatePumpHallDirectionStatus( void ); //Pressure sensor U08 getFPGAPnReadCount( void ); Index: firmware/App/Services/Messaging.c =================================================================== diff -u -re7fe0454b5b2d39009dc784dc8c156856df8bc86 -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision e7fe0454b5b2d39009dc784dc8c156856df8bc86) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -21,6 +21,7 @@ #include "Conductivity.h" #include "ConcentratePumps.h" +#include "DialysatePumps.h" #include "Compatible.h" #include "Messaging.h" #include "OperationModes.h" @@ -104,6 +105,12 @@ MSG_ID_DD_TEMPERATURE_SENSOR_READ_COUNTER_OVERRIDE_REQUEST, MSG_ID_DD_TEMPERATURE_SENSOR_BARO_READ_COUNTER_OVERRIDE_REQUEST, MSG_ID_DD_TEMPERATURE_SENSOR_BARO_CRC_OVERRIDE_REQUEST, + MSG_ID_DD_DIALYSATE_PUMPS_PUBLISH_INTERVAL_OVERRIDE_REQUEST, //30 + MSG_ID_DD_DIALYSATE_PUMPS_TARGET_SPEED_OVERRIDE_REQUEST, + MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_SPEED_OVERRIDE_REQUEST, + MSG_ID_DD_DIALYSATE_PUMPS_TARGET_PRESSURE_OVERRIDE_REQUEST, + MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_CURRENT_OVERRIDE_REQUEST, + MSG_ID_DD_DIALYSATE_PUMPS_MEASURED_DIRECTION_OVERRIDE_REQUEST, //35 }; /// Message handling function table @@ -136,7 +143,13 @@ &testMeasuredTemperatureOverride, &testTemperatureReadCounterOverride, &testBaroTemperatureReadCounterOverride, - &testBaroTemperatureCRCOverride + &testBaroTemperatureCRCOverride, + &testDialysatePumpsDataPublishIntervalOverride, //30 + &testDialysatePumpTargetSpeedOverride, + &testDialysatePumpMeasuredSpeedOverride, + &testDialysatePumpTargetPressureOverride, + &testDialysatePumpMeasuredCurrentOverride, + &testDialysatePumpMeasuredDirectionOverride, //35 }; #define NUM_OF_FUNCTION_HANDLERS (sizeof(MSG_FUNCTION_HANDLERS) / sizeof(MsgFuncPtr)) Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r3a87ca0e2a722318216623d7e1f4c354c58c506c -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 3a87ca0e2a722318216623d7e1f4c354c58c506c) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -19,6 +19,7 @@ #include "lin.h" #include "ConcentratePumps.h" +#include "DialysatePumps.h" #include "Messaging.h" #include "OperationModes.h" #include "SystemCommDD.h" @@ -82,8 +83,8 @@ // Monitor thermistors state machine //execThermistors(); - // manage drain pump - // execDrainPumpController(); + // manage dialysate pump + execDialysatePumpController(); // manage concentrate pumps execConcentratePumpController(); Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -re3699de422fa3ba1b8145c4cc44257702c9e336f -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision e3699de422fa3ba1b8145c4cc44257702c9e336f) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -17,7 +17,8 @@ #include "gio.h" -#include "Conductivity.h" +#include "Conductivity.h" +#include "DialysatePumps.h" #include "FPGA.h" //#include "Heaters.h" #include "InternalADC.h" @@ -58,7 +59,7 @@ execFPGA( TRUE ); // Monitor internal ADC channels - //execInternalADC(); + execInternalADC(); // Monitor pressures execPressureSensor(); @@ -75,12 +76,9 @@ // Control valves execValves(); - // Monitor RO pump - //execROPumpMonitor(); + // Monitor dialysate pump + execDialysatePumpMonitor(); - // Monitor drain pump - //execDrainPumpMonitor(); - // Heaters monitor //execHeatersMonitor(); Index: firmware/source/sys_main.c =================================================================== diff -u -rfefb47e88a5285e99498efb830fdceb9e95c2c3e -rbbcdba8850dd6f6a53044eca6a5ece611654653a --- firmware/source/sys_main.c (.../sys_main.c) (revision fefb47e88a5285e99498efb830fdceb9e95c2c3e) +++ firmware/source/sys_main.c (.../sys_main.c) (revision bbcdba8850dd6f6a53044eca6a5ece611654653a) @@ -65,6 +65,7 @@ #include "Conductivity.h" #include "ConcentratePumps.h" #include "DDCommon.h" +#include "DialysatePumps.h" #include "FpgaDD.h" #include "Interrupts.h" #include "MsgQueues.h" @@ -164,6 +165,7 @@ initValves(); initTemperature(); initConcentratePump(); + initDialysatePump(); initCommBuffers(); initMsgQueues(); initSystemComm();