Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r6419179374edcd65da462de84e8aeaefb7e20320 -r24b2fe72608344e67ef37234085d15ad5e4fcc37 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 6419179374edcd65da462de84e8aeaefb7e20320) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 24b2fe72608344e67ef37234085d15ad5e4fcc37) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2022 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 FPGA.c +* @file FPGA.c * -* @author (last) Peman Montazemi -* @date (last) 15-Feb-2021 +* @author (last) Sean Nash +* @date (last) 12-Nov-2021 * -* @author (original) Dara Navaei -* @date (original) 05-Nov-2019 +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 * ***************************************************************************/ @@ -20,9 +20,13 @@ #include "sci.h" #include "sys_dma.h" -#include "FPGA.h" #include "Comm.h" +#include "Compatible.h" +#include "FPGA.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" +#include "Timers.h" #include "Utilities.h" /** @@ -76,16 +80,40 @@ #define MAX_COMM_ERROR_RETRIES 5 ///< Maximum consecutive FPGA communication error retries. +#define FPGA_INPUT_VOLTAGE_SCALE 3.0 ///< FPGA source and aux voltage. +#define FPGA_PVN_VOLTAGE_SCALE 1.0 ///< FPGA pvn voltage. + #define FPGA_ADC1_AUTO_READ_ENABLE 0x01 ///< Auto-read enable bit for ADC1 control register. #define FPGA_AIRTRAP_LEVEL_LOW_MASK 0x0008 ///< Bit mask for air trap lower level sensor. #define FPGA_AIRTRAP_LEVEL_HIGH_MASK 0x0004 ///< Bit mask for air trap upper level sensor. -#define FPGA_FLUIDLEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. -#define FPGA_ADA_INPUT_STATUS_MASK 0x0001 ///< Bit mask for arterial air bubble detector input status. -#define FPGA_ADV_INPUT_STATUS_MASK 0x0002 ///< Bit mask for venous air bubble detector input status. -#define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector status. +#define FPGA_FLUID_LEAK_STATE_MASK 0x0040 ///< Bit mask for fluid leak detector. +#define FPGA_BLOOD_LEAK_STATUS_MASK 0x1000 ///< Bit mask for blood leak detector. +#define FPGA_BLOOD_LEAK_ZERO_STATE_MASK 0x2000 ///< Bit mask for blood leak detector zero. +#define FPGA_BLOOD_LEAK_ZERO_CMD 0x02 ///< Bit for blood leak detector zero command. +#define FPGA_BLOOD_LEAK_SELF_TEST_CMD 0x01 ///< Bit for blood leak detector self test command. + +#define FPGA_ADA_BUBBLE_STATUS_MASK 0x0001 ///< Bit mask for arterial air bubble detector input status. +#define FPGA_ADV_BUBBLE_STATUS_MASK 0x0002 ///< Bit mask for venous air bubble detector input status. +#define FPGA_ADA_BUBBLE_SELF_TEST_CMD 0x04 ///< Bit for arterial air bubble detector self-test command. +#define FPGA_ADV_BUBBLE_SELF_TEST_CMD 0x08 ///< Bit for venous air bubble detector self-test command. + +#define FPGA_PBO_TEMP_DIVISOR 2047.0 ///< Used in conversion of PBo temperature reading to deg C. +#define FPGA_PBO_TEMP_GAIN 200.0 ///< Used in conversion of PBo temperature reading to deg C. +#define FPGA_PBO_TEMP_OFFSET 50.0 ///< Used in conversion of PBo temperature reading to deg C. + +#define FPGA_ALARM_AUDIO_VOLUME_SHIFT 3 ///< Shift alarm audio volume 3 bits to left before writing to register. +#define FPGA_ALARM_AUDIO_DIVIDE_SHIFT 6 ///< Shift alarm audio volume divider 6 bits to left before writing to register. + +#define FPGA_BACKUP_ALARM_AUDIO_CONVERT 0.4 ///< Converts backup (piezo) alarm audio ADC volts to amps. + +#define FRONT_DOOR_SWITCH_MASK 0x0010 ///< Front door switch bit mask. Bit 4 of the GPIO register. +#define PUMP_TRACK_SWITCH_MASK 0x0020 ///< Pump track switch bit mask. Bit 5 of the GPIO register. + +#define PROCESSOR_FPGA_CLOCK_DIFF_TOLERANCE 1 ///< Tolerance for processor clock speed check against FPGA clock. + // FPGA Sensors Record #pragma pack(push,1) /// Record structure for FPGA header read. @@ -123,19 +151,19 @@ U16 bloodOcclusionData; ///< Reg 276. Blood pump occlusion sensor data. U08 bloodOcclusionReadCount; ///< Reg 278. Blood pump occlusion sensor read count. U08 bloodOcclusionErrorCount; ///< Reg 279. Blood pump occlusion sensor error count. - U16 dialysateInOcclusionData; ///< Reg 280. Dialysate inlet pump occlusion sensor data. - U08 dialysateInOcclusionReadCount; ///< Reg 282. Dialysate inlet pump occlusion sensor read count. - U08 dialysateInOcclusionErrorCount; ///< Reg 283. Dialysate inlet pump occlusion sensor error count. - U16 dialysateOutOcclusionData; ///< Reg 284. Dialysate outlet pump occlusion sensor data. - U08 dialysateOutOcclusionReadCount; ///< Reg 286. Dialysate outlet pump occlusion sensor read count. - U08 dialysateOutOcclusionErrorCount; ///< Reg 287. Dialysate outlet pump occlusion sensor error count. + U16 obsolete1; ///< Reg 280. Unused. + U08 obsolete2; ///< Reg 282. Unused. + U08 obsolete3; ///< Reg 283. Unused. + U16 obsolete4; ///< Reg 284. Unused. + U08 obsolete5; ///< Reg 286. Unused. + U08 obsolete6; ///< Reg 287. Unused. U16 bloodPumpHallSensorCount; ///< Reg 288. Blood pump hall sensor count. U08 bloodPumpHallSensorStatus; ///< Reg 290. Blood pump hall sensor status. U08 dialInPumpHallSensorStatus; ///< Reg 291. Dialysate inlet pump hall sensor status. U32 adc1Channel0; ///< Reg 292. ADC1 channel 0 data. U32 adc1Channel1; ///< Reg 296. ADC1 channel 1 data. U32 bloodFlowSoundSpeedData; ///< Reg 300. Blood flow sensor - sound speed data. - U32 bloodFlowAccFlowData; ///< Reg 304. Blood flow sensor - accumualted flow data. + U32 bloodFlowAccFlowData; ///< Reg 304. Blood flow sensor - accumulated flow data. F32 bloodFlowSignalStrength; ///< Reg 308. Blood flow sensor - signal strength. U08 adc1SequenceCount; ///< Reg 312. ADC1 round robin channel sequence count. U08 adc1ErrorCount; ///< Reg 313. ADC1 error count. @@ -154,7 +182,7 @@ U16 dialInPumpHallSensorCount; ///< Reg 336. Dialysate inlet pump hall sensor count. U16 dialOutPumpHallSensorCount; ///< Reg 338. Dialysate outlet pump hall sensor count. U32 dialysateFlowSoundSpeedData; ///< Reg 340. Dialysate flow sensor - sound speed data. - U32 dialysateFlowAccFlowData; ///< Reg 344. Dialysate flow sensor - accumualted flow data. + U32 dialysateFlowAccFlowData; ///< Reg 344. Dialysate flow sensor - accumulated flow data. F32 dialysateFlowSignalStrength; ///< Reg 348. Dialysate flow sensor - signal strength. U16 fan1PulseTime; ///< Reg 352. Fan 1 pulse time in 2.5 uSec resolution. 0xFFFF if fan RPM < 500 RPM. U16 fan2PUlseTime; ///< Reg 354. Fan 2 pulse time in 2.5 uSec resolution. 0xFFFF if fan RPM < 500 RPM. @@ -163,13 +191,13 @@ S16 VBVPosition; ///< Reg 360. Encoder position from VBV pinch valve. 0 until PID interface is enabled. S16 VDiPosition; ///< Reg 362. Encoder position from VDi pinch valve. 0 until PID interface is enabled. S16 VDoPosition; ///< Reg 364. Encoder position from VDo pinch valve. 0 until PID interface is enabled. - S16 VSparePosition; ///< Reg 366. Encoder position from VSpare pinch valve. 0 until PID interface is enabled. + S16 fpgaIntVoltage; ///< Reg 366. Internal FPGA Vcc voltage. 3V range over 12 bits (0..4095). U16 valveStatus; ///< Reg 368. Valve status register. U16 VBAPWMTarget; ///< Reg 370. PWM target duty cycle for VBA pinch valve. U16 VBVPWMTarget; ///< Reg 372. PWM target duty cycle for VBV pinch valve. 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 fpgaAuxVoltage; ///< Reg 378. Internal FPGA Vcc Aux voltage. 3V range over 12 bits (0..4095). 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. @@ -184,11 +212,13 @@ U16 VBVCurrent; ///< Reg 400. VBV pinch valve current (Register VAUX2) U16 VDoCurrent; ///< Reg 402. VDo pinch valve current (Register VAUX3) U16 VBACurrent; ///< Reg 404. VBA pinch valve current (Register VAUX8) - U16 VDiSpeed; ///< Reg 406. VDi pinch valve current (Register VAUX9) + U16 VDiSpeed; ///< Reg 406. VDi pinch valve current (Register VAUX5) U16 VDoSpeed; ///< Reg 408. VDo pinch valve speed (Register VAUX10) - U16 VDiCurrent; ///< Reg 410. VDi pinch valve current (Register VAUX11) - U16 VSpareSpeed; ///< Reg 412. VSpare speed (Register VAUX5) - U16 VSpareCurrent; ///< Reg 414. VSpare current (Register VAUX13) + U16 VDiCurrent; ///< Reg 410. VDi pinch valve current (Register VAUX13) + U16 fpgaTemperature; ///< Reg 412. FPGA die temperature (deg C = counts x (503.975/4096) - 273.15). + U16 fpgaVpvn; ///< Reg 414. FPGA pvn voltage. 1V range over 12 bits (0..4095). + U16 fpgaTimerCount_ms; ///< Reg 416. Free running 1ms timer counter. Rolls over at 65535.Internal FPGA timer count in ms. + U16 backupAlarmAudioPeakCurrent; ///< Reg 418. Piezo alarm peak ADC current in previous 10ms. 12 bit unsigned. } FPGA_SENSORS_T; /// Record structure for FPGA continuous priority writes. @@ -273,6 +303,9 @@ static FPGA_SENSORS_ASYNC_T fpgaSensorReadingsAsync; ///< Record of last received async (as needed) FPGA sensor data. #endif +static U16 currentFPGATimerCount_ms; ///< Current FPGA timer count in ms. +static U32 currentTimerCount_ms; ///< Current processor timer count in ms. + // ********** private function prototypes ********** static FPGA_STATE_T handleFPGAReadHeaderState( void ); @@ -295,6 +328,7 @@ static void startDMAReceiptOfReadResp( void ); static void consumeUnexpectedData( void ); +static void monitorFPGAPowerStatus( void ); /*********************************************************************//** * @brief @@ -519,13 +553,21 @@ } // If retries for commands exceeds limit, fault - if ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) + if ( ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) +#ifdef _RELEASE_ + || ( fpgaSensorReadings.errorCountProcessor > MAX_COMM_ERROR_RETRIES ) ) +#else + ) +#endif { - activateAlarmNoData( ALARM_ID_FPGA_COMM_TIMEOUT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_COMM_TIMEOUT, fpgaCommRetryCount, (U32)fpgaSensorReadings.errorCountProcessor ) } // Reset comm flags after processing incoming responses resetFPGACommFlags(); + + // Monitor the power status + monitorFPGAPowerStatus(); } /*********************************************************************//** @@ -860,19 +902,62 @@ // Check FPGA reported correct ID if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) { - result = SELF_TEST_STATUS_PASSED; + // Check FPGA compatibility w/ firmware + if ( fpgaHeader.fpgaRevMajor > MIN_HD_FPGA_MAJOR ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + if ( ( MIN_HD_FPGA_MAJOR == fpgaHeader.fpgaRevMajor ) && ( fpgaHeader.fpgaRev >= MIN_HD_FPGA_MINOR ) ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaRevMajor, (U32)fpgaHeader.fpgaRev ) + } + } } else { result = SELF_TEST_STATUS_FAILED; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaId ) + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaId ) } return result; } /*********************************************************************//** * @brief + * The execFPGAClockSpeedTest function verifies the processor clock speed + * against the FPGA clock. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return passed, or failed + *************************************************************************/ +void execFPGAClockSpeedTest( void ) +{ + U16 const newFPGATimerCount_ms = getFPGATimerCount(); + U32 const newTimerCount_ms = getMSTimerCount(); + U32 const diffFPGATimerCount = (U32)u16DiffWithWrap( currentFPGATimerCount_ms, newFPGATimerCount_ms ); + U32 const diffTimerCount = u32DiffWithWrap( currentTimerCount_ms, newTimerCount_ms ); + + if ( getCurrentOperationMode() > MODE_INIT ) + { + if ( abs( diffFPGATimerCount - diffTimerCount ) > PROCESSOR_FPGA_CLOCK_DIFF_TOLERANCE ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_FPGA_CLOCK_SPEED_CHECK_FAILURE, diffFPGATimerCount, diffTimerCount ); + } + } + + currentFPGATimerCount_ms = newFPGATimerCount_ms; + currentTimerCount_ms = newTimerCount_ms; +} + +/*********************************************************************//** + * @brief * The consumeUnexpectedData function checks to see if a byte is sitting in * the SCI2 received data register. * @details Inputs: fpgaHeader @@ -893,6 +978,18 @@ /*********************************************************************//** * @brief + * The monitorFPGAPowerStatus function monitors the status of the FPGA power source. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorFPGAPowerStatus( void ) +{ + // TOD fill up. Figure out the status of the power source from FPGA from NOE and Kai. +} + +/*********************************************************************//** + * @brief * The setupDMAForWriteCmd function sets the byte count for the next DMA * write command to the FPGA. * @details Inputs: none @@ -1056,42 +1153,102 @@ /*********************************************************************//** * @brief + * The getFPGATemperature function gets the fpga internal die temperature. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return current internal FPGA die temperature (in counts) + *************************************************************************/ +U16 getFPGATemperature( void ) +{ + return fpgaSensorReadings.fpgaTemperature; +} + +/*********************************************************************//** + * @brief + * The getFPGAVcc function gets the fpga input voltage. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return current FPGA input voltage (in volts) + *************************************************************************/ +F32 getFPGAVcc( void ) +{ + F32 result = (F32)fpgaSensorReadings.fpgaIntVoltage * FPGA_INPUT_VOLTAGE_SCALE / (F32)BITS_12_FULL_SCALE; + + return result; +} + +/*********************************************************************//** + * @brief + * The getFPGAVccAux function gets the fpga aux. voltage. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return current FPGA aux. voltage (in volts) + *************************************************************************/ +F32 getFPGAVccAux( void ) +{ + F32 result = (F32)fpgaSensorReadings.fpgaAuxVoltage * FPGA_INPUT_VOLTAGE_SCALE / (F32)BITS_12_FULL_SCALE; + + return result; +} + +/*********************************************************************//** + * @brief + * The getFPGAVpvn function gets the fpga pvn voltage. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return current FPGA pvn voltage (in volts) + *************************************************************************/ +F32 getFPGAVpvn( void ) +{ + F32 result = (F32)fpgaSensorReadings.fpgaVpvn * FPGA_PVN_VOLTAGE_SCALE / (F32)BITS_12_FULL_SCALE; + + return result; +} + +/*********************************************************************//** + * @brief * The setAlarmAudioState function sets the fpga audio control to the given * state and volume. * @details Inputs: none * @details Outputs: alarm audio state and attenuation set - * @param state the state of alarm audio to command: + * @param state the state of alarm audio to command (3..5): * 0 - No alarm tone * 1 - Low priority alarm tone (c e) * 2 - Medium priority alarm tone (c f# c) * 3 - High priority alarm tone (c f# c - c f#) - * @param volumeLevel the level of attenuation to command (0..4) + * 4 - Continuous test tone (e) + * @param volumeLevel the level of attenuation to command (0..2): * 4 - 3 dB gain * 3 - 6 dB gain * 2 - 9 dB gain * 1 - 12 dB gain * 0 - 15 dB gain + * @param volumeDivider further attenuation via divider (6..7): + * 0 - Divide by 2 + * 1 - Divide by 4 + * 2 - Divide by 8 + * 3 - Divide by 16 * @return none *************************************************************************/ -void setAlarmAudioState( ALARM_PRIORITY_T state, U32 volumeLevel ) +void setAlarmAudioState( U32 state, U32 volumeLevel, U32 volumeDivider ) { - if ( ( state < NUM_OF_ALARM_PRIORITIES ) && ( volumeLevel <= MAX_ALARM_VOLUME_ATTENUATION ) ) - { - U08 audioCmd = (U08)state; + U08 audioCmd = (U08)state; - audioCmd |= ( (U08)volumeLevel << 2 ); + audioCmd |= ( (U08)volumeLevel << FPGA_ALARM_AUDIO_VOLUME_SHIFT ); + audioCmd |= ( (U08)volumeDivider << FPGA_ALARM_AUDIO_DIVIDE_SHIFT ); + + if ( ( state <= NUM_OF_ALARM_PRIORITIES ) && ( volumeLevel <= MAX_ALARM_VOLUME_ATTENUATION ) ) + { fpgaActuatorSetPoints.alarmControl = audioCmd; } else { - U08 audioCmd = (U08)ALARM_PRIORITY_HIGH; - + // 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, (U32)audioCmd ) // 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 ); + audioCmd = (U08)ALARM_PRIORITY_HIGH; + audioCmd |= ( (U08)MIN_ALARM_VOLUME_ATTENUATION << FPGA_ALARM_AUDIO_VOLUME_SHIFT ); 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 ) - } } @@ -1123,54 +1280,82 @@ /*********************************************************************//** * @brief - * The getFPGABloodFlow function gets the latest blood flow reading. + * The getFPGADialysateFlow function gets the latest dialysate flow reading. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return last blood flow reading + * @return last dialysate flow reading *************************************************************************/ -F32 getFPGABloodFlow( void ) +F32 getFPGADialysateFlow( void ) { - return fpgaSensorReadings.bloodFlowLast; + return fpgaSensorReadings.dialysateFlowLast; } /*********************************************************************//** * @brief - * The getFPGADialysateFlow function gets the latest dialysate flow reading. + * The getFPGADialysateFlowMeterStatus function gets the dialysate flow meter status. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return last dialysate flow reading + * @return current dialysate flow meter status *************************************************************************/ -F32 getFPGADialysateFlow( void ) +U08 getFPGADialysateFlowMeterStatus( void ) { - return fpgaSensorReadings.dialysateFlowLast; + return fpgaSensorReadings.dialysateFlowMeterDeviceStatus; } /*********************************************************************//** * @brief - * The getFPGABloodFlowMeterStatus function gets the blood flow meter status. + * The getFPGADialysateFlowFastPacketReadCounter function gets the dialysate + * flow meter fast packet read counter. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return current blood flow meter status + * @return current dialysate flow meter fast packet read counter *************************************************************************/ -U08 getFPGABloodFlowMeterStatus( void ) +U08 getFPGADialysateFlowFastPacketReadCounter( void ) { - return fpgaSensorReadings.bloodFlowMeterDeviceStatus; + return fpgaSensorReadings.dialysateFlowMeterDataPktCount; } /*********************************************************************//** * @brief - * The getFPGADialysateFlowMeterStatus function gets the dialysate flow meter status. + * The getFPGADialysateFlowSlowPacketReadCounter function gets the dialysate + * flow meter slow packet read counter. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return current dialysate flow meter status + * @return current dialysate flow meter slow packet read counter *************************************************************************/ -U08 getFPGADialysateFlowMeterStatus( void ) +U08 getFPGADialysateFlowSlowPacketReadCounter( void ) { - return fpgaSensorReadings.dialysateFlowMeterDeviceStatus; + return ( fpgaSensorReadings.dialysateFlowMeterSlowPckCounts & MASK_OFF_NIBBLE_LSB ) >> SHIFT_BITS_BY_4; } /*********************************************************************//** * @brief + * The getFPGADialysateFlowStatusPacketReadCounter function gets the dialysate + * flow meter status packet read counter. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current dialysate flow meter status packet read counter + *************************************************************************/ +U08 getFPGADialysateFlowStatusPacketReadCounter( void ) +{ + return ( fpgaSensorReadings.dialysateFlowMeterSlowPckCounts & MASK_OFF_NIBBLE_MSB ); +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateFlowErrorCounter function gets the dialysate flow meter + * error counter. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current dialysate flow meter error counter + *************************************************************************/ +U08 getFPGADialysateFlowErrorCounter( void ) +{ + return fpgaSensorReadings.dialysateFlowMeterErrorCount; +} + +/*********************************************************************//** + * @brief * The getFPGABloodPumpHallSensorCount function gets the latest blood pump * hall sensor count. Count is a 16 bit free running counter. If counter is * counting up, indicates motor is running in forward direction. If counter is @@ -1189,9 +1374,9 @@ * @brief * The getFPGABloodPumpHallSensorStatus function gets the latest blood pump * hall sensor status. - * Bit 0 - Derived direction of the blood pump motor (0=Fwd, 1=Rev) - * Bit 1 - A direction error was detected in the current hall sensor phase - * Bit 2 - A direction error was detected since the last read of this register + * Bit 7 - Derived direction of the blood pump motor (0=Fwd, 1=Rev) + * Bit 6 - Unused + * Bit 5-0 - Direction error count since power-up (rolls over) * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last blood pump hall sensor status reading. @@ -1221,9 +1406,9 @@ * @brief * The getFPGADialInPumpHallSensorStatus function gets the latest dialysate inlet pump * hall sensor status. - * Bit 0 - Derived direction of the dialyste inlet pump motor (0=Fwd, 1=Rev) - * Bit 1 - A direction error was detected in the current hall sensor phase - * Bit 2 - A direction error was detected since the last read of this register + * Bit 7 - Derived direction of the dialysate inlet pump motor (0=Fwd, 1=Rev) + * Bit 6 - Unused + * Bit 5-0 - Direction error count since power-up (rolls over) * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last dialysate inlet pump hall sensor status reading. @@ -1253,9 +1438,9 @@ * @brief * The getFPGADialOutPumpHallSensorStatus function gets the latest dialysate outlet pump * hall sensor status. - * Bit 0 - Derived direction of the dialysate outlet pump motor (0=Fwd, 1=Rev) - * Bit 1 - A direction error was detected in the current hall sensor phase - * Bit 2 - A direction error was detected since the last read of this register + * Bit 7 - Derived direction of the dialysate outlet pump motor (0=Fwd, 1=Rev) + * Bit 6 - Unused + * Bit 5-0 - Direction error count since power-up (rolls over) * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last dialysate outlet pump hall sensor status reading. @@ -1279,28 +1464,28 @@ /*********************************************************************//** * @brief - * The getFPGADialInPumpOcclusion function gets the latest dialysate - * inlet occlusion reading. + * The getFPGABloodPumpOcclusionReadCounter function gets the latest blood + * pump occlusion read counter. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return last dialysate inlet occlusion reading + * @return last blood pump occlusion read counter *************************************************************************/ -U16 getFPGADialInPumpOcclusion( void ) +U08 getFPGABloodPumpOcclusionReadCounter( void ) { - return fpgaSensorReadings.dialysateInOcclusionData; + return fpgaSensorReadings.bloodOcclusionReadCount; } /*********************************************************************//** * @brief - * The getFPGADialOutPumpOcclusion function gets the latest dialysate - * outlet occlusion reading. + * The getFPGABloodPumpOcclusionErrorCounter function gets the latest blood + * pump occlusion error counter. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return last dialysate outlet occlusion reading + * @return last blood pump occlusion error counter *************************************************************************/ -U16 getFPGADialOutPumpOcclusion( void ) +U08 getFPGABloodPumpOcclusionErrorCounter( void ) { - return fpgaSensorReadings.dialysateOutOcclusionData; + return fpgaSensorReadings.bloodOcclusionErrorCount; } /*********************************************************************//** @@ -1320,7 +1505,33 @@ /*********************************************************************//** * @brief - * The getFPGAVenousPressure function gets the venous arterial pressure reading. + * The getFPGAArterialPressureReadCounter function gets the latest arterial + * pressure sensor read counter. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last arterial pressure sensor read counter + *************************************************************************/ +U08 getFPGAArterialPressureReadCounter( void ) +{ + return fpgaSensorReadings.adc1SequenceCount; +} + +/*********************************************************************//** + * @brief + * The getFPGAArterialPressureErrorCounter function gets the latest arterial + * pressure sensor error counter. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last arterial pressure sensor error counter + *************************************************************************/ +U08 getFPGAArterialPressureErrorCounter( void ) +{ + return fpgaSensorReadings.adc1ErrorCount; +} + +/*********************************************************************//** + * @brief + * The getFPGAVenousPressure function gets the latest venous pressure reading. * The high 2 bits are status bits: 00=ok, 01=cmd mode, 10=stale data, 11=diag * The low 14 bits are data. Zero is at 1638. Values above are positive, * below are negative. @@ -1335,6 +1546,32 @@ /*********************************************************************//** * @brief + * The getFPGAVenousPressureTemperature function gets the latest venous pressure + * sensor temperature reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last venous pressure sensor temperature reading + *************************************************************************/ +U16 getFPGAVenousPressureTemperature( void ) +{ + return fpgaSensorReadings.venousTemperature; +} + +/*********************************************************************//** + * @brief + * The getFPGAVenousPressureReadCounter function gets the latest venous pressure + * sensor read counter. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last venous pressure sensor read counter + *************************************************************************/ +U08 getFPGAVenousPressureReadCounter( void ) +{ + return fpgaSensorReadings.venousReadCounter; +} + +/*********************************************************************//** + * @brief * The setFPGASyringePumpControlFlags function sets the syringe pump control * register per given bit flags. * @details Inputs: none @@ -1513,6 +1750,18 @@ /*********************************************************************//** * @brief + * The getFPGATimerCount function gets the latest FPGA timer millisecond count. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last FPGA timer count + *************************************************************************/ +U16 getFPGATimerCount( void ) +{ + return fpgaSensorReadings.fpgaTimerCount_ms; +} + +/*********************************************************************//** + * @brief * The getFPGAAccelAxes function gets the accelerometer axis readings. * Axis readings are in ADC counts. 0.004 g per LSB. * @details Inputs: fpgaSensorReadings @@ -1566,6 +1815,22 @@ /*********************************************************************//** * @brief + * The getFPGABackupAlarmAudioCurrent function gets the latest piezo alarm + * audio current reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return Latest piezo alarm audio current reading + *************************************************************************/ +F32 getFPGABackupAlarmAudioCurrent( void ) +{ + U16 adcCnts = fpgaSensorReadings.backupAlarmAudioPeakCurrent; + F32 result = ( ( (F32)adcCnts / (F32)BITS_12_FULL_SCALE ) * FPGA_BACKUP_ALARM_AUDIO_CONVERT ) * (F32)MA_PER_AMP; + + return result; +} + +/*********************************************************************//** + * @brief * The getFPGAAirTrapLevels function gets the latest air trap level sensor * readings. * @details Inputs: fpgaSensorReadings @@ -1584,119 +1849,215 @@ /*********************************************************************//** * @brief - * The getFPGAArterialAirBubbleStatus function gets the latest arterial air - * bubble detector status. - * @details Inputs: fpgaSensorReadings + * The getDoorState function gets the current state of door switch. + * @details Inputs: none * @details Outputs: none - * @return TRUE if air bubble is detected, otherwise FALSE + * @return current door state *************************************************************************/ -BOOL getFPGAArterialAirBubbleStatus( void ) +OPN_CLS_STATE_T getFPGADoorState( void ) { - U16 const status = fpgaSensorReadings.fpgaGPIO & FPGA_ADA_INPUT_STATUS_MASK; + // TODO: Get actual door state from FPGA or GPIO + BOOL const status = 0x0; - return ( 0 == status ? TRUE : FALSE ); + return ( 0 == status ? STATE_CLOSED : STATE_OPEN ); } /*********************************************************************//** * @brief - * The getFPGAVenousAirBubbleStatus function gets the latest venous air - * bubble detector status. + * The setFPGAValvesControlMode function sets the valves control mode. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param bits : The bits to enable the PID controller of a valve + * @return none + *************************************************************************/ +void setFPGAValvesControlMode( U16 bits ) +{ + fpgaActuatorSetPoints.fpgaPIDControl = bits; +} + +/*********************************************************************//** + * @brief + * The getValvesStatus function reads the status of the valves * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return TRUE if air bubble is detected, otherwise FALSE + * @return The status of the valves *************************************************************************/ -BOOL getFPGAVenousAirBubbleStatus( void ) +U16 getFPGAValvesStatus( void ) { - U16 const status = fpgaSensorReadings.fpgaGPIO & FPGA_ADV_INPUT_STATUS_MASK; - - return ( 0 == status ? FALSE : TRUE ); + return fpgaSensorReadings.valveStatus; } /*********************************************************************//** * @brief - * The setFPGASensorTest function sets the sensor test output. - * @details Inputs: fpgaActuatorSetPoints - * @details Outputs: fpgaActuatorSetPoints - * @param sensorTest - * @return none + * The noFPGAFluidLeakDetected function returns TRUE if no fluid leak has been + * detected (dry) and FALSE if a fluid leak has been detected (wet). + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return noFPGAFluidLeakDetected *************************************************************************/ -void setFPGASensorTest( U08 sensorTest ) +BOOL noFPGAFluidLeakDetected( void ) { - fpgaActuatorSetPoints.fpgaSensorTest = sensorTest; + U16 noFPGAFluidLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_FLUID_LEAK_STATE_MASK; + + return ( 0 == noFPGAFluidLeakDetected ? FALSE : TRUE ); } /*********************************************************************//** * @brief - * The getFPGABloodLeakDetectorStatus function gets the latest blood leak - * detector status. + * The noFPGABloodLeakDetected function returns TRUE if no blood leak has been + * detected and FALSE if a blood leak has been detected. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return TRUE if blood leak is detected, otherwise FALSE + * @return noFPGABloodLeakDetected *************************************************************************/ -BOOL getFPGABloodLeakDetectorStatus( void ) +BOOL noFPGABloodLeakDetected( void ) { - U16 const status = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_STATUS_MASK; + U16 noFPGABloodLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_STATUS_MASK; - return ( 0 == status ? FALSE : TRUE ); + return ( 0 == noFPGABloodLeakDetected ? TRUE : FALSE ); } /*********************************************************************//** * @brief - * The getDoorState function gets the current state of door switch. - * @details Inputs: none + * The FPGABloodLeakZeroDetected function returns TRUE if blood leak zeroing has + * been detected and FALSE if no blood leak zeroing has been detected. + * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return current door state + * @return FPGABloodLeakZeroDetected *************************************************************************/ -OPN_CLS_STATE_T getFPGADoorState( void ) +BOOL FPGABloodLeakZeroDetected( void ) { - // TODO: Get actual door state from FPGA or GPIO - BOOL const status = 0x0; + U16 FPGABloodLeakZeroDetected = fpgaSensorReadings.fpgaGPIO & FPGA_BLOOD_LEAK_ZERO_STATE_MASK; - return ( 0 == status ? STATE_CLOSED : STATE_OPEN ); + return ( 0 == FPGABloodLeakZeroDetected ? FALSE : TRUE ); } /*********************************************************************//** * @brief - * The setFPGAValvesControlMode function sets the valves control mode. - * @details Inputs: fpgaActuatorSetPoints + * The setFPGABloodLeakZero function sets the Blood Leak detector into + * zeroing mode via the FPGA. + * @details Inputs: none * @details Outputs: fpgaActuatorSetPoints - * @param bits : The bits to enable the PID controller of a valve * @return none *************************************************************************/ -void setFPGAValvesControlMode( U16 bits ) +void setFPGABloodLeakZero( void ) { - fpgaActuatorSetPoints.fpgaPIDControl = bits; + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_ZERO_CMD; } /*********************************************************************//** * @brief - * The getValvesStatus function reads the status of the valves + * The clearFPGABloodLeakZero function clears the Blood Leak detector from + * zeroing mode via the FPGA. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return The status of the valves + * @return none *************************************************************************/ -U16 getFPGAValvesStatus( void ) +void clearFPGABloodLeakZero( void ) { - return fpgaSensorReadings.valveStatus; + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_ZERO_CMD; } /*********************************************************************//** * @brief - * The noFluidLeakDetected function returns TRUE if no fluid leak has been - * detected (dry) and FALSE if a fluid leak has been detected (wet). + * The setFPGABloodLeakSelfTest function sets the Blood Leak detector into + * self-test mode via the FPGA. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @return: none + *************************************************************************/ +void setFPGABloodLeakSelfTest( void ) +{ + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_BLOOD_LEAK_SELF_TEST_CMD; +} + +/*********************************************************************//** + * @brief + * The clearFPGABloodLeakSelfTest function clears the Blood Leak detector from + * self-test mode via the FPGA. * @details Inputs: fpgaSensorReadings * @details Outputs: none - * @return noFluidLeakDetected + * @return none *************************************************************************/ -BOOL noFPGAFluidLeakDetected( void ) +void clearFPGABloodLeakSelfTest( void ) { - U16 noFluidLeakDetected = fpgaSensorReadings.fpgaGPIO & FPGA_FLUIDLEAK_STATE_MASK; + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_BLOOD_LEAK_SELF_TEST_CMD; +} - return ( 0 == noFluidLeakDetected ? FALSE : TRUE ); +/*********************************************************************//** + * @brief + * The noFPGABubbleDetected function returns TRUE if no air bubble has been + * detected and FALSE if an air bubble has been detected. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return noFPGABubbleDetected + *************************************************************************/ +BOOL noFPGABubbleDetected( U32 bubble ) +{ + U16 noFPGABubbleDetected = 0; + + if ( bubble == ADA ) + { + noFPGABubbleDetected = fpgaSensorReadings.fpgaGPIO & FPGA_ADA_BUBBLE_STATUS_MASK; + } + else if ( bubble == ADV ) + { + noFPGABubbleDetected = fpgaSensorReadings.fpgaGPIO & FPGA_ADV_BUBBLE_STATUS_MASK; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_BUBBLE_ID, bubble ) + } + + return ( 0 != noFPGABubbleDetected ? TRUE : FALSE ); } /*********************************************************************//** * @brief + * The setFPGABubbleSelfTest function sets the given air bubble detector into + * self-test mode via the FPGA. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @return: none + *************************************************************************/ +void setFPGABubbleSelfTest( U32 bubble ) +{ + if ( bubble == ADA ) + { + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_ADA_BUBBLE_SELF_TEST_CMD; + } + else if ( bubble == ADV ) + { + fpgaActuatorSetPoints.fpgaSensorTest |= FPGA_ADV_BUBBLE_SELF_TEST_CMD; + } +} + +/*********************************************************************//** + * @brief + * The clearFPGABubbleSelfTest function clears the given air bubble detector + * from self-test mode via the FPGA. + * @details Inputs: none + * @details Outputs: fpgaActuatorSetPoints + * @return: none + *************************************************************************/ +void clearFPGABubbleSelfTest( U32 bubble ) +{ + if ( bubble == ADA ) + { + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_ADA_BUBBLE_SELF_TEST_CMD; + } + else if ( bubble == ADV ) + { + fpgaActuatorSetPoints.fpgaSensorTest &= ~FPGA_ADV_BUBBLE_SELF_TEST_CMD; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_BUBBLE_ID, bubble ) + } +} + +/*********************************************************************//** + * @brief * The setValveDialyzerInletPosition function sets the position of VDi * in counts * @details Inputs: fpgaActuatorSetPoints @@ -1938,6 +2299,66 @@ return fpgaSensorReadings.VBACurrent; } +/*********************************************************************//** + * @brief + * The getFPGABoardTemperature function reads the FPGA board temperature. + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return Current FPGA board temperature + *************************************************************************/ +U16 getFPGABoardTemperature( void ) +{ + return fpgaSensorReadings.fpgaTemperature; +} + +/*********************************************************************//** + * The getFPGAFrontDoorStatus function returns the FPGA front door status + * bit. + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return front door FPGA status bit + *************************************************************************/ +U16 getFPGAFrontDoorStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & FRONT_DOOR_SWITCH_MASK ); +} + +/*********************************************************************//** + * @brief + * The getFPGAPBAADCTemperature function reads the PBA ADC temperature. + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return PBA ADC temperature + *************************************************************************/ +U32 getFPGAPBAADCTemperature( void ) +{ + return fpgaSensorReadings.adc1Channel1; +} + +/*********************************************************************//** + * @brief + * The getFPGAInletFan1TogglePeriod function reads the inlet fan 1 pulse time. + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return Inlet fan 1 pulse time + *************************************************************************/ +U16 getFPGAInletFan1TogglePeriod( void ) +{ + return fpgaSensorReadings.fan1PulseTime; +} + +/*********************************************************************//** + * The getFPGAPumpTrackSwitchStatus function returns the FPGA pump track + * switch status bit. + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return pump track switch FPGA status bit + *************************************************************************/ +U16 getFPGAPumpTrackSwitchStatus( void ) +{ + return ( fpgaSensorReadings.fpgaGPIO & PUMP_TRACK_SWITCH_MASK ); +} + #ifdef DEBUG_ENABLED /*********************************************************************//** * @brief