Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r111d91eb16612b02663397a2faa713f2a9bafe0c -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 111d91eb16612b02663397a2faa713f2a9bafe0c) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -79,7 +79,7 @@ static F32 totalSalineVolumeDelivered; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). static F32 bolusSalineVolumeDelivered; ///< Volume (mL) of current bolus delivered so far. static F32 bolusSalineVolumeDelivered_Safety; ///< Volume (mL) of current bolus delivered so far according to safety monitor. -static U32 bolusSalineMotorCount; ///< Blood pump motor rev count during saline bolus to calculate saline bolus volume independently for safety. +static S32 bolusSalineMotorCount; ///< Blood pump motor rev count during saline bolus to calculate saline bolus volume independently for safety. static U32 bolusSalineLastMotorCount; ///< Last blood pump count from last saline bolus volume update. static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. @@ -94,14 +94,14 @@ static UF_STATE_T handleUFStartState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); -static UF_STATE_T handleUFOffState( DIALYSIS_STATE_T *dialysisState ); -static UF_STATE_T handleUFCompletedState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); +static void startHeparinPump( void ); + static void checkUFAccuracyAndVolume( void ); static void updateUFVolumes( void ); @@ -201,7 +201,8 @@ setDialInPumpTargetFlowRate( setDialysateFlowRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); #endif setDialOutPumpTargetRate( setDialysateFlowRate + (S32)setUFRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // TODO - Heparin pump + // Start Heparin pump as appropriate + startHeparinPump(); // Tell DG to start heating dialysate cmdStartDGTrimmerHeater(); @@ -215,6 +216,42 @@ /*********************************************************************//** * @brief + * The startHeparinPump function sets the syringe pump running as appropriate + * when starting/resuming dialysis sub-mode. + * @details Inputs: Heparin treatment parameters, treatment time remaining + * @details Outputs: Syringe pump started/stopped as appropriate + * @return none + *************************************************************************/ +static void startHeparinPump( void ) +{ + HEPARIN_STATE_T currentHeparinState = getHeparinState(); + U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); + U32 minRem = getTreatmentTimeRemainingSecs() / SEC_PER_MIN; + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + + // Do not run syringe pump if no Heparin included in prescription or it was paused or if Heparin should be stopped at this stage of treatment + if ( ( minRem > preStop ) && ( HEPARIN_STATE_STOPPED == currentHeparinState ) ) + { + // If not done with bolus, start/resume bolus + if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) + { + startHeparinBolus(); // TODO - check return status + } + // Otherwise, start/resume continuous delivery + else + { + startHeparinContinuous(); // TODO - check return status + } + } + else + { + stopSyringePump(); + } +} + +/*********************************************************************//** + * @brief * The setDialysisParams function sets the dialysis treatment parameters. * This function should be called prior to beginning dialysis treatment * and when the user changes one or more parameters during treatment. @@ -261,7 +298,7 @@ setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // TODO - stop Heparin pump + stopSyringePump(); // Tell DG to stop heating dialysate cmdStopDGTrimmerHeater(); } @@ -392,7 +429,7 @@ * volume collected so far for current treatment. * @details Inputs: measUFVolume, measUFVolumeFromPriorReservoirs * @details Outputs: none - * @return currentUFState + * @return measUFVolume *************************************************************************/ F32 getUltrafiltrationVolumeCollected( void ) { @@ -403,6 +440,19 @@ /*********************************************************************//** * @brief + * The getUltrafiltrationReferenceVolume function gets the current ultrafiltration + * reference volume. + * @details Inputs: measUFVolume, measUFVolumeFromPriorReservoirs + * @details Outputs: none + * @return refUFVolume + *************************************************************************/ +F32 getUltrafiltrationReferenceVolume( void ) +{ + return refUFVolume; +} + +/*********************************************************************//** + * @brief * The pauseUF function pauses ultrafiltration. * @details Inputs: currentDialysisState, currentUFState * @details Outputs: currentUFState, outlet pump set point @@ -446,8 +496,6 @@ // Send response w/ reason code if rejected sendUFPauseResumeResponse( result, rejectReason, currentUFState ); - // Send state data immediately for UI update - broadcastTreatmentTimeAndState(); return result; } @@ -474,7 +522,7 @@ setDialOutPumpTargetRate( setDialysateFlowRate + FLOAT_TO_INT_WITH_ROUND( setUFRate ), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); // Restart UF time accumulation for reference volume calculation lastUFTimeStamp = getMSTimerCount(); - // Go to UF paused state + // Go to UF running state currentUFState = UF_RUNNING_STATE; } else @@ -552,7 +600,22 @@ static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ) { DIALYSIS_STATE_T result = DIALYSIS_UF_STATE; + U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); + U32 minRem = getTreatmentTimeRemainingSecs() / SEC_PER_MIN; + // Stop Heparin delivery if we have reached Heparin pre-stop point + if ( getTreatmentTimeRemainingSecs() < preStop ) + { + stopSyringePump(); + setHeparinCompleted(); + } + // TODO - find a better way to start continuous delivery after bolus completes + if ( HEPARIN_STATE_STOPPED == getHeparinState() ) + { + startHeparinPump(); + } + + // Handle current ultrafiltration state switch ( currentUFState ) { case UF_START_STATE: @@ -567,17 +630,9 @@ currentUFState = handleUFRunningState( &result ); break; - case UF_OFF_STATE: - currentUFState = handleUFOffState( &result ); - break; - - case UF_COMPLETED_STATE: - currentUFState = handleUFCompletedState( &result ); - break; - default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_UF_STATE, currentUFState ) - currentUFState = UF_COMPLETED_STATE; + currentUFState = UF_PAUSED_STATE; break; } @@ -637,16 +692,9 @@ { UF_STATE_T result; - if ( maxUFVolumeML < NEARLY_ZERO ) - { - result = UF_OFF_STATE; - } - else - { - lastUFTimeStamp = getMSTimerCount(); - uFTimeMS = 0; - result = UF_RUNNING_STATE; - } + lastUFTimeStamp = getMSTimerCount(); + uFTimeMS = 0; + result = UF_RUNNING_STATE; return result; } @@ -681,17 +729,6 @@ salineBolusStartRequested = FALSE; } } - // Handle auto-resume after saline bolus - else if ( TRUE == salineBolusAutoResumeUF ) - { - salineBolusAutoResumeUF = FALSE; - // Set outlet pump to dialysate rate + set UF rate - setDialOutPumpTargetRate( setDialysateFlowRate + FLOAT_TO_INT_WITH_ROUND( setUFRate ), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); - // Restart UF time accumulation for reference volume calculation - lastUFTimeStamp = getMSTimerCount(); - // Resume UF - result = UF_RUNNING_STATE; - } return result; } @@ -719,16 +756,17 @@ // Update UF ref volume in UF running state only refUFVolume += ( ( (F32)msSinceLast / MS_PER_SECOND ) / SEC_PER_MIN ) * setUFRate; - // Calculate UF volumes and provide to dialysate outlet pump controller - updateUFVolumes(); - - // If we have reached target UF volume, UF is complete + // If we have reached target UF volume, UF is complete - set UF rate to zero for remainder of treatment if ( refUFVolume >= maxUFVolumeML ) { - result = UF_COMPLETED_STATE; + setUFRate = 0.0; } + + // Calculate UF volumes and provide to dialysate outlet pump controller + updateUFVolumes(); + // Handle saline bolus start request from user - else if ( TRUE == salineBolusStartRequested ) + if ( TRUE == salineBolusStartRequested ) { if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) { @@ -750,74 +788,6 @@ /*********************************************************************//** * @brief - * The handleUFCompletedOrOffState function handles the UF Off state - * of the ultrafiltration state machine. - * @details Inputs: none - * @details Outputs: UF volumes updated and provided to DPo pump controller. - * @param dialysisState next dialysis state - * @return next ultrafiltration state - *************************************************************************/ -static UF_STATE_T handleUFOffState( DIALYSIS_STATE_T *dialysisState ) -{ - UF_STATE_T result = UF_OFF_STATE; - - // Calculate UF volumes and provide to dialysate outlet pump controller - updateUFVolumes(); - - // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) - { - salineBolusAutoResumeUF = FALSE; - // Go to saline bolus state - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) - { - *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - } - else - { - salineBolusStartRequested = FALSE; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleUFCompletedState function handles the UF Completed - * state of the ultrafiltration state machine. This is a terminal state. - * @details Inputs: none - * @details Outputs: UF volumes updated and provided to DPo pump controller. - * @param dialysisState next dialysis state - * @return next ultrafiltration state - *************************************************************************/ -static UF_STATE_T handleUFCompletedState( DIALYSIS_STATE_T *dialysisState ) -{ - UF_STATE_T result = UF_COMPLETED_STATE; - - // Calculate UF volumes and provide to dialysate outlet pump controller - updateUFVolumes(); - - // Handle saline bolus start request from user - if ( TRUE == salineBolusStartRequested ) - { - salineBolusAutoResumeUF = FALSE; - // Go to saline bolus state - if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) - { - *dialysisState = DIALYSIS_SALINE_BOLUS_STATE; - } - else - { - salineBolusStartRequested = FALSE; - } - } - - return result; -} - -/*********************************************************************//** - * @brief * The handleSalineBolusIdleState function handles the idle state of the * saline bolus state machine. * @details Inputs: none @@ -834,15 +804,10 @@ { salineBolusStartRequested = FALSE; // Cmd all pumps to stop -#ifndef RUN_PUMPS_OPEN_LOOP setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); -#else - setBloodPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); - setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); -#endif + stopSyringePump(); // Begin saline bolus result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; } @@ -913,26 +878,21 @@ F32 bolusTargetVolume = (F32)getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); F32 bldFlowRate = getMeasuredBloodFlowRate(); // TODO - should I use raw flow instead of filtered here??? F32 volSinceLastUpdateMl = bldFlowRate * timeSinceLastVolumeUpdateMin; - U32 bldPumpMotorCount = getBloodPumpMotorCount(); - U32 bldPumpMotorDelta = u32DiffWithWrap( bolusSalineLastMotorCount, bldPumpMotorCount ); // Update saline bolus volumes bolusSalineLastVolumeTimeStamp = getMSTimerCount(); bolusSalineVolumeDelivered += volSinceLastUpdateMl; totalSalineVolumeDelivered += volSinceLastUpdateMl; - bolusSalineMotorCount += bldPumpMotorDelta; - bolusSalineLastMotorCount = bldPumpMotorCount; - bolusSalineVolumeDelivered_Safety = ( (F32)bolusSalineMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc + bolusSalineMotorCount = u32BiDiffWithWrap( bolusSalineLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; + bolusSalineVolumeDelivered_Safety = ( (F32)bolusSalineMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc (from PBA). -#ifndef DISABLE_SALINE_BOLUS_CHECKS // Check for empty saline bag per arterial line pressure if ( TRUE == isSalineBagEmpty() ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_EMPTY_SALINE_BAG, getMeasuredArterialPressure() ); errorFound = TRUE; result = SALINE_BOLUS_STATE_IDLE; } -#endif // Determine if we have reached maximum saline delivery volume if ( ( totalSalineVolumeDelivered >= (F32)MAX_SALINE_VOLUME_DELIVERED ) ) @@ -947,7 +907,7 @@ // If safety thinks we have under-delivered the bolus, throw a fault if ( bolusSalineVolumeDelivered_Safety < ( bolusTargetVolume * MIN_SALINE_BOLUS_VOLUME_PCT ) ) { -#ifndef DISABLE_SALINE_BOLUS_CHECKS +#ifndef DISABLE_PUMP_FLOW_CHECKS SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); errorFound = TRUE; #endif @@ -963,7 +923,7 @@ // Determine if safety thinks we have over-delivered the bolus else if ( bolusSalineVolumeDelivered_Safety > ( bolusTargetVolume * MAX_SALINE_BOLUS_VOLUME_PCT ) ) { -#ifndef DISABLE_SALINE_BOLUS_CHECKS +#ifndef DISABLE_PUMP_FLOW_CHECKS SET_ALARM_WITH_2_F32_DATA( ALARM_ID_SALINE_BOLUS_VOLUME_CHECK_FAILURE, bolusTargetVolume, bolusSalineVolumeDelivered_Safety ); errorFound = TRUE; result = SALINE_BOLUS_STATE_IDLE; @@ -989,6 +949,7 @@ // Resume UF if appropriate if ( TRUE == salineBolusAutoResumeUF ) { + salineBolusAutoResumeUF = FALSE; currentUFState = UF_RUNNING_STATE; } // Resume dialysis @@ -1034,7 +995,7 @@ { SALINE_BOLUS_DATA_PAYLOAD_T data; - data.maxSalineVolumeMl = MAX_SALINE_VOLUME_DELIVERED; + data.tgtSalineVolumeMl = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); data.cumSalineVolumeMl = totalSalineVolumeDelivered; data.bolSalineVolumeMl = bolusSalineVolumeDelivered; broadcastSalineBolusData( data ); @@ -1091,7 +1052,8 @@ static void updateUFVolumes( void ) { DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); - F32 latestResVolume = getReservoirWeightSmallFilter( activeRes ); + LOAD_CELL_ID_T lc = ( activeRes == DG_RESERVOIR_1 ? LOAD_CELL_RESERVOIR_1_PRIMARY : LOAD_CELL_RESERVOIR_2_PRIMARY ); + F32 latestResVolume = getLoadCellWeight( lc ); #ifndef DISABLE_UF_ALARMS F32 deltaVolume = latestResVolume - resFinalVolume[ activeRes ]; Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r2cc4f0cfc6512c942864d7d302cef5df375a2081 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 2cc4f0cfc6512c942864d7d302cef5df375a2081) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -170,13 +170,15 @@ U16 VDiPWMTarget; ///< Reg 374. PWM target duty cycle for VDi pinch valve. U16 VDoPWMTarget; ///< Reg 376. PWM target duty cycle for VDo pinch valve. U16 VSparePWMTarget; ///< Reg 378. PWM target duty cycle for Vspare pinch valve. - U16 SyringePumpStatus; ///< Reg 380. Syringe pump status register - U16 SyringePumpEncStatus; ///< Reg 382. Syringe pump encoder status - U32 SyringePumpEncPosition; ///< Reg 384. Syringe pump encoder position - U16 sPumpAdcDataReadChannel0; ///< Reg 388. - U16 sPumpAdcDataReadCh1; ///< Reg 390. - U16 sPumpAdcDataReadCh2; ///< Reg 392. - U16 sPumpAdcDataReadCh3; ///< Reg 394. + U08 syringePumpStatus; ///< Reg 380. Syringe pump status register. + U08 syringePumpADCReadCounter; ///< Reg 381. Syringe pump ADC read counter. + U08 syringePumpADCandDACStatus; ///< Reg 382. Syringe pump ADC and DAC status register. + U08 syringePumpEncoderStatus; ///< Reg 383. Syringe pump encoder status register. + U32 syringePumpEncPosition; ///< Reg 384. Syringe pump encoder position + U16 syringePumpAdcDataReadCh0; ///< Reg 388. Syringe pump ADC channel 0 register (10 bit). + U16 syringePumpAdcDataReadCh1; ///< Reg 390. Syringe pump ADC channel 1 register (10 bit). + U16 syringePumpAdcDataReadCh2; ///< Reg 392. Syringe pump ADC channel 2 register (10 bit). + U16 syringePumpAdcDataReadCh3; ///< Reg 394. Syringe pump ADC channel 3 register (10 bit). U16 VBASpeed; ///< Reg 396. VBA pinch valve speed (Register VAUX0) U16 VBVSpeed; ///< Reg 398. VBV pinch valve speed (Register VAUX1) U16 VBVCurrent; ///< Reg 400. VBV pinch valve current (Register VAUX2) @@ -204,7 +206,11 @@ U16 VDiPWMFixed; ///< Reg 28. VDi PWM set to fixed current by setting fixed PWM duty cycle. Range 750 to 4250. < 2500 is reverse direction. U16 VDoPWMFixed; ///< Reg 30. VDo PWM set to fixed current by setting fixed PWM duty cycle. Range 750 to 4250. < 2500 is reverse direction. U16 VSparePWMFixed; ///< Reg 32. Vspare PWM set to fixed current by setting fixed PWM duty cycle. Range 750 to 4250. < 2500 is reverse direction. - U08 AlarmControl; ///< Reg 34. Alarm (audio) control register. + U08 alarmControl; ///< Reg 34. Alarm (audio) control register. + U08 syringePumpControl; ///< Reg 35. Syringe pump control register. + U32 syringePumpStepToggleTime; ///< Reg 36. Syringe pump step time toggle register. Sets time between step toggle which dictates stepper motor speed. + U16 syringePumpDACOut; ///< Reg 40. Syringe pump DAC output level (12-bit). + U08 syringePumpADCandDACControl; ///< Reg 42. Syringe pump ADC and DAC control register. } FPGA_ACTUATORS_T; // TODO clean up the struct @@ -303,7 +309,7 @@ memset( &fpgaHeader, 0, sizeof(FPGA_HEADER_T) ); memset( &fpgaSensorReadings, 0, sizeof(FPGA_SENSORS_T) ); memset( &fpgaActuatorSetPoints, 0, sizeof(FPGA_ACTUATORS_T) ); - fpgaActuatorSetPoints.AlarmControl = (U08)MIN_ALARM_VOLUME_ATTENUATION << 2; // Start alarm audio volume at maximum + fpgaActuatorSetPoints.alarmControl = (U08)MIN_ALARM_VOLUME_ATTENUATION << 2; // Start alarm audio volume at maximum // Initialize fpga comm buffers memset( &fpgaWriteCmdBuffer, 0, FPGA_WRITE_CMD_BUFFER_LEN ); @@ -1078,15 +1084,15 @@ U08 audioCmd = (U08)state; audioCmd |= ( (U08)volumeLevel << 2 ); - fpgaActuatorSetPoints.AlarmControl = audioCmd; + fpgaActuatorSetPoints.alarmControl = audioCmd; } else { U08 audioCmd = (U08)ALARM_PRIORITY_HIGH; // Set alarm audio to high priority, max volume for safety since s/w seems to be having trouble setting audio correctly audioCmd |= ( (U08)MIN_ALARM_VOLUME_ATTENUATION << 2 ); - fpgaActuatorSetPoints.AlarmControl = audioCmd; + fpgaActuatorSetPoints.alarmControl = audioCmd; // S/w fault to indicate issue w/ s/w SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_ALARM_AUDIO_PARAM, volumeLevel ) @@ -1333,6 +1339,184 @@ /*********************************************************************//** * @brief + * The setFPGASyringePumpControlFlags function sets the syringe pump control + * register per given bit flags. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @param bitFlags control bit settings for syringe pump + * @return none + *************************************************************************/ +void setFPGASyringePumpControlFlags( U08 bitFlags ) +{ + fpgaActuatorSetPoints.syringePumpControl = bitFlags; +} + +/*********************************************************************//** + * @brief + * The setFPGASyringePumpADCandDACControlFlags function sets the syringe pump + * ADC/DAC control register per given bit flags. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @param bitFlags ADC/DAC control bit settings for syringe pump + * @return none + *************************************************************************/ +void setFPGASyringePumpADCandDACControlFlags( U08 bitFlags ) +{ + fpgaActuatorSetPoints.syringePumpADCandDACControl = bitFlags; +} + +/*********************************************************************//** + * @brief + * The setFPGASyringePumpDACOutputLevel function sets the syringe pump force + * sensor DAC output level register to a given value. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @param counts level to set syringe pump force sensor DAC to + * @return none + *************************************************************************/ +void setFPGASyringePumpDACOutputLevel( U16 counts ) +{ + fpgaActuatorSetPoints.syringePumpDACOut = counts; +} + +/*********************************************************************//** + * @brief + * The setFPGASyringePumpStepToggleTime function sets the syringe pump stepper + * toggle time register to a given period (in uSec). + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @param microSeconds toggle the stepper motor at this time interval to set pump speed + * @return none + *************************************************************************/ +void setFPGASyringePumpStepToggleTime( U32 microSeconds ) +{ + fpgaActuatorSetPoints.syringePumpStepToggleTime = microSeconds; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpStatus function gets the latest syringe pump status + * register reading. Bit 0 indicates a fault. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump status reading + *************************************************************************/ +U08 getFPGASyringePumpStatus( void ) +{ + return fpgaSensorReadings.syringePumpStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCReadCounter function gets the latest syringe pump + * ADC read counter. Counter is 8-bit and rolls over when exceeding 255. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC read counter + *************************************************************************/ +U08 getFPGASyringePumpADCReadCounter( void ) +{ + return fpgaSensorReadings.syringePumpADCReadCounter; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCandDACStatus function gets the latest syringe pump + * ADC/DAC status register reading. + * Bit 7 = DAC write and read-back done + * Bit 6 = I2C error on DAC data transfer + * Bit 0..5 = count of I2C errors, rolls over after 63 + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC/DAC status reading + *************************************************************************/ +U08 getFPGASyringePumpADCandDACStatus( void ) +{ + return fpgaSensorReadings.syringePumpADCandDACStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpEncoderStatus function gets the latest syringe pump + * encoder status register reading. + * Bit 7 = direction (0=fwd, 1=rev) + * Bit 0..5 = direction error count (# of errors after power up, rolls over after 63) + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump encoder status reading + *************************************************************************/ +U08 getFPGASyringePumpEncoderStatus( void ) +{ + return fpgaSensorReadings.syringePumpEncoderStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpEncoderPosition function gets the latest syringe pump + * encoder position reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump encoder position reading + *************************************************************************/ +U32 getFPGASyringePumpEncoderPosition( void ) +{ + return fpgaSensorReadings.syringePumpEncPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCChannel0 function gets the latest syringe pump ADC + * channel 0 register reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC channel 0 reading + *************************************************************************/ +U16 getFPGASyringePumpADCChannel0( void ) +{ + return fpgaSensorReadings.syringePumpAdcDataReadCh0; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCChannel1 function gets the latest syringe pump ADC + * channel 1 register reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC channel 1 reading + *************************************************************************/ +U16 getFPGASyringePumpADCChannel1( void ) +{ + return fpgaSensorReadings.syringePumpAdcDataReadCh1; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCChannel2 function gets the latest syringe pump ADC + * channel 2 register reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC channel 2 reading + *************************************************************************/ +U16 getFPGASyringePumpADCChannel2( void ) +{ + return fpgaSensorReadings.syringePumpAdcDataReadCh2; +} + +/*********************************************************************//** + * @brief + * The getFPGASyringePumpADCChannel3 function gets the latest syringe pump ADC + * channel 3 register reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last syringe pump ADC channel 3 reading + *************************************************************************/ +U16 getFPGASyringePumpADCChannel3( void ) +{ + return fpgaSensorReadings.syringePumpAdcDataReadCh3; +} + +/*********************************************************************//** + * @brief * The getFPGAAccelAxes function gets the accelerometer axis readings. * Axis readings are in ADC counts. 0.004 g per LSB. * @details Inputs: fpgaSensorReadings Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r2cc4f0cfc6512c942864d7d302cef5df375a2081 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 2cc4f0cfc6512c942864d7d302cef5df375a2081) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -21,11 +21,18 @@ #include "HDCommon.h" #include "Interrupts.h" + /** * @defgroup FPGA FPGA * @brief FPGA service module. - * Maintains latest sensor readings at priority task interval. Updates actuator - * states at priority task interval. + * The FPGA module manages communication between the HD and the FPGA via UART. + * This module is driven by the Priority Task via calls to two FPGA executive functions: + * 1) an incoming executive manages the states of the state machine that deal with responses and data received from the FPGA + * 2) an outgoing executive manages transmission of write and read commands to the FPGA. + * This module first reads the header record that includes the FPGA ID and revision and + * verifies the FPGA ID to check FPGA communication. It then initializes and configures the ADCs and + * various other sensors that are interfaced via the FPGA. Then, it essentially enters an infinite loop + * where a bulk write command updates actuator set points and a bulk read command retrieves the latest sensor readings. * * @addtogroup FPGA * @{ @@ -69,6 +76,20 @@ U16 getFPGADialInPumpOcclusion( void ); U16 getFPGADialOutPumpOcclusion( void ); +void setFPGASyringePumpControlFlags( U08 bitFlags ); +void setFPGASyringePumpADCandDACControlFlags( U08 bitFlags ); +void setFPGASyringePumpDACOutputLevel( U16 counts ); +void setFPGASyringePumpStepToggleTime( U32 microSeconds ); +U08 getFPGASyringePumpStatus( void ); +U08 getFPGASyringePumpADCReadCounter( void ); +U08 getFPGASyringePumpADCandDACStatus( void ); +U08 getFPGASyringePumpEncoderStatus( void ); +U32 getFPGASyringePumpEncoderPosition( void ); +U16 getFPGASyringePumpADCChannel0( void ); +U16 getFPGASyringePumpADCChannel1( void ); +U16 getFPGASyringePumpADCChannel2( void ); +U16 getFPGASyringePumpADCChannel3( void ); + void getFPGAAccelAxes( S16 *x, S16 *y, S16 *z ); void getFPGAAccelMaxes( S16 *xm, S16*ym, S16*zm ); void getFPGAAccelStatus( U16 *cnt, U16 *accelFPGAFaultReg ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r2cc4f0cfc6512c942864d7d302cef5df375a2081 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 2cc4f0cfc6512c942864d7d302cef5df375a2081) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -204,6 +204,10 @@ *************************************************************************/ void checkInFromUI( void ) { + if ( FALSE == uiDidCommunicate ) + { // Start DG check-in timer when UI first communicates + timeOfLastDGCheckIn = getMSTimerCount(); + } uiIsCommunicating = TRUE; timeOfLastUICheckIn = getMSTimerCount(); uiDidCommunicate = TRUE; @@ -930,11 +934,12 @@ { activateAlarmNoData( ALARM_ID_UI_COMM_TIMEOUT ); } + if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) + { + activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); + dgIsCommunicating = FALSE; + } } - if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) - { - dgIsCommunicating = FALSE; - } } /*********************************************************************//** @@ -1179,7 +1184,7 @@ handleTreatmentParametersFromUI( message ); break; - case MSG_ID_UI_START_TREATMENT: + case MSG_ID_STARTING_STOPPING_TREATMENT_CMD: handleUIStartTreatmentMsg( message ); break; @@ -1191,6 +1196,10 @@ handleChangePressureLimitsRequest( message ); break; + case MSG_ID_UI_HEPARIN_PAUSE_RESUME_REQUEST: + handleHeparinCommandRequest( message ); + break; + case MSG_ID_UI_SET_UF_VOLUME_PARAMETER: handleUFVolumeSetRequest( message ); break; @@ -1462,6 +1471,38 @@ handleTestSuperClearAlarmsRequest( message ); break; + case MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: + handleTestSyringePumpDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_OPERATION_REQUEST: + handleTestSyringePumpOperationRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_RATE_OVERRIDE: + handleTestSyringePumpMeasuredRateOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_FORCE_OVERRIDE: + handleTestSyringePumpMeasuredForceOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_SYRINGE_DETECT_OVERRIDE: + handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_HOME_OVERRIDE: + handleTestSyringePumpMeasuredHomeOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_POSITION_OVERRIDE: + handleTestSyringePumpMeasuredPositionOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_VOLUME_OVERRIDE: + handleTestSyringePumpMeasuredVolumeOverrideRequest( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r2cc4f0cfc6512c942864d7d302cef5df375a2081 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 2cc4f0cfc6512c942864d7d302cef5df375a2081) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -433,6 +433,38 @@ return result; } +/*********************************************************************//** + * @brief + * The sendHeparinCommandResponse function constructs a Heparin command response + * to the UI and queues the msg for transmit on the + * appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Heparin command response msg constructed and queued. + * @param accepted flag indicating whether request was accepted + * @param rejReason rejection reason code + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHeparinCommandResponse( U32 accepted, U32 rejReason ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE; + msg.hdr.payloadLen = sizeof( U32 ) * 2; + + memcpy( payloadPtr, &accepted, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &rejReason, sizeof( U32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); + + return result; +} + /*********************************************************************//** * @brief * The sendTreatmentParamsRangesToUI function constructs a treatment parameter @@ -1021,6 +1053,62 @@ result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); return result; +} + +/*********************************************************************//** + * @brief + * The broadcastSyringePumpData function constructs a syringe pump data + * msg to be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: syringe pump data msg constructed and queued. + * @param data syringe pump data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SYRINGE_PUMP_DATA; + msg.hdr.payloadLen = sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ); + + memcpy( payloadPtr, &data, sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** + * @brief + * The broadcastHeparinData function constructs a Heparin data message + * to be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details Inputs: none + * @details Outputs: Heparin data msg constructed and queued. + * @param data Heparin data record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastHeparinData( F32 volume ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_HEPARIN_DATA_BROADCAST; + msg.hdr.payloadLen = sizeof( F32 ); + + memcpy( payloadPtr, &volume, sizeof( F32 ) ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; } /*********************************************************************//** @@ -1966,12 +2054,12 @@ * response to the UI and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: Treatment parameters response msg constructed and queued. - * @param rejected T/F - are settings rejected? + * @param accepted T/F - are settings accepted? * @param rejectReasons reasons each parameter was rejected (if not accepted) * @param byteLength number of bytes that array of reject reasons takes * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendTreatmentParametersResponseMsg( BOOL rejected, U08 *rejectReasons, U32 byteLength ) +BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ) { BOOL result; MESSAGE_T msg; @@ -1982,7 +2070,7 @@ msg.hdr.msgID = MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE; msg.hdr.payloadLen = sizeof( BOOL ) + byteLength; - memcpy( payloadPtr, &rejected, sizeof( BOOL ) ); + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); payloadPtr += sizeof( BOOL ); memcpy( payloadPtr, rejectReasons, byteLength ); @@ -2182,6 +2270,31 @@ /*********************************************************************//** * @brief + * The handleHeparinCommandRequest function handles a Heparin command + * request message from the UI. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleHeparinCommandRequest( MESSAGE_T *message ) +{ + if ( sizeof( U32 ) == message->hdr.payloadLen ) + { + U32 payload; + + memcpy( &payload, &message->payload[0], sizeof( U32 ) ); + + userHeparinRequest( (HEPARIN_CMD_T)payload ); + } + else + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, FALSE ); + } +} + +/*********************************************************************//** + * @brief * The handleSalineBolusRequest function handles a saline bolus request * message from the UI. * @details Inputs: none @@ -3372,7 +3485,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetBloodPumpOcclusionOverride( payload.state.f32 ); + result = testSetBloodPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3404,7 +3517,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialInPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialInPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3436,7 +3549,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialOutPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialOutPumpOcclusionOverride( payload.state.u32 ); } else { @@ -4375,4 +4488,253 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** + * @brief + * The handleTestSyringePumpDataBroadcastIntervalOverrideRequest function handles a + * request to override the syringe pump data broadcast interval. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpDataBroadcastIntervalOverrideRequest( 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 = testSetSyringePumpDataPublishIntervalOverride( (U32)(payload.state.u32) ); + } + else + { + result = testResetSyringePumpDataPublishIntervalOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpOperationRequest function handles a + * request to initiate a syringe pump operation. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpOperationRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(SYRINGE_PUMP_OP_PAYLOAD_T) ) + { + SYRINGE_PUMP_OP_PAYLOAD_T payload; + + memcpy( &payload, message->payload, sizeof(SYRINGE_PUMP_OP_PAYLOAD_T) ); + result = testSyringePumpOperationRequest( payload ); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredRateOverrideRequest function handles a + * request to override the syringe pump measured rate. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredRateOverrideRequest( 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 = testSetSyringePumpMeasuredRateOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredRateOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredForceOverrideRequest function handles a + * request to override the syringe pump measured force analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredForceOverrideRequest( 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 = testSetSyringePumpMeasuredForceOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredForceOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredSyringeDetectOverrideRequest function handles a + * request to override the syringe pump syringe detected analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( 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 = testSetSyringePumpMeasuredSyringeDetectOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredSyringeDetectOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredHomeOverrideRequest function handles a + * request to override the syringe pump measured home analog signal. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredHomeOverrideRequest( 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 = testSetSyringePumpMeasuredHomeOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredHomeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredPositionOverrideRequest function handles a + * request to override the syringe pump measured position. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredPositionOverrideRequest( 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 = testSetSyringePumpMeasuredPositionOverride( (S32)(payload.state.u32) ); + } + else + { + result = testResetSyringePumpMeasuredPositionOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief + * The handleTestSyringePumpMeasuredVolumeOverrideRequest function handles a + * request to override the syringe pump measured volume delivered. + * @details Inputs: none + * @details Outputs: message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestSyringePumpMeasuredVolumeOverrideRequest( 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 = testSetSyringePumpMeasuredVolumeOverride( payload.state.f32 ); + } + else + { + result = testResetSyringePumpMeasuredVolumeOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r2cc4f0cfc6512c942864d7d302cef5df375a2081 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 2cc4f0cfc6512c942864d7d302cef5df375a2081) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -33,6 +33,7 @@ #include "NVDataMgmt.h" #include "PresOccl.h" #include "Rinseback.h" +#include "SyringePump.h" #include "Valves.h" /** @@ -104,7 +105,7 @@ void handleTreatmentParametersFromUI( MESSAGE_T *message ); // MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE -BOOL sendTreatmentParametersResponseMsg( BOOL rejected, U08 *rejectReasons, U32 byteLength ); +BOOL sendTreatmentParametersResponseMsg( BOOL accepted, U08 *rejectReasons, U32 byteLength ); // MSG_ID_UI_SET_UF_VOLUME_PARAMETER void handleUFVolumeSetRequest( MESSAGE_T *message ); @@ -163,6 +164,12 @@ // MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE BOOL sendPressureLimitsChangeResponse( PRESSURE_LIMIT_CHANGE_RESPONSE_T *data ); +// MSG_ID_UI_HEPARIN_PAUSE_RESUME_REQUEST +void handleHeparinCommandRequest( MESSAGE_T *message ); + +// MSG_ID_HD_HEPARIN_PAUSE_RESUME_RESPONSE +BOOL sendHeparinCommandResponse( U32 accepted, U32 rejReason ); + // MSG_ID_UI_RINSEBACK_CMD void handlRinsebackCmd( MESSAGE_T *message ); @@ -236,7 +243,13 @@ BOOL broadcastDialInFlowData( DIALIN_PUMP_STATUS_PAYLOAD_T *dialInData ); // MSG_ID_DIALYSATE_OUT_FLOW_DATA -BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); +BOOL broadcastDialOutFlowData( DIAL_OUT_FLOW_DATA_T *dialOutFlowData ); + +// MSG_ID_HD_SYRINGE_PUMP_DATA +BOOL broadcastSyringePumpData( SYRINGE_PUMP_DATA_PAYLOAD_T data ); + +// MSG_ID_HD_HEPARIN_DATA_BROADCAST +BOOL broadcastHeparinData( F32 volume ); // MSG_ID_PRESSURE_OCCLUSION_DATA BOOL broadcastPresOcclData( PRESSURE_OCCLUSION_DATA_T data ); @@ -481,6 +494,30 @@ // MSG_ID_HD_SET_OP_MODE_REQUEST void handleTestSetOpModeRequest( MESSAGE_T *message ); +// MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: +void handleTestSyringePumpDataBroadcastIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_OPERATION_REQUEST: +void handleTestSyringePumpOperationRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_RATE_OVERRIDE: +void handleTestSyringePumpMeasuredRateOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_FORCE_OVERRIDE: +void handleTestSyringePumpMeasuredForceOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_SYRINGE_DETECT_OVERRIDE: +void handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_HOME_OVERRIDE: +void handleTestSyringePumpMeasuredHomeOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_POSITION_OVERRIDE: +void handleTestSyringePumpMeasuredPositionOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_HD_SYRINGE_PUMP_MEASURED_VOLUME_OVERRIDE: +void handleTestSyringePumpMeasuredVolumeOverrideRequest( MESSAGE_T *message ); + /**@}*/ #endif Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -rd2c7420f7420cb79e116f26f187764cd6ce52c68 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision d2c7420f7420cb79e116f26f187764cd6ce52c68) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -25,6 +25,7 @@ #include "FluidLeak.h" #include "FPGA.h" #include "InternalADC.h" +#include "SyringePump.h" #include "SystemComm.h" #include "Valves.h" #include "WatchdogMgmt.h" @@ -66,7 +67,12 @@ execInternalADC(); // Monitor air trap level sensors - execAirTrapMonitor(); + execAirTrapMonitor(); + +#ifndef DISABLE_SYRINGE_PUMP + // Control/Monitor syringe pump + execSyringePump(); +#endif // Monitor blood pump and flow execBloodFlowMonitor(); Index: firmware/source/sys_main.c =================================================================== diff -u -r1afd5c87ef15399998a743c2ebcafe2cc03bd363 -rb01c6571b1ffade6de3e0bf6890de918f4d8b47d --- firmware/source/sys_main.c (.../sys_main.c) (revision 1afd5c87ef15399998a743c2ebcafe2cc03bd363) +++ firmware/source/sys_main.c (.../sys_main.c) (revision b01c6571b1ffade6de3e0bf6890de918f4d8b47d) @@ -71,6 +71,7 @@ #include "CPLD.h" #include "DialInFlow.h" #include "DialOutFlow.h" +#include "FluidLeak.h" #include "FPGA.h" #include "InternalADC.h" #include "Interrupts.h" @@ -191,6 +192,7 @@ initDialOutFlow(); initSyringePump(); initValves(); + initFluidLeak(); // Initialize modes initOperationModes(); // Initialize async interrupt handlers