Index: firmware/App/Services/FPGA.c =================================================================== diff -u -rf7e3018ec6ab762fe08efb42b21fb2ca970174b0 -r8e7158d8231435496fcf1d5649e51babf859ccc7 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision f7e3018ec6ab762fe08efb42b21fb2ca970174b0) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 8e7158d8231435496fcf1d5649e51babf859ccc7) @@ -1,936 +1,1635 @@ -/************************************************************************** - * - * Copyright (c) 2019-2020 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 - * - * @date 21-Oct-2019 - * @author S. Nash - * - * @brief FPGA interface service module. Provides an interface to the FPGA. \n - * Various sensor readings are gathered and get functions provided for them. \n - * Various actuator settings are sent and set functions provided for them. - * - **************************************************************************/ +/************************************************************************** +* +* Copyright (c) 2019-2021 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 +* +* @author (last) Sean Nash +* @date (last) 01-Dec-2020 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ + +#include // for memset(), memcpy() + +#include "sci.h" +#include "sys_dma.h" + +#include "FPGA.h" +#include "Comm.h" +#include "SystemCommMessages.h" +#include "Utilities.h" + +/** + * @addtogroup FPGA + * @{ + */ + +// ********** private definitions ********** + +/// Enumeration of FPGA states. +typedef enum FPGA_States +{ + FPGA_STATE_START = 0, ///< Start state for the FPGA. + FPGA_STATE_READ_HEADER, ///< Read header command state for the FPGA. + FPGA_STATE_RCV_HEADER, ///< Receive header state for the FPGA. + FPGA_STATE_WRITE_ALL_ACTUATORS, ///< Write actuators command state for the FPGA. + FPGA_STATE_RCV_ALL_SENSORS, ///< Receive sensors state for the FPGA. + FPGA_STATE_READ_ALL_SENSORS_ASYNC, ///< Read async sensors state for the FPGA. + FPGA_STATE_RCV_ALL_SENSORS_ASYNC, ///< Receive async sensors state for the FPGA. + FPGA_STATE_FAILED, ///< Failed state for the FPGA. + NUM_OF_FPGA_STATES ///< Number of FPGA states. +} FPGA_STATE_T; + +#define FPGA_PAGE_SIZE 256 ///< FPGA register pages are 256 bytes. +#define FPGA_EXPECTED_ID 0x5A ///< Expected ID for HD FPGA. + +#define FPGA_HEADER_START_ADDR 0x0000 ///< Start address for FPGA header data. +#define FPGA_BULK_READ_START_ADDR 0x0100 ///< Start address for FPGA continuous priority reads. +#define FPGA_BULK_WRITE_START_ADDR 0x000C ///< Start address for FPGA continuous priority writes. +#define FPGA_BULK_ASYNC_READ_START_ADDR 0x0200 ///< Start address for FPGA async reads. + +#define FPGA_WRITE_CMD_BUFFER_LEN (FPGA_PAGE_SIZE+8) ///< FPGA write command buffer byte length. +#define FPGA_READ_CMD_BUFFER_LEN 8 ///< FPGA read command buffer byte length. +#define FPGA_WRITE_RSP_BUFFER_LEN 8 ///< FPGA write command response buffer byte length. +#define FPGA_READ_RSP_BUFFER_LEN (FPGA_PAGE_SIZE+8) ///< FPGA read command response buffer byte length. + +#define FPGA_WRITE_CMD_CODE 0x55 ///< FPGA write command code. +#define FPGA_READ_CMD_CODE 0x5A ///< FPGA read command code. +#define FPGA_WRITE_CMD_ACK 0xA5 ///< FPGA write command ACK code. +#define FPGA_READ_CMD_ACK 0xAA ///< FPGA read command ACK code. +#define FPGA_CMD_NAK 0xEE ///< FPGA command NAK code. + +#define FPGA_CRC_LEN 2 ///< FPGA CRC byte length. +#define FPGA_WRITE_CMD_HDR_LEN 4 ///< FPGA write command header byte length. +#define FPGA_READ_CMD_HDR_LEN 4 ///< FPGA read command header byte length. +#define FPGA_WRITE_RSP_HDR_LEN 3 ///< FPGA write command response header byte length. +#define FPGA_READ_RSP_HDR_LEN 3 ///< FPGA read command response header byte length. + +#define SCI2_RECEIVE_DMA_REQUEST 28 ///< Serial port 2 receive DMA request line. +#define SCI2_TRANSMIT_DMA_REQUEST 29 ///< Serial port 2 transmit DMA request line. + +#define MAX_COMM_ERROR_RETRIES 5 ///< Maximum consecutive FPGA communication error retries. + +#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. + +// FPGA Sensors Record +#pragma pack(push,1) +/// Record structure for FPGA header read. +typedef struct +{ + U08 fpgaId; ///< Reg 0. FPGA ID code. Checked against expected value at power up to verify basic FPGA communication and operation. + U08 fpgaRev; ///< Reg 1. FPGA revision (minor) being reported. + U08 fpgaRevMajor; ///< Reg 2. FPGA revision (major) being reported. + U08 fpgaRevLab; ///< Reg 3. FPGA revision (lab) being reported. + U16 fpgaStatus; ///< Reg 4. FPGA status register. + U08 fpgaDiag; ///< Reg 6. FPGA diagnostic (R/W) register. + U08 adc1Control; ///< Reg 7. ADC1 control register. Bit 0=auto read enable. + U08 flowDAQ1Cmd; ///< Reg 8. Command passed to flow DAQ #1. + U08 flowDAQ2Cmd; ///< Reg 9. Command passed to flow DAQ #2. + U08 accelCmd; ///< Reg 10. Command passed to accelerometer. + U08 fpgaSensorTest; ///< Reg 11. Blood leak and bubble detector sensor test register. + U16 fpgaPIDControl; ///< Reg 12. Valve PID enables. +} FPGA_HEADER_T; // read only on FPGA + +/// Record structure for FPGA continuous priority reads. +typedef struct // TODO - add all sensor readings to this structure per FPGA register map +{ + U08 errorCountProcessor; ///< Reg 256. TBD. + U08 errorCountPC; ///< Reg 257. TBD. + U08 bloodFlowMeterDataPktCount; ///< Reg 258. Blood flow sensor data packet count. + U08 bloodFlowMeterSlowPktCounts; ///< Reg 259. Blood flow sensor slow data packet count. + F32 bloodFlowLast; ///< Reg 260. Blood flow rate data. + U08 bloodFlowMeterDeviceStatus; ///< Reg 264. Blood flow sensor status. + U08 bloodFlowMeterResponse; ///< Reg 265. TBD. + U08 dialysateFlowMeterDataPktCount; ///< Reg 266. Dialysate flow sensor data packet count. + U08 dialysateFlowMeterSlowPckCounts; ///< Reg 267. Dialysate flow sensor slow data packet count. + F32 dialysateFlowLast; ///< Reg 268. Dialysate flow rate data. + U08 dialysateFlowMeterDeviceStatus; ///< Reg 272. Dialysate flow sensor status. + U08 dialysateFlowMeterResponse; ///< Reg 273. TBD. + U08 bloodFlowMeterErrorCount; ///< Reg 274. Blood flow sensor error count. + U08 dialysateFlowMeterErrorCount; ///< Reg 275. Dialysate flow sensor error count. + 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 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. + 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. + U16 accelX; ///< Reg 314. Accelerometer X axis data. + U16 accelY; ///< Reg 316. Accelerometer Y axis data. + U16 accelZ; ///< Reg 318. Accelerometer Z axis data. + U16 accelXMax; ///< Reg 320. Accelerometer X axis max data (since last read). + U16 accelYMax; ///< Reg 322. Accelerometer Y axis max data (since last read). + U16 accelZMax; ///< Reg 324. Accelerometer Z axis max data (since last read). + U16 accelFaultRegister; ///< Reg 326. Accelerometer fault register. + U16 accelSampleCounter; ///< Reg 328. Accelerometer sample count. + U16 venousPressure; ///< Reg 330. Venous pressure sensor data. + U16 venousTemperature; ///< Reg 332. Venous pressure sensor temperature. + U08 venousReadCounter; ///< Reg 334. Venous pressure sensor read count. + U08 dialOutPumpSensorStatus; ///< Reg 335. Dialysate outlet pump hall sensor status. + 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. + 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. + U16 fpgaGPIO; ///< Reg 356. FPGA GPIO register. + S16 VBAPosition; ///< Reg 358. Encoder position from VBA pinch valve. 0 until PID interface is enabled. + 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. + 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 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. + 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) + 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 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) +} FPGA_SENSORS_T; + +/// Record structure for FPGA continuous priority writes. +typedef struct // TODO - add all actuator set points to this structure per FPGA register map +{ + U16 fpgaPIDControl; ///< Reg 12. Valve PID enables. + S16 VBASetPoint; ///< Reg 14. VBA pinch valve is commanded to this set point position. + S16 VBVSetPoint; ///< Reg 16. VBV pinch valve is commanded to this set point position. + S16 VDiSetPoint; ///< Reg 18. VDi pinch valve is commanded to this set point position. + S16 VDoSetPoint; ///< Reg 20. VDo pinch valve is commanded to this set point position. + S16 VSpareSetPoint; ///< Reg 22. VSpare pinch valve is commanded to this set point position. + U16 VBAPWMFixed; ///< Reg 24. VBA PWM set to fixed current by setting fixed PWM duty cycle. Range 750 to 4250. < 2500 is reverse direction. + U16 VBVPWMFixed; ///< Reg 26. VBV PWM set to fixed current by setting fixed PWM duty cycle. Range 750 to 4250. < 2500 is reverse direction. + 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. +} FPGA_ACTUATORS_T; + +// TODO clean up the struct +/// Record structure for FPGA async (as needed) reads. +typedef struct // TODO - add all sensor readings to this structure per FPGA register map +{ + U16 fpgaDieTemp; ///< Reg 512. Internal FPGA die temperature. + U16 fpgaADCVccVoltage; ///< Reg 514. Internal FPGA Vcc voltage. + U16 fpgaADCVccAuxVoltage; ///< Reg 516. Internal FPGA Vcc aux voltage. + U16 fpgaADCVpvnVoltage; ///< Reg 518. Internal FPGA VPVN voltage. + U16 fpgaVAux0Voltage; ///< Reg 520. Aux. voltage 0. + U16 fpgaVAux1Voltage; ///< Reg 522. Aux. voltage 1. + U16 fpgaVAux2Voltage; ///< Reg 524. Aux. voltage 2. + U16 fpgaVAux3Voltage; ///< Reg 526. Aux. voltage 3. + U16 fpgaVAux8Voltage; ///< Reg 528. Aux. voltage 8. + U16 fpgaVAux9Voltage; ///< Reg 530. Aux. voltage 9. + U16 fpgaVAux10Voltage; ///< Reg 532. Aux. voltage 10. + U16 fpgaVAux11Voltage; ///< Reg 534. Aux. voltage 11. + F32 bloodFlowSoundSpeed; ///< Reg 536. Blood flow sound speed. + F32 bloodFlowAccFlow; ///< Reg 540. Blood flow accumulated flow. + F32 bloodFlowSignalStrength; ///< Reg 544. Blood flow signal strength. + F32 dialysateInFlowSoundSpeed; ///< Reg 548. Dialysate inlet flow sound speed. + F32 dialysateInFlowAccFlow; ///< Reg 552. Dialysate inlet flow accumulated flow. + F32 dialysateInFlowSignalStrength; ///< Reg 556. Dialysate inlet flow signal strength. + U16 fpgaVAux5Voltage; ///< Reg 560. Aux. voltage 5. +} FPGA_SENSORS_ASYNC_T; +#pragma pack(pop) + +// ********** private data ********** + +// FPGA state +static FPGA_STATE_T fpgaState = FPGA_STATE_START; ///< Current FPGA state. + +static U32 fpgaCommRetryCount = 0; ///< FPGA communication retry counter. +static U32 fpgaReceiptCounter = 0; ///< FPGA response receipt counter. +static U32 fpgaTransmitCounter = 0; ///< FPGA command transmit counter. +static BOOL fpgaWriteCommandInProgress = FALSE; ///< Flag indicating an FPGA write command is in progress. +static BOOL fpgaReadCommandInProgress = FALSE; ///< Flag indicating an FPGA read command is in progress. +static BOOL fpgaBulkWriteAndReadInProgress = FALSE; ///< Flag indicating an FPGA bulk write and read command are in progress. +static BOOL fpgaWriteCommandResponseReceived = FALSE; ///< Flag indicating a response to an FPGA write command has been received. +static BOOL fpgaReadCommandResponseReceived = FALSE; ///< Flag indicating a response to an FPGA read command has been received. + +// FPGA comm buffers +static U08 fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_BUFFER_LEN ]; ///< FPGA write command buffer. Holds the next FPGA write command to be transmitted. +static U08 fpgaReadCmdBuffer[ FPGA_READ_CMD_BUFFER_LEN ]; ///< FPGA read command buffer. Holds the next FPGA read command to be transmitted. +static U08 fpgaWriteResponseBuffer[ FPGA_WRITE_RSP_BUFFER_LEN ]; ///< FPGA write command response buffer. Memory reserved to capture the response to the last FPGA write command. +static U08 fpgaReadResponseBuffer[ FPGA_READ_RSP_BUFFER_LEN ]; ///< FPGA read command response buffer. Memory reserved to capture the response to the last FPGA read command. + +// DMA control records +static g_dmaCTRL fpgaDMAWriteControlRecord; ///< DMA record for controlling a DMA write command transmission from buffer. +static g_dmaCTRL fpgaDMAWriteRespControlRecord; ///< DMA record for controlling a DMA write command reception to buffer. +static g_dmaCTRL fpgaDMAReadControlRecord; ///< DMA record for controlling a DMA read command transmission from buffer. +static g_dmaCTRL fpgaDMAReadRespControlRecord; ///< DMA record for controlling a DMA read command reception to buffer. + +// FPGA data +static FPGA_HEADER_T fpgaHeader; ///< Record of last received FPGA header data. +static FPGA_SENSORS_T fpgaSensorReadings; ///< Record of last received FPGA priority sensor data. +static FPGA_ACTUATORS_T fpgaActuatorSetPoints; ///< Record of next transmitted FPGA priority actuator data. +#ifdef READ_FPGA_ASYNC_DATA +static FPGA_SENSORS_ASYNC_T fpgaSensorReadingsAsync; ///< Record of last received async (as needed) FPGA sensor data. +#endif + +// ********** private function prototypes ********** + +static FPGA_STATE_T handleFPGAReadHeaderState( void ); +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ); +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ); +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ); +#ifdef READ_FPGA_ASYNC_DATA +static FPGA_STATE_T handleFPGAReceiveAllSensorsAsyncState( void ); +static FPGA_STATE_T handleFPGAReadAllSensorsAsyncState( void ); +#endif + +static void resetFPGACommFlags( void ); +static void setupDMAForWriteCmd( U32 bytes2Transmit ); +static void startDMAWriteCmd( void ); +static void setupDMAForWriteResp( U32 bytes2Receive ); +static void startDMAReceiptOfWriteResp( void ); +static void setupDMAForReadCmd( U32 bytes2Transmit ); +static void startDMAReadCmd( void ); +static void setupDMAForReadResp( U32 bytes2Receive ); +static void startDMAReceiptOfReadResp( void ); + +static void consumeUnexpectedData( void ); + +/*********************************************************************//** + * @brief + * The initFPGA function initializes the FPGA module. + * @details Inputs: none + * @details Outputs: FPGA module initialized. + * @return none + *************************************************************************/ +void initFPGA( void ) +{ + // initialize fpga data structures + memset( &fpgaHeader, 0, sizeof(FPGA_HEADER_T) ); + memset( &fpgaSensorReadings, 0, sizeof(FPGA_SENSORS_T) ); + memset( &fpgaActuatorSetPoints, 0, sizeof(FPGA_ACTUATORS_T) ); + + // initialize fpga comm buffers + memset( &fpgaWriteCmdBuffer, 0, FPGA_WRITE_CMD_BUFFER_LEN ); + memset( &fpgaReadCmdBuffer, 0, FPGA_READ_CMD_BUFFER_LEN ); + memset( &fpgaWriteResponseBuffer, 0, FPGA_WRITE_RSP_BUFFER_LEN ); + memset( &fpgaReadResponseBuffer, 0, FPGA_READ_RSP_BUFFER_LEN ); + + // enable interrupt notifications for FPGA serial port + sciEnableNotification( scilinREG, SCI_OE_INT | SCI_FE_INT ); + + // assign DMA channels to h/w DMA requests + dmaReqAssign( DMA_CH0, SCI2_RECEIVE_DMA_REQUEST ); + dmaReqAssign( DMA_CH2, SCI2_TRANSMIT_DMA_REQUEST ); + // set DMA channel priorities + dmaSetPriority( DMA_CH0, HIGHPRIORITY ); + dmaSetPriority( DMA_CH2, LOWPRIORITY ); + // Enable DMA block transfer complete interrupts + dmaEnableInterrupt( DMA_CH0, BTC ); + dmaEnableInterrupt( DMA_CH2, BTC ); + + // initialize FPGA DMA Write Control Record + fpgaDMAWriteControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteCmdBuffer; // transfer source address + fpgaDMAWriteControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register + fpgaDMAWriteControlRecord.CHCTRL = 0; // no chaining + fpgaDMAWriteControlRecord.ELCNT = 1; // frame is 1 element + fpgaDMAWriteControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known + fpgaDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + fpgaDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + fpgaDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed + fpgaDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + fpgaDMAWriteControlRecord.ELSOFFSET = 0; // not used + fpgaDMAWriteControlRecord.ELDOFFSET = 0; // not used + fpgaDMAWriteControlRecord.FRSOFFSET = 0; // not used + fpgaDMAWriteControlRecord.FRDOFFSET = 0; // not used + + // initialize FPGA DMA Write Response Control Record + fpgaDMAWriteRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAWriteRespControlRecord.SADD = (U32)(&(scilinREG->RD));// source is SCI2 recv register + fpgaDMAWriteRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // transfer destination address + fpgaDMAWriteRespControlRecord.CHCTRL = 0; // no chaining + fpgaDMAWriteRespControlRecord.ELCNT = 1; // frame is 1 element + fpgaDMAWriteRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known + fpgaDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + fpgaDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + fpgaDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed + fpgaDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment + fpgaDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // not used + fpgaDMAWriteRespControlRecord.ELSOFFSET = 0; // not used + fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // not used + fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // not used + + // initialize FPGA DMA Read Control Record + fpgaDMAReadControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAReadControlRecord.SADD = (U32)fpgaReadCmdBuffer; // transfer source address + fpgaDMAReadControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register + fpgaDMAReadControlRecord.CHCTRL = 0; // no chaining + fpgaDMAReadControlRecord.ELCNT = 1; // frame is 1 element + fpgaDMAReadControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known + fpgaDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + fpgaDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + fpgaDMAReadControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed + fpgaDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + fpgaDMAReadControlRecord.ELSOFFSET = 0; // not used + fpgaDMAReadControlRecord.ELDOFFSET = 0; // not used + fpgaDMAReadControlRecord.FRSOFFSET = 0; // not used + fpgaDMAReadControlRecord.FRDOFFSET = 0; // not used + + // initialize FPGA DMA Read Response Control Record + fpgaDMAReadRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAReadRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // source is SCI2 recv register + fpgaDMAReadRespControlRecord.DADD = (U32)fpgaReadResponseBuffer; // transfer destination address + fpgaDMAReadRespControlRecord.CHCTRL = 0; // no chaining + fpgaDMAReadRespControlRecord.ELCNT = 1; // frame is 1 element + fpgaDMAReadRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known + fpgaDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + fpgaDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; // + fpgaDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + fpgaDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed + fpgaDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment + fpgaDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // not used + fpgaDMAReadRespControlRecord.ELSOFFSET = 0; // not used + fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // not used + fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // not used + + // there shouldn't be any data pending yet + consumeUnexpectedData(); +} + +/*********************************************************************//** + * @brief + * The resetFPGACommFlags function resets the various fpga comm flags and + * counters. + * @details Inputs: none + * @details Outputs: fpga comm flags & counters reset + * @return none + *************************************************************************/ +static void resetFPGACommFlags( void ) +{ + fpgaWriteCommandResponseReceived = FALSE; + fpgaReadCommandResponseReceived = FALSE; + fpgaWriteCommandInProgress = FALSE; + fpgaReadCommandInProgress = FALSE; + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaTransmitCounter = 0; + fpgaReceiptCounter = 0; +} + +/*********************************************************************//** + * @brief + * The signalFPGAReceiptCompleted function increments a counter to indicate + * that another DMA receipt from the FPGA has completed. + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter + * @return none + *************************************************************************/ +void signalFPGAReceiptCompleted( void ) +{ + fpgaReceiptCounter++; + // did FPGA Ack last command? + if ( TRUE == fpgaWriteCommandInProgress ) + { + fpgaWriteCommandInProgress = FALSE; + fpgaWriteCommandResponseReceived = TRUE; + } + else if ( TRUE == fpgaReadCommandInProgress ) + { + fpgaReadCommandInProgress = FALSE; + fpgaReadCommandResponseReceived = TRUE; + } + + // see if we want to follow up with a bulk read command + if ( TRUE == fpgaBulkWriteAndReadInProgress ) + { + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaReadCommandInProgress = TRUE; + // initiate bulk read command + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + } +} + +/*********************************************************************//** + * @brief + * The signalFPGATransmitCompleted function increments a counter to indicate + * that another DMA transmit to the FPGA has completed. + * @details Inputs: none + * @details Outputs: fpgaReceiptCounter + * @return none + *************************************************************************/ +void signalFPGATransmitCompleted( void ) +{ + fpgaTransmitCounter++; +} + +/*********************************************************************//** + * @brief + * The execFPGA function manages incoming data exchanges with the FPGA. + * @details Inputs: fpgaState + * @details Outputs: fpgaState + * @return none + *************************************************************************/ +void execFPGAIn( void ) +{ + // FPGA incoming state machine + switch ( fpgaState ) + { + case FPGA_STATE_START: + fpgaState = FPGA_STATE_READ_HEADER; + break; + + case FPGA_STATE_RCV_HEADER: + fpgaState = handleFPGAReceiveHeaderState(); + break; + + // TODO - sensor/ADC init/configuration states + + case FPGA_STATE_RCV_ALL_SENSORS: + fpgaState = handleFPGAReceiveAllSensorsState(); + break; + +#ifdef READ_FPGA_ASYNC_DATA + case FPGA_STATE_RCV_ALL_SENSORS_ASYNC: + fpgaState = handleFPGAReceiveAllSensorsAsyncState(); + break; +#endif + + case FPGA_STATE_FAILED: + // do nothing - we'll be stuck here + break; + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_IN_STATE, fpgaState ) + } + else + { + // ok, some states handled in the outgoing state machine + } + break; + } + + // if retries for commands exceeds limit, fault + if ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) + { + // TODO - FPGA comm fault + } + + // reset comm flags after processing incoming responses + resetFPGACommFlags(); +} + +/*********************************************************************//** + * @brief + * The execFPGAOut function manages outgoing data exchanges with the FPGA. + * @details Inputs: fpgaState + * @details Outputs: fpgaState + * @return none + *************************************************************************/ +void execFPGAOut( void ) +{ + // FPGA outgoing state machine + switch ( fpgaState ) + { + case FPGA_STATE_READ_HEADER: + fpgaState = handleFPGAReadHeaderState(); + break; + + // TODO - sensor/ADC init/configuration states + + case FPGA_STATE_WRITE_ALL_ACTUATORS: + fpgaState = handleFPGAWriteAllActuatorsState(); + break; + + case FPGA_STATE_FAILED: + // do nothing - we'll be stuck here + break; + +#ifdef READ_FPGA_ASYNC_DATA + case FPGA_STATE_READ_ALL_SENSORS_ASYNC: + fpgaState = handleFPGAReadAllSensorsAsyncState(); + break; +#endif + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_OUT_STATE, fpgaState ) + } + else + { + // ok, some states handled in the incoming state machine + } + break; + } +} + +/*********************************************************************//** + * @brief + * The handleFPGAReadHeaderState function handles the FPGA state where + * the read header registers command is sent to the FPGA. + * @details Inputs: none + * @details Outputs: read command sent to FPGA + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReadHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_HEADER; + U16 crc; + + // construct read command to read 3 registers starting at address 0 + fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_HEADER_START_ADDR ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_HEADER_START_ADDR ); + fpgaReadCmdBuffer[ 3 ] = sizeof(FPGA_HEADER_T); + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + // prep DMA for sending the read cmd and receiving the response + fpgaReadCommandInProgress = TRUE; + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T) + FPGA_CRC_LEN ); + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAReceiveHeaderState function handles the FPGA state + * where the header registers read response should be ready to take in. + * @details Inputs: none + * @details Outputs: header register values updated + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_READ_HEADER; + + // did we get an FPGA response? + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T); + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) + { + fpgaCommRetryCount = 0; + // capture the read values + memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else + { + fpgaCommRetryCount++; + } + } + else // header read was NAK'd + { + fpgaCommRetryCount++; + } + } + else // no response to read command + { + fpgaCommRetryCount++; + } + + // shouldn't be any data received at this time + consumeUnexpectedData(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAWriteAllActuatorsState function handles the FPGA state + * where the bulk write command is sent to the FPGA. + * @details Inputs: actuator set points + * @details Outputs: actuator set points sent to FPGA + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_ALL_SENSORS; + U16 crc; + + // construct bulk write command to write actuator data registers starting at address 3 (TODO - change address later) + fpgaWriteCmdBuffer[ 0 ] = FPGA_WRITE_CMD_CODE; + fpgaWriteCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); + fpgaWriteCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_WRITE_START_ADDR ); + fpgaWriteCmdBuffer[ 3 ] = sizeof(FPGA_ACTUATORS_T); + memcpy( &( fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN ] ), &fpgaActuatorSetPoints, sizeof( FPGA_ACTUATORS_T ) ); + crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ); + fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ] = GET_MSB_OF_WORD( crc ); + fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) + 1 ] = GET_LSB_OF_WORD( crc ); + + // construct bulk read command to read sensor data registers starting at address 8 + fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_READ_START_ADDR ); + fpgaReadCmdBuffer[ 3 ] = sizeof(FPGA_SENSORS_T); + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + + // prep DMA for sending the bulk write cmd and receiving its response + setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) + FPGA_CRC_LEN ); + setupDMAForWriteResp( FPGA_WRITE_RSP_HDR_LEN + FPGA_CRC_LEN ); + // prep DMA for sending the bulk read cmd and receiving its response + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_SENSORS_T ) + FPGA_CRC_LEN ); + // set fpga comm flags for bulk write cmd and follow-up bulk read command + fpgaWriteCommandInProgress = TRUE; + fpgaBulkWriteAndReadInProgress = TRUE; + // initiate bulk write command and it's receipt - read will follow + startDMAReceiptOfWriteResp(); + startDMAWriteCmd(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAReceiveAllSensorsState function handles the FPGA state + * where the bulk read response should be ready to parse. + * @details Inputs: none + * @details Outputs: sensor values updated + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_WRITE_ALL_ACTUATORS; + + // check bulk write command success + if ( ( FALSE == fpgaWriteCommandResponseReceived ) || ( fpgaWriteResponseBuffer[ 0 ] != FPGA_WRITE_CMD_ACK ) ) + { + fpgaCommRetryCount++; + } + + // if bulk read command is ACK'd, collect the readings + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_T); + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) + { + fpgaCommRetryCount = 0; + // capture the read values + memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_SENSORS_T ) ); +#ifndef READ_FPGA_ASYNC_DATA + result = FPGA_STATE_WRITE_ALL_ACTUATORS; +#else + result = FPGA_STATE_READ_ALL_SENSORS_ASYNC; +#endif + } + else // bad CRC + { + fpgaCommRetryCount++; + } + } + else // read command was NAK'd + { + fpgaCommRetryCount++; + } + } + else // no response to read command + { + fpgaCommRetryCount++; + } + + // shouldn't be any data received at this time + consumeUnexpectedData(); + + return result; +} + +#ifdef READ_FPGA_ASYNC_DATA +/*********************************************************************//** + * @brief + * The handleFPGAReadAllSensorsAsyncState function handles the FPGA state where + * the read async sensors command is sent to the FPGA. + * @details Inputs: none + * @details Outputs: read async sensors command sent to FPGA + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReadAllSensorsAsyncState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_ALL_SENSORS_ASYNC; + U16 crc; + + // construct read command to read low priority async registers starting at address 0x200 + fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[ 1 ] = GET_LSB_OF_WORD( FPGA_BULK_ASYNC_READ_START_ADDR ); + fpgaReadCmdBuffer[ 2 ] = GET_MSB_OF_WORD( FPGA_BULK_ASYNC_READ_START_ADDR ); + fpgaReadCmdBuffer[ 3 ] = sizeof(FPGA_SENSORS_ASYNC_T); + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); + fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); + // prep DMA for sending the read cmd and receiving the response + fpgaReadCommandInProgress = TRUE; + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_ASYNC_T) + FPGA_CRC_LEN ); + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleFPGAReceiveAllSensorsAsyncState function handles the FPGA state + * where the bulk async read response should be ready to parse. + * @details Inputs: none + * @details Outputs: async sensor values updated + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveAllSensorsAsyncState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_READ_ALL_SENSORS_ASYNC; + + // if bulk read command is ACK'd, collect the readings + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_ASYNC_T); + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) + { + fpgaCommRetryCount = 0; + // capture the read values + memcpy( &fpgaSensorReadingsAsync, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_SENSORS_ASYNC_T ) ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else // bad CRC + { + fpgaCommRetryCount++; + } + } + else // read command was NAK'd + { + fpgaCommRetryCount++; + } + } + else // no response to read command + { + fpgaCommRetryCount++; + } + + // shouldn't be any data received at this time + consumeUnexpectedData(); + + return result; +} +#endif + +/*********************************************************************//** + * @brief + * The execFPGATest function executes the FPGA self-test. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return passed, or failed + *************************************************************************/ +SELF_TEST_STATUS_T execFPGATest( void ) +{ + SELF_TEST_STATUS_T result; + + // check FPGA reported correct ID +#ifndef RM46_EVAL_BOARD_TARGET + if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) +#else + if ( 1 ) +#endif + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaId ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The consumeUnexpectedData function checks to see if a byte is sitting in + * the SCI2 received data register. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return fpgaDiag + *************************************************************************/ +static void consumeUnexpectedData( void ) +{ + // clear any errors + sciRxError( scilinREG ); + + // if a byte is pending read, read it + if ( sciIsRxReady( scilinREG ) != 0 ) + { + sciReceiveByte( scilinREG ); + } +} + +/*********************************************************************//** + * @brief + * The setupDMAForWriteCmd function sets the byte count for the next DMA + * write command to the FPGA. + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA write command is set + * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA + * @return none + *************************************************************************/ +static void setupDMAForWriteCmd( U32 bytes2Transmit ) +{ + // verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_WRITE_CMD_BUFFER_LEN ) + { + fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, bytes2Transmit ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAWriteCmd function initiates the DMA transmit for the next + * DMA write command to the FPGA. + * @details Inputs: none + * @details Outputs: DMA write command to FPGA is initiated + * @return none + *************************************************************************/ +static void startDMAWriteCmd( void ) +{ + dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord ); + dmaSetChEnable( DMA_CH2, DMA_HW ); + setSCI2DMATransmitInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForWriteResp function sets the expected byte count for the + * next DMA write command response from the FPGA. + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA write command response is set + * @param bytes2Receive number of bytes expected to be transmitted via DMA from the FPGA + * @return none + *************************************************************************/ +static void setupDMAForWriteResp( U32 bytes2Receive ) +{ + // verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_WRITE_RSP_BUFFER_LEN ) + { + fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, bytes2Receive ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReceiptOfWriteResp function initiates readiness of the DMA + * receiver for the next DMA write command response from the FPGA. + * @details Inputs: none + * @details Outputs: DMA write command response is ready to be received from the FPGA + * @return none + *************************************************************************/ +static void startDMAReceiptOfWriteResp( void ) +{ + dmaSetCtrlPacket( DMA_CH0, fpgaDMAWriteRespControlRecord ); + dmaSetChEnable( DMA_CH0, DMA_HW ); + setSCI2DMAReceiveInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForReadCmd function sets the byte count for the next DMA + * read command to the FPGA. + * @details Inputs: none + * @details Outputs: number of bytes for next FPGA read command is set + * @param bytes2Transmit number of bytes to be transmitted via DMA to the FPGA + * @return none + *************************************************************************/ +static void setupDMAForReadCmd( U32 bytes2Transmit ) +{ + // verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_READ_CMD_BUFFER_LEN ) + { + fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, bytes2Transmit ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReadCmd function initiates the DMA transmit for the next + * DMA read command to the FPGA. + * @details Inputs: none + * @details Outputs: DMA read command to FPGA is initiated + * @return none + *************************************************************************/ +static void startDMAReadCmd( void ) +{ + dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord ); + dmaSetChEnable( DMA_CH2, DMA_HW ); + setSCI2DMATransmitInterrupt(); +} + +/*********************************************************************//** + * @brief + * The setupDMAForReadResp function sets the expected byte count for the + * next DMA read command response from the FPGA. + * @details Inputs: none + * @details Outputs: number of expected bytes for next FPGA read command response is set + * @param bytes2Receive number of expected bytes to be transmitted via DMA from the FPGA + * @return none + *************************************************************************/ +static void setupDMAForReadResp( U32 bytes2Receive ) +{ + // verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_READ_RSP_BUFFER_LEN ) + { + fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, bytes2Receive ) + } +} + +/*********************************************************************//** + * @brief + * The startDMAReceiptOfReadResp function initiates readiness of the DMA + * receiver for the next DMA read command response from the FPGA. + * @details Inputs: none + * @details Outputs: DMA read command response is ready to be received from the FPGA + * @return none + *************************************************************************/ +static void startDMAReceiptOfReadResp( void ) +{ + dmaSetCtrlPacket( DMA_CH0, fpgaDMAReadRespControlRecord ); + dmaSetChEnable( DMA_CH0, DMA_HW ); + setSCI2DMAReceiveInterrupt(); +} + +/*********************************************************************//** + * @brief + * The getFPGAVersions function gets the fpga version numbers. + * @details Inputs: fpgaHeader + * @details Outputs: none + * @return none + *************************************************************************/ +void getFPGAVersions( U08 *Id, U08 *Maj, U08 *Min, U08 *Lab ) +{ + *Id = fpgaHeader.fpgaId; + *Min = fpgaHeader.fpgaRev; + *Maj = fpgaHeader.fpgaRevMajor; + *Lab = fpgaHeader.fpgaRevLab; +} + +/*********************************************************************//** + * @brief + * The getFPGABloodFlowSignalStrength function gets the latest blood flow + * signal strength reading. + * @details Inputs: fpgaSensorReadings2 + * @details Outputs: none + * @return last blood flow signal strength reading + *************************************************************************/ +F32 getFPGABloodFlowSignalStrength( void ) +{ + return fpgaSensorReadings.bloodFlowSignalStrength; +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateFlowSignalStrength function gets the latest dialysate + * flow signal strength reading. + * @details Inputs: fpgaSensorReadings2 + * @details Outputs: none + * @return last dialysate flow signal strength reading + *************************************************************************/ +F32 getFPGADialysateFlowSignalStrength( void ) +{ + return fpgaSensorReadings.dialysateFlowSignalStrength; +} + +/*********************************************************************//** + * @brief + * The getFPGABloodFlow function gets the latest blood flow reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last blood flow reading + *************************************************************************/ +F32 getFPGABloodFlow( void ) +{ + return fpgaSensorReadings.bloodFlowLast; +} + +/*********************************************************************//** + * @brief + * The getFPGADialysateFlow function gets the latest dialysate flow reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate flow reading + *************************************************************************/ +F32 getFPGADialysateFlow( void ) +{ + return fpgaSensorReadings.dialysateFlowLast; +} + +/*********************************************************************//** + * @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 + * counting down, indicates motor is running in reverse direction. Counter will + * wrap at 0/65535. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last blood pump hall sensor count reading. + *************************************************************************/ +U16 getFPGABloodPumpHallSensorCount( void ) +{ + return fpgaSensorReadings.bloodPumpHallSensorCount; +} + +/*********************************************************************//** + * @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 + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last blood pump hall sensor status reading. + *************************************************************************/ +U08 getFPGABloodPumpHallSensorStatus( void ) +{ + return fpgaSensorReadings.bloodPumpHallSensorStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGADialInPumpHallSensorCount function gets the latest dialysate inlet 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 + * counting down, indicates motor is running in reverse direction. Counter will + * wrap at 0/65535. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate inlet pump hall sensor count reading. + *************************************************************************/ +U16 getFPGADialInPumpHallSensorCount( void ) +{ + return fpgaSensorReadings.dialInPumpHallSensorCount; +} + +/*********************************************************************//** + * @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 + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate inlet pump hall sensor status reading. + *************************************************************************/ +U08 getFPGADialInPumpHallSensorStatus( void ) +{ + return fpgaSensorReadings.dialInPumpHallSensorStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGADialOutPumpHallSensorCount function gets the latest dialysate outlet 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 + * counting down, indicates motor is running in reverse direction. Counter will + * wrap at 0/65535. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate outlet pump hall sensor count reading. + *************************************************************************/ +U16 getFPGADialOutPumpHallSensorCount( void ) +{ + return fpgaSensorReadings.dialOutPumpHallSensorCount; +} + +/*********************************************************************//** + * @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 + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate outlet pump hall sensor status reading. + *************************************************************************/ +U08 getFPGADialOutPumpHallSensorStatus( void ) +{ + return fpgaSensorReadings.dialOutPumpSensorStatus; +} + +/*********************************************************************//** + * @brief + * The getFPGABloodPumpOcclusion function gets the latest blood occlusion reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last blood occlusion reading + *************************************************************************/ +U16 getFPGABloodPumpOcclusion( void ) +{ + return fpgaSensorReadings.bloodOcclusionData; +} + +/*********************************************************************//** + * @brief + * The getFPGADialInPumpOcclusion function gets the latest dialysate + * inlet occlusion reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate inlet occlusion reading + *************************************************************************/ +U16 getFPGADialInPumpOcclusion( void ) +{ + return fpgaSensorReadings.dialysateInOcclusionData; +} + +/*********************************************************************//** + * @brief + * The getFPGADialOutPumpOcclusion function gets the latest dialysate + * outlet occlusion reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last dialysate outlet occlusion reading + *************************************************************************/ +U16 getFPGADialOutPumpOcclusion( void ) +{ + return fpgaSensorReadings.dialysateOutOcclusionData; +} + +/*********************************************************************//** + * @brief + * The getFPGAArterialPressure function gets the latest arterial pressure reading. + * High byte indicates alarm status for ADC channel. + * Low 24-bits are channel reading. Subtract 2^23 from low 24 bits to get + * signed channel reading. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last arterial pressure reading + *************************************************************************/ +U32 getFPGAArterialPressure( void ) +{ + return fpgaSensorReadings.adc1Channel0; +} + +/*********************************************************************//** + * @brief + * The getFPGAVenousPressure function gets the venous arterial 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. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return last venous pressure reading + *************************************************************************/ +U16 getFPGAVenousPressure( void ) +{ + return fpgaSensorReadings.venousPressure; +} + +/*********************************************************************//** + * @brief + * The getFPGAAccelAxes function gets the accelerometer axis readings. + * Axis readings are in ADC counts. 0.004 g per LSB. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @param x Populate this param with X axis reading + * @param y Populate this param with Y axis reading + * @param z Populate this param with Z axis reading + * @return none + *************************************************************************/ +void getFPGAAccelAxes( S16 *x, S16 *y, S16 *z ) +{ + *x = (S16)fpgaSensorReadings.accelX; + *y = (S16)fpgaSensorReadings.accelY; + *z = (S16)fpgaSensorReadings.accelZ; +} + +/*********************************************************************//** + * @brief + * The getFPGAAccelMaxes function gets the maximum accelerometer axis readings. + * from last FPGA read (every 10ms). + * Axis readings are in ADC counts. 0.004 g per LSB. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @param x Populate this param with maximum X axis reading + * @param y Populate this param with maximum Y axis reading + * @param z Populate this param with maximum Z axis reading + * @return none + *************************************************************************/ +void getFPGAAccelMaxes( S16 *xmax, S16*ymax, S16*zmax ) +{ + *xmax = (S16)fpgaSensorReadings.accelXMax; + *ymax = (S16)fpgaSensorReadings.accelYMax; + *zmax = (S16)fpgaSensorReadings.accelZMax; +} + +/*********************************************************************//** + * @brief + * The getFPGAAccelStatus function gets the accelerometer reading count + * and error register values. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @param cnt Populate this param with latest sample counter value + * @param err Populate this param with latest error + * @return none + *************************************************************************/ +void getFPGAAccelStatus( U16 *cnt, U16 *err ) +{ + *cnt = fpgaSensorReadings.accelSampleCounter; + *err = fpgaSensorReadings.accelFaultRegister; +} + +/*********************************************************************//** + * @brief + * The getFPGAAirTrapLevels function gets the latest air trap level sensor + * readings. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return none + *************************************************************************/ +void getFPGAAirTrapLevels( BOOL *airAtLower, BOOL *airAtUpper ) +{ + U16 fpgaGPIO = fpgaSensorReadings.fpgaGPIO; + U16 lower = fpgaGPIO & FPGA_AIRTRAP_LEVEL_LOW_MASK; + U16 upper = fpgaGPIO & FPGA_AIRTRAP_LEVEL_HIGH_MASK; + + *airAtLower = ( 0 == lower ? FALSE : TRUE ); + *airAtUpper = ( 0 == upper ? FALSE : TRUE ); +} + +/*********************************************************************//** + * @brief + * 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 The status of the valves + *************************************************************************/ +U16 getFPGAValvesStatus( void ) +{ + return fpgaSensorReadings.valveStatus; +} + +/*********************************************************************//** + * @brief + * The setValveDialyzerInletPosition function sets the position of VDi + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerInletPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VDiSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveDialyzerInletPosition function reads the current position + * of VDi in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VDi + *************************************************************************/ +S16 getFPGAValveDialyzerInletPosition( void ) +{ + return fpgaSensorReadings.VDiPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerInletCurrentCounts function reads the current \n + * of VDi in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VDi + *************************************************************************/ +U16 getFPGAValveDialyzerInletCurrentCounts( void ) +{ + return fpgaSensorReadings.VDiCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerInletPWM function sets the PWM of VDI in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VDI in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerInletPWM( U16 count ) +{ + fpgaActuatorSetPoints.VDiPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerInletPWM function reads the current PWM target + * of VDI. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VDI + *************************************************************************/ +U16 getFPGAValveDialyzerInletPWM( void ) +{ + return fpgaSensorReadings.VDiPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerOutletPosition function sets the position of VDo + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerOutletPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VDoSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletPosition function reads the current position + * of VDo in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VDo + *************************************************************************/ +S16 getFPGAValveDialyzerOutletPosition( void ) +{ + return fpgaSensorReadings.VDoPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletCurrentCounts function reads the current + * of VDo in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VDo + *************************************************************************/ +U16 getFPGAValveDialyzerOutletCurrentCounts( void ) +{ + return fpgaSensorReadings.VDoCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveDialyzerOutletPWM function sets the PWM of VDO in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VDO in counts + * @return none + *************************************************************************/ +void setFPGAValveDialyzerOutletPWM( U16 count ) +{ + fpgaActuatorSetPoints.VDoPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveDialyzerOutletPWM function reads the current PWM target + * of VDO. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VDO + *************************************************************************/ +U16 getFPGAValveDialyzerOutletPWM( void ) +{ + return fpgaSensorReadings.VDoPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setValveBloodVenousPosition function sets the position of VBV + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodVenousPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VBVSetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveBloodVenousPosition function reads the current position + * of VBV in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VBV + *************************************************************************/ +S16 getFPGAValveBloodVenousPosition( void ) +{ + return fpgaSensorReadings.VBVPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodVenousCurrentCounts function reads the current + * of VBV in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VBV + *************************************************************************/ +U16 getFPGAValveBloodVenousCurrentCounts( void ) +{ + return fpgaSensorReadings.VBVCurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveBloodVenousPWM function sets the PWM of VBV in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VBV in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodVenousPWM( U16 count ) +{ + fpgaActuatorSetPoints.VBVPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodVenousPWM function returns the PWM of VBV in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: none + * @return returns the PWM of VBV in counts + *************************************************************************/ +U16 getFPGAValveBloodVenousPWM( void ) +{ + return fpgaSensorReadings.VBVPWMTarget; +} +#endif + +/*********************************************************************//** + * @brief + * The setValveBloodArterialPosition function sets the position of VBA + * in counts + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param setPoint : Next position of the valve in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodArterialPosition( S16 setPoint ) +{ + fpgaActuatorSetPoints.VBASetPoint = setPoint; +} + +/*********************************************************************//** + * @brief + * The getValveBloodArterialPosition function reads the current position + * of VBA in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current position of VBA + *************************************************************************/ +S16 getFPGAValveBloodArterialPosition( void ) +{ + return fpgaSensorReadings.VBAPosition; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodArterialCurrentCounts function reads the current + * of VBA in counts + * @details Inputs: none + * @details Outputs: fpgaSensorReadings + * @return The current of VBA + *************************************************************************/ +U16 getFPGAValveBloodArterialCurrentCounts( void ) +{ + return fpgaSensorReadings.VBACurrent; +} + +#ifdef DEBUG_ENABLED +/*********************************************************************//** + * @brief + * The setFPGAValveBloodArterialPWM function sets a PWM for VBA in counts. + * @details Inputs: fpgaActuatorSetPoints + * @details Outputs: fpgaActuatorSetPoints + * @param count which is the PWM of VBA in counts + * @return none + *************************************************************************/ +void setFPGAValveBloodArterialPWM( U16 count ) +{ + fpgaActuatorSetPoints.VBAPWMFixed = count; +} + +/*********************************************************************//** + * @brief + * The getFPGAValveBloodArterialPWM function returns the current PWM of + * VBA in counts. + * @details Inputs: fpgaSensorReadings + * @details Outputs: none + * @return current PWM of VBA in counts + *************************************************************************/ +U16 getFPGAValveBloodArterialPWM( void ) +{ + return fpgaSensorReadings.VBAPWMTarget; +} +#endif -#include // for memset(), memcpy() - -#include "sci.h" -#include "sys_dma.h" - -#include "FPGA.h" -#include "Comm.h" -#include "SystemCommMessages.h" -#include "Utilities.h" - -// ********** private definitions ********** - -typedef enum FPGA_States -{ - FPGA_STATE_START = 0, - FPGA_STATE_READ_HEADER, - FPGA_STATE_RCV_HEADER, - FPGA_STATE_WRITE_ALL_ACTUATORS, - FPGA_STATE_RCV_ALL_SENSORS, - FPGA_STATE_FAILED, - NUM_OF_FPGA_STATES -} FPGA_STATE_T; - -#define FPGA_PAGE_SIZE 256 -#define FPGA_EXPECTED_ID 0x59 - -#define FPGA_HEADER_START_ADDR 256 // update these after re-arranging w/ Randy -#define FPGA_BULK_READ_START_ADDR 262 -#define FPGA_BULK_WRITE_START_ADDR 2 - -#define FPGA_WRITE_CMD_BUFFER_LEN (FPGA_PAGE_SIZE+8) -#define FPGA_READ_CMD_BUFFER_LEN 8 -#define FPGA_WRITE_RSP_BUFFER_LEN 8 -#define FPGA_READ_RSP_BUFFER_LEN (FPGA_PAGE_SIZE+8) - -#define FPGA_WRITE_CMD_CODE 0x55 -#define FPGA_READ_CMD_CODE 0x5A -#define FPGA_WRITE_CMD_ACK 0xA5 -#define FPGA_READ_CMD_ACK 0xAA -#define FPGA_CMD_NAK 0xEE - -#define FPGA_CRC_LEN 2 -#define FPGA_WRITE_CMD_HDR_LEN 4 -#define FPGA_READ_CMD_HDR_LEN 4 -#define FPGA_WRITE_RSP_HDR_LEN 3 -#define FPGA_READ_RSP_HDR_LEN 3 - -#define SCI2_RECEIVE_DMA_REQUEST 28 -#define SCI2_TRANSMIT_DMA_REQUEST 29 - -#define MAX_COMM_ERROR_RETRIES 5 - -// FPGA Sensors Record -#pragma pack(push,1) -typedef struct -{ - U08 fpgaId; - U08 fpgaRev; - U16 fpgaControl; - U16 fpgaStatus; -} FPGA_HEADER_T; // read only on FPGA - -typedef struct // TODO - add all sensor readings to this structure per FPGA register map -{ - U08 bloodFlowMeterDataPktCount; - U08 bloodFlowMeterSlowPktCounts; - U08 bloodFlowMeterDeviceStatus; - U08 bloodFlowMeterResponse; - F32 bloodFlowLast; - U08 dialysateFlowMeterDataPktCount; - U08 dialysateFlowMeterSlowPckCounts; - U08 dialysateFlowMeterDeviceStatus; - U08 dialysateFlowMeterResponse; - F32 dialysateFlowLast; - U08 bloodFlowMeterErrorCount; - U08 dialysateFlowMeterErrorCount; - U16 bloodOcclusionData; - U08 bloodOcclusionReadCount; - U08 bloodOcclusionErrorCount; - U16 dialysateInOcclusionData; - U08 dialysateInOcclusionReadCount; - U08 dialysateInOcclusionErrorCount; - U16 dialysateOutOcclusionData; - U08 dialysateOutOcclusionReadCount; - U08 dialysateOutOcclusionErrorCount; - U16 arterialPressureData; - U08 arterialPressureReadCount; - U08 arterialPressureErrorCount; - U16 dialysateTempPrimaryData; - U16 dialysateTempBackupData; -} FPGA_SENSORS_T; - -typedef struct // TODO - add all actuator set points to this structure per FPGA register map -{ - U08 bloodValveSetState; -} FPGA_ACTUATORS_T; -#pragma pack(pop) - -// ********** private data ********** - -// FPGA state -static FPGA_STATE_T fpgaState = FPGA_STATE_START; - -static U32 fpgaCommRetryCount = 0; -static U32 fpgaReceiptCounter = 0; -static U32 fpgaTransmitCounter = 0; -static BOOL fpgaWriteCommandInProgress = FALSE; -static BOOL fpgaReadCommandInProgress = FALSE; -static BOOL fpgaBulkWriteAndReadInProgress = FALSE; -static BOOL fpgaWriteCommandResponseReceived = FALSE; -static BOOL fpgaReadCommandResponseReceived = FALSE; - -// FPGA comm buffers -static U08 fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_BUFFER_LEN ]; -static U08 fpgaReadCmdBuffer[ FPGA_READ_CMD_BUFFER_LEN ]; -static U08 fpgaWriteResponseBuffer[ FPGA_WRITE_RSP_BUFFER_LEN ]; -static U08 fpgaReadResponseBuffer[ FPGA_READ_RSP_BUFFER_LEN ]; - -// DMA control records -static g_dmaCTRL fpgaDMAWriteControlRecord; -static g_dmaCTRL fpgaDMAWriteRespControlRecord; -static g_dmaCTRL fpgaDMAReadControlRecord; -static g_dmaCTRL fpgaDMAReadRespControlRecord; - -// FPGA data -static FPGA_HEADER_T fpgaHeader; -static FPGA_SENSORS_T fpgaSensorReadings; -static FPGA_ACTUATORS_T fpgaActuatorSetPoints; - -// ********** private function prototypes ********** - -static FPGA_STATE_T handleFPGAReadHeaderState( void ); -static FPGA_STATE_T handleFPGAReceiveHeaderState( void ); -static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ); -static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ); - -static void resetFPGACommFlags( void ); -static void setupDMAForWriteCmd( U32 bytes2Transmit ); -static void startDMAWriteCmd( void ); -static void setupDMAForWriteResp( U32 bytes2Receive ); -static void startDMAReceiptOfWriteResp( void ); -static void setupDMAForReadCmd( U32 bytes2Transmit ); -static void startDMAReadCmd( void ); -static void setupDMAForReadResp( U32 bytes2Receive ); -static void startDMAReceiptOfReadResp( void ); - -static void consumeUnexpectedData( void ); - -/************************************************************************* - * @brief initFPGA - * The initFPGA function initializes the FPGA module. - * @details - * Inputs : none - * Outputs : FPGA module initialized. - * @param none - * @return none - *************************************************************************/ -void initFPGA( void ) -{ - // initialize fpga data structures - memset( &fpgaHeader, 0, sizeof(FPGA_HEADER_T) ); - memset( &fpgaSensorReadings, 0, sizeof(FPGA_SENSORS_T) ); - memset( &fpgaActuatorSetPoints, 0, sizeof(FPGA_ACTUATORS_T) ); - - // initialize fpga comm buffers - memset( &fpgaWriteCmdBuffer, 0, FPGA_WRITE_CMD_BUFFER_LEN ); - memset( &fpgaReadCmdBuffer, 0, FPGA_READ_CMD_BUFFER_LEN ); - memset( &fpgaWriteResponseBuffer, 0, FPGA_WRITE_RSP_BUFFER_LEN ); - memset( &fpgaReadResponseBuffer, 0, FPGA_READ_RSP_BUFFER_LEN ); - - // enable interrupt notifications for FPGA serial port - sciEnableNotification( scilinREG, SCI_OE_INT | SCI_FE_INT ); - - // assign DMA channels to h/w DMA requests - dmaReqAssign( DMA_CH0, SCI2_RECEIVE_DMA_REQUEST ); - dmaReqAssign( DMA_CH2, SCI2_TRANSMIT_DMA_REQUEST ); - // set DMA channel priorities - dmaSetPriority( DMA_CH0, HIGHPRIORITY ); - dmaSetPriority( DMA_CH2, LOWPRIORITY ); - // Enable DMA block transfer complete interrupts - dmaEnableInterrupt( DMA_CH0, BTC ); - dmaEnableInterrupt( DMA_CH2, BTC ); - - // initialize FPGA DMA Write Control Record - fpgaDMAWriteControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteCmdBuffer; // transfer source address - fpgaDMAWriteControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register - fpgaDMAWriteControlRecord.CHCTRL = 0; // no chaining - fpgaDMAWriteControlRecord.ELCNT = 1; // frame is 1 element - fpgaDMAWriteControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known - fpgaDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - fpgaDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; // - fpgaDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment - fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed - fpgaDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAWriteControlRecord.ELSOFFSET = 0; // not used - fpgaDMAWriteControlRecord.ELDOFFSET = 0; // not used - fpgaDMAWriteControlRecord.FRSOFFSET = 0; // not used - fpgaDMAWriteControlRecord.FRDOFFSET = 0; // not used - - // initialize FPGA DMA Write Response Control Record - fpgaDMAWriteRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - fpgaDMAWriteRespControlRecord.SADD = (U32)(&(scilinREG->RD));// source is SCI2 recv register - fpgaDMAWriteRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // transfer destination address - fpgaDMAWriteRespControlRecord.CHCTRL = 0; // no chaining - fpgaDMAWriteRespControlRecord.ELCNT = 1; // frame is 1 element - fpgaDMAWriteRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known - fpgaDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - fpgaDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; // - fpgaDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed - fpgaDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment - fpgaDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // not used - fpgaDMAWriteRespControlRecord.ELSOFFSET = 0; // not used - fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // not used - fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // not used - - // initialize FPGA DMA Read Control Record - fpgaDMAReadControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - fpgaDMAReadControlRecord.SADD = (U32)fpgaReadCmdBuffer; // transfer source address - fpgaDMAReadControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register - fpgaDMAReadControlRecord.CHCTRL = 0; // no chaining - fpgaDMAReadControlRecord.ELCNT = 1; // frame is 1 element - fpgaDMAReadControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known - fpgaDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - fpgaDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; // - fpgaDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAReadControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment - fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed - fpgaDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAReadControlRecord.ELSOFFSET = 0; // not used - fpgaDMAReadControlRecord.ELDOFFSET = 0; // not used - fpgaDMAReadControlRecord.FRSOFFSET = 0; // not used - fpgaDMAReadControlRecord.FRDOFFSET = 0; // not used - - // initialize FPGA DMA Read Response Control Record - fpgaDMAReadRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - fpgaDMAReadRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // source is SCI2 recv register - fpgaDMAReadRespControlRecord.DADD = (U32)fpgaReadResponseBuffer; // transfer destination address - fpgaDMAReadRespControlRecord.CHCTRL = 0; // no chaining - fpgaDMAReadRespControlRecord.ELCNT = 1; // frame is 1 element - fpgaDMAReadRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known - fpgaDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - fpgaDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; // - fpgaDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed - fpgaDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment - fpgaDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // not used - fpgaDMAReadRespControlRecord.ELSOFFSET = 0; // not used - fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // not used - fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // not used - - // there shouldn't be any data pending yet - consumeUnexpectedData(); -} - -/************************************************************************* - * @brief resetFPGACommFlags - * The resetFPGACommFlags function resets the various fpga comm flags and \n - * counters. - * @details - * Inputs : none - * Outputs : fpga comm flags & counters reset - * @param none - * @return none - *************************************************************************/ -static void resetFPGACommFlags( void ) -{ - fpgaWriteCommandResponseReceived = FALSE; - fpgaReadCommandResponseReceived = FALSE; - fpgaWriteCommandInProgress = FALSE; - fpgaReadCommandInProgress = FALSE; - fpgaBulkWriteAndReadInProgress = FALSE; - fpgaTransmitCounter = 0; - fpgaReceiptCounter = 0; -} - -/************************************************************************* - * @brief signalFPGAReceiptCompleted - * The signalFPGAReceiptCompleted function increments a counter to indicate \n - * that another DMA receipt from the FPGA has completed. - * @details - * Inputs : none - * Outputs : fpgaReceiptCounter - * @param none - * @return none - *************************************************************************/ -void signalFPGAReceiptCompleted( void ) -{ - fpgaReceiptCounter++; - // did FPGA Ack last command? - if ( TRUE == fpgaWriteCommandInProgress ) - { - fpgaWriteCommandInProgress = FALSE; - fpgaWriteCommandResponseReceived = TRUE; - } - else if ( TRUE == fpgaReadCommandInProgress ) - { - fpgaReadCommandInProgress = FALSE; - fpgaReadCommandResponseReceived = TRUE; - } - - // see if we want to follow up with a bulk read command - if ( TRUE == fpgaBulkWriteAndReadInProgress ) - { - fpgaBulkWriteAndReadInProgress = FALSE; - fpgaReadCommandInProgress = TRUE; - // initiate bulk read command - startDMAReceiptOfReadResp(); - startDMAReadCmd(); - } -} - -/************************************************************************* - * @brief signalFPGATransmitCompleted - * The signalFPGATransmitCompleted function increments a counter to indicate \n - * that another DMA transmit to the FPGA has completed. - * @details - * Inputs : none - * Outputs : fpgaReceiptCounter - * @param none - * @return none - *************************************************************************/ -void signalFPGATransmitCompleted( void ) -{ - fpgaTransmitCounter++; -} - -/************************************************************************* - * @brief execFPGAIn - * The execFPGA function manages incoming data exchanges with the FPGA. - * @details - * Inputs : fpgaState - * Outputs : fpgaState - * @param none - * @return none - *************************************************************************/ -void execFPGAIn( void ) -{ - // FPGA incoming state machine - switch ( fpgaState ) - { - case FPGA_STATE_START: - fpgaState = FPGA_STATE_READ_HEADER; - break; - - case FPGA_STATE_RCV_HEADER: - fpgaState = handleFPGAReceiveHeaderState(); - break; - - // TODO - sensor/ADC init/configuration states - - case FPGA_STATE_RCV_ALL_SENSORS: - fpgaState = handleFPGAReceiveAllSensorsState(); - break; - - case FPGA_STATE_FAILED: - // do nothing - we'll be stuck here - break; - - default: - if ( fpgaState >= NUM_OF_FPGA_STATES ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_IN_STATE, fpgaState ) - } - else - { - // ok, some states handled in the outgoing state machine - } - break; - } - - // if retries for commands exceeds limit, fault - if ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) - { - // TODO - FPGA comm fault - } - - // reset comm flags after processing incoming responses - resetFPGACommFlags(); -} - -/************************************************************************* - * @brief execFPGAOut - * The execFPGAOut function manages outgoing data exchanges with the FPGA. - * @details - * Inputs : fpgaState - * Outputs : fpgaState - * @param none - * @return none - *************************************************************************/ -void execFPGAOut( void ) -{ - // FPGA outgoing state machine - switch ( fpgaState ) - { - case FPGA_STATE_READ_HEADER: - fpgaState = handleFPGAReadHeaderState(); - break; - - // TODO - sensor/ADC init/configuration states - - case FPGA_STATE_WRITE_ALL_ACTUATORS: - fpgaState = handleFPGAWriteAllActuatorsState(); - break; - - case FPGA_STATE_FAILED: - // do nothing - we'll be stuck here - break; - - default: - if ( fpgaState >= NUM_OF_FPGA_STATES ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_INVALID_OUT_STATE, fpgaState ) - } - else - { - // ok, some states handled in the incoming state machine - } - break; - } -} - -/************************************************************************* - * @brief handleFPGAReadHeaderState - * The handleFPGAReadHeaderState function handles the FPGA state where \n - * the read header registers command is sent to the FPGA. - * @details - * Inputs : none - * Outputs : read command sent to FPGA - * @param none - * @return next FPGA state - *************************************************************************/ -static FPGA_STATE_T handleFPGAReadHeaderState( void ) -{ - FPGA_STATE_T result = FPGA_STATE_RCV_HEADER; - U16 crc; - - // construct read command to read 3 registers starting at address 0 - fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; - fpgaReadCmdBuffer[ 1 ] = 0x00; // start at FPGA address 0 - fpgaReadCmdBuffer[ 2 ] = 0x00; - fpgaReadCmdBuffer[ 3 ] = sizeof(FPGA_HEADER_T); - crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); - fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); - fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); - // prep DMA for sending the read cmd and receiving the response - fpgaReadCommandInProgress = TRUE; - setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T) + FPGA_CRC_LEN ); - setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); - startDMAReceiptOfReadResp(); - startDMAReadCmd(); - - return result; -} - -/************************************************************************* - * @brief handleFPGAReceiveHeaderState - * The handleFPGAReceiveHeaderState function handles the FPGA state \n - * where the header registers read response should be ready to take in. - * @details - * Inputs : none - * Outputs : header register values updated - * @param none - * @return next FPGA state - *************************************************************************/ -static FPGA_STATE_T handleFPGAReceiveHeaderState( void ) -{ - FPGA_STATE_T result = FPGA_STATE_READ_HEADER; - - // did we get an FPGA response? - if ( TRUE == fpgaReadCommandResponseReceived ) - { - // did FPGA Ack the read command? - if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) - { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T); - U32 crcPos = rspSize; - U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); - - // does the FPGA response CRC check out? - if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) - { - fpgaCommRetryCount = 0; - // capture the read values - memcpy( &fpgaHeader, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_HEADER_T ) ); - result = FPGA_STATE_WRITE_ALL_ACTUATORS; - } - else - { - fpgaCommRetryCount++; - } - } - else // header read was NAK'd - { - fpgaCommRetryCount++; - } - } - else // no response to read command - { - fpgaCommRetryCount++; - } - - // shouldn't be any data received at this time - consumeUnexpectedData(); - - return result; -} - -/************************************************************************* - * @brief handleFPGAWriteAllActuatorsState - * The handleFPGAWriteAllActuatorsState function handles the FPGA state \n - * where the bulk write command is sent to the FPGA. - * @details - * Inputs : actuator set points - * Outputs : actuator set points sent to FPGA - * @param none - * @return next FPGA state - *************************************************************************/ -static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ) -{ - FPGA_STATE_T result = FPGA_STATE_RCV_ALL_SENSORS; - U16 crc; - - // construct bulk write command to write actuator data registers starting at address 3 (TODO - change address later) - fpgaWriteCmdBuffer[ 0 ] = FPGA_WRITE_CMD_CODE; - fpgaWriteCmdBuffer[ 1 ] = 0x08; // start at FPGA address 8 - fpgaWriteCmdBuffer[ 2 ] = 0x00; - fpgaWriteCmdBuffer[ 3 ] = sizeof(FPGA_ACTUATORS_T); - memcpy( &( fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN ] ), &fpgaActuatorSetPoints, sizeof( FPGA_ACTUATORS_T ) ); - crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ); - fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) ] = GET_MSB_OF_WORD( crc ); - fpgaWriteCmdBuffer[ FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) + 1 ] = GET_LSB_OF_WORD( crc ); - // construct bulk read command to read sensor data registers starting at address 8 - fpgaReadCmdBuffer[ 0 ] = FPGA_READ_CMD_CODE; - fpgaReadCmdBuffer[ 1 ] = 0x08; // start at FPGA address 0x108 (264) - fpgaReadCmdBuffer[ 2 ] = 0x01; - fpgaReadCmdBuffer[ 3 ] = sizeof(FPGA_SENSORS_T); - crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); - fpgaReadCmdBuffer[ 4 ] = GET_MSB_OF_WORD( crc ); - fpgaReadCmdBuffer[ 5 ] = GET_LSB_OF_WORD( crc ); - // prep DMA for sending the bulk write cmd and receiving its response - setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + sizeof( FPGA_ACTUATORS_T ) + FPGA_CRC_LEN ); - setupDMAForWriteResp( FPGA_WRITE_RSP_HDR_LEN + FPGA_CRC_LEN ); - // prep DMA for sending the bulk read cmd and receiving its response - setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); - setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof( FPGA_SENSORS_T ) + FPGA_CRC_LEN ); - // set fpga comm flags for bulk write cmd and follow-up bulk read command - fpgaWriteCommandInProgress = TRUE; - fpgaBulkWriteAndReadInProgress = TRUE; - // initiate bulk write command and it's receipt - read will follow - startDMAReceiptOfWriteResp(); - startDMAWriteCmd(); - - return result; -} - -/************************************************************************* - * @brief handleFPGAReceiveAllSensorsState - * The handleFPGAReceiveAllSensorsState function handles the FPGA state \n - * where the bulk read response should be ready to parse. - * @details - * Inputs : none - * Outputs : sensor values updated - * @param none - * @return next FPGA state - *************************************************************************/ -static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ) -{ - FPGA_STATE_T result = FPGA_STATE_WRITE_ALL_ACTUATORS; - - // check bulk write command success - if ( ( FALSE == fpgaWriteCommandResponseReceived ) || ( fpgaWriteResponseBuffer[ 0 ] != FPGA_WRITE_CMD_ACK ) ) - { - fpgaCommRetryCount++; - } - - // if bulk read command is ACK'd, collect the readings - if ( TRUE == fpgaReadCommandResponseReceived ) - { - // did FPGA Ack the read command? - if ( fpgaReadResponseBuffer[ 0 ] == FPGA_READ_CMD_ACK ) - { - U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_T); - U32 crcPos = rspSize; - U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[ crcPos ], fpgaReadResponseBuffer[ crcPos + 1 ] ); - - // does the FPGA response CRC check out? - if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) - { - fpgaCommRetryCount = 0; - // capture the read values - memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[ FPGA_READ_RSP_HDR_LEN ], sizeof( FPGA_SENSORS_T ) ); - result = FPGA_STATE_WRITE_ALL_ACTUATORS; - } - else // bad CRC - { - fpgaCommRetryCount++; - } - } - else // read command was NAK'd - { - fpgaCommRetryCount++; - } - } - else // no response to read command - { - fpgaCommRetryCount++; - } - - // shouldn't be any data received at this time - consumeUnexpectedData(); - - return result; -} - -/************************************************************************* - * @brief execFPGATest - * The execFPGATest function executes the FPGA self-test. \n - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param none - * @return passed, or failed - *************************************************************************/ -SELF_TEST_STATUS_T execFPGATest( void ) -{ - SELF_TEST_STATUS_T result; - - // check FPGA reported correct ID -#ifndef RM46_EVAL_BOARD_TARGET - if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) -#else - if ( 1 ) -#endif - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_FPGA_POST_TEST_FAILED, (U32)fpgaHeader.fpgaId ) - } - - return result; -} - -/************************************************************************* - * @brief setupDMAForWriteCmd - * The setupDMAForWriteCmd function sets the byte count for the next DMA \n - * write command to the FPGA. - * @details - * Inputs : none - * Outputs : # of bytes for next FPGA write command is set - * @param bytes2Transmit : # of bytes to be transmitted via DMA to the FPGA. - * @return none - *************************************************************************/ -static void setupDMAForWriteCmd( U32 bytes2Transmit ) -{ - // verify # of bytes does not exceed buffer length - if ( bytes2Transmit <= FPGA_WRITE_CMD_BUFFER_LEN ) - { - fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, bytes2Transmit ) - } -} - -/************************************************************************* - * @brief startDMAWriteCmd - * The startDMAWriteCmd function initiates the DMA transmit for the next \n - * DMA write command to the FPGA. - * @details - * Inputs : none - * Outputs : DMA write command to FPGA is initiated - * @param none - * @return none - *************************************************************************/ -static void startDMAWriteCmd( void ) -{ - dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord ); - dmaSetChEnable( DMA_CH2, DMA_HW ); - setSCI2DMATransmitInterrupt(); -} - -/************************************************************************* - * @brief setupDMAForWriteResp - * The setupDMAForWriteResp function sets the expected byte count for the \n - * next DMA write command response from the FPGA. - * @details - * Inputs : none - * Outputs : # of expected bytes for next FPGA write command response is set - * @param bytes2Receive : # of bytes expected to be transmitted via DMA from the FPGA. - * @return none - *************************************************************************/ -static void setupDMAForWriteResp( U32 bytes2Receive ) -{ - // verify # of bytes does not exceed buffer length - if ( bytes2Receive <= FPGA_WRITE_RSP_BUFFER_LEN ) - { - fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, bytes2Receive ) - } -} - -/************************************************************************* - * @brief startDMAReceiptOfWriteResp - * The startDMAReceiptOfWriteResp function initiates readiness of the DMA \n - * receiver for the next DMA write command response from the FPGA. - * @details - * Inputs : none - * Outputs : DMA write command response is ready to be received from the FPGA - * @param none - * @return none - *************************************************************************/ -static void startDMAReceiptOfWriteResp( void ) -{ - dmaSetCtrlPacket( DMA_CH0, fpgaDMAWriteRespControlRecord ); - dmaSetChEnable( DMA_CH0, DMA_HW ); - setSCI2DMAReceiveInterrupt(); -} - -/************************************************************************* - * @brief setupDMAForReadCmd - * The setupDMAForReadCmd function sets the byte count for the next DMA \n - * read command to the FPGA. - * @details - * Inputs : none - * Outputs : # of bytes for next FPGA read command is set - * @param bytes2Transmit : # of bytes to be transmitted via DMA to the FPGA. - * @return none - *************************************************************************/ -static void setupDMAForReadCmd( U32 bytes2Transmit ) -{ - // verify # of bytes does not exceed buffer length - if ( bytes2Transmit <= FPGA_READ_CMD_BUFFER_LEN ) - { - fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, bytes2Transmit ) - } -} - -/************************************************************************* - * @brief startDMAReadCmd - * The startDMAReadCmd function initiates the DMA transmit for the next \n - * DMA read command to the FPGA. - * @details - * Inputs : none - * Outputs : DMA read command to FPGA is initiated - * @param none - * @return none - *************************************************************************/ -static void startDMAReadCmd( void ) -{ - dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord ); - dmaSetChEnable( DMA_CH2, DMA_HW ); - setSCI2DMATransmitInterrupt(); -} - -/************************************************************************* - * @brief setupDMAForReadResp - * The setupDMAForReadResp function sets the expected byte count for the \n - * next DMA read command response from the FPGA. - * @details - * Inputs : none - * Outputs : # of expected bytes for next FPGA read command response is set - * @param bytes2Receive : # of expected bytes to be transmitted via DMA from the FPGA. - * @return none - *************************************************************************/ -static void setupDMAForReadResp( U32 bytes2Receive ) -{ - // verify # of bytes does not exceed buffer length - if ( bytes2Receive <= FPGA_READ_RSP_BUFFER_LEN ) - { - fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, bytes2Receive ) - } -} - -/************************************************************************* - * @brief startDMAReceiptOfReadResp - * The startDMAReceiptOfReadResp function initiates readiness of the DMA \n - * receiver for the next DMA read command response from the FPGA. - * @details - * Inputs : none - * Outputs : DMA read command response is ready to be received from the FPGA - * @param none - * @return none - *************************************************************************/ -static void startDMAReceiptOfReadResp( void ) -{ - dmaSetCtrlPacket( DMA_CH0, fpgaDMAReadRespControlRecord ); - dmaSetChEnable( DMA_CH0, DMA_HW ); - setSCI2DMAReceiveInterrupt(); -} - -/************************************************************************* - * @brief getFPGAId - * The getFPGAId function gets the version read from the Id register \n - * of the FPGA. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param none - * @return Id - *************************************************************************/ -U08 getFPGAId( void ) -{ - return fpgaHeader.fpgaId; -} - -/************************************************************************* - * @brief getFPGARev - * The getFPGARev function gets the revision read from the Rev register \n - * of the FPGA. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param none - * @return Revision - *************************************************************************/ -U08 getFPGARev( void ) -{ - return fpgaHeader.fpgaRev; -} - -/************************************************************************* - * @brief getFPGAStatus - * The getFPGAStatus function gets the version read from the diagnostic register \n - * of the FPGA. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param none - * @return fpgaHeader.fpgaStatus - *************************************************************************/ -U16 getFPGAStatus( void ) -{ - return fpgaHeader.fpgaStatus; -} - -/************************************************************************* - * @brief getFPGADiag - * The getFPGADiag function sets the diagnostic register of the FPGA. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param ctrl : value to write to diagnostic register - * @return none - *************************************************************************/ -void setFPGAControl( U16 ctrl ) -{ - fpgaHeader.fpgaControl = ctrl; -} - -/************************************************************************* - * @brief getFPGABloodFlow - * The getFPGABloodFlow function gets the latest blood flow reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none - * @param none - * @return last blood flow reading - *************************************************************************/ -F32 getFPGABloodFlow( void ) -{ - return fpgaSensorReadings.bloodFlowLast; -} - -/************************************************************************* - * @brief getFPGADialysateFlow - * The getFPGADialysateFlow function gets the latest dialysate flow reading. - * @details - * Inputs : fpgaSensorReadings - * Outputs : none - * @param none - * @return last dialysate flow reading - *************************************************************************/ -F32 getFPGADialysateFlow( void ) -{ - return fpgaSensorReadings.dialysateFlowLast; -} - -/************************************************************************* - * @brief consumeUnexpectedData - * The consumeUnexpectedData function checks to see if a byte is sitting in \n - * the SCI2 received data register. - * @details - * Inputs : fpgaHeader - * Outputs : none - * @param none - * @return fpgaDiag - *************************************************************************/ -static void consumeUnexpectedData( void ) -{ - // clear any errors - sciRxError( scilinREG ); - // if a byte is pending read, read it - if ( sciIsRxReady( scilinREG ) != 0 ) - { - sciReceiveByte( scilinREG ); - } -} - +/**@}*/