Big changes
This commit is contained in:
@@ -0,0 +1,593 @@
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using FpgaMeasurementInstrumentsLib;
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Raytheon.Instruments
|
||||
{
|
||||
/// <summary>
|
||||
/// This class serves as an interface to FPGAs that implement a UDP interface.
|
||||
/// It allows for the ability to read and write to registers.
|
||||
/// </summary>
|
||||
public class CommFpgaEthernet : IFpgaComm, IDisposable
|
||||
{
|
||||
#region PrivateClassMembers
|
||||
private UdpClient _udpClient;
|
||||
private readonly int _localPort;
|
||||
private readonly int _remotePort;
|
||||
private readonly string _remoteAddress;
|
||||
private static object _syncObj = new Object();
|
||||
private SelfTestResult _selfTestResult;
|
||||
private State _state;
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// NLog logger
|
||||
/// </summary>
|
||||
private readonly ILogger _logger;
|
||||
/// <summary>
|
||||
/// Raytheon configuration
|
||||
/// </summary>
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PrivateFuctions
|
||||
|
||||
/// <summary>
|
||||
/// The Finalizer
|
||||
/// </summary>
|
||||
~CommFpgaEthernet()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object
|
||||
/// </summary>
|
||||
/// <param name="disposing"></param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read data off of the socket
|
||||
/// </summary>
|
||||
/// <param name="dataRead">The data that was read</param>
|
||||
/// <returns>The number of bytes read</returns>
|
||||
private int ReadData(ref byte[] dataRead)
|
||||
{
|
||||
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, _localPort);
|
||||
|
||||
dataRead = _udpClient.Receive(ref remoteIPEndPoint);
|
||||
|
||||
int numBytesRead = dataRead.Length;
|
||||
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send a command message and get a response message
|
||||
/// </summary>
|
||||
/// <param name="commandMsg">The message to send</param>
|
||||
/// <param name="rspMsg">The response</param>
|
||||
private void SendCommandGetResponse(FPGACmdMessage commandMsg, ref FPGARspMessage rspMsg)
|
||||
{
|
||||
uint rxBufferSize = rspMsg.GetEntireMsgLength();
|
||||
uint rxNumBytesExpected = rxBufferSize;
|
||||
|
||||
uint dataToSendNumBytes = commandMsg.GetEntireMsgLength();
|
||||
|
||||
// send the command
|
||||
byte[] dataToSend = new byte[dataToSendNumBytes];
|
||||
|
||||
// get a pointer to the data
|
||||
GCHandle sendPinnedArray = GCHandle.Alloc(dataToSend, GCHandleType.Pinned);
|
||||
IntPtr pByte = sendPinnedArray.AddrOfPinnedObject();
|
||||
commandMsg.Format(pByte);
|
||||
sendPinnedArray.Free();
|
||||
|
||||
// send the data
|
||||
int numBytesSent = SendData(dataToSend);
|
||||
|
||||
if (dataToSendNumBytes != numBytesSent)
|
||||
{
|
||||
throw new Exception("wanted to send: " + dataToSendNumBytes.ToString() + " bytes, SendData() reported that it sent: " + numBytesSent.ToString());
|
||||
}
|
||||
|
||||
// read the response
|
||||
byte[] rspBuffer = new byte[rxBufferSize];
|
||||
int numBytesRead = ReadData(ref rspBuffer);
|
||||
|
||||
if (numBytesRead != rxNumBytesExpected)
|
||||
{
|
||||
throw new Exception("received " + numBytesRead.ToString() + " bytes, expected " + rxNumBytesExpected.ToString());
|
||||
}
|
||||
|
||||
// populate the rspMsg object
|
||||
GCHandle rxPinnedArray = GCHandle.Alloc(rspBuffer, GCHandleType.Pinned);
|
||||
IntPtr pBytePtr = rxPinnedArray.AddrOfPinnedObject();
|
||||
rspMsg.Parse(pBytePtr);
|
||||
rxPinnedArray.Free();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send data out of the socket
|
||||
/// </summary>
|
||||
/// <param name="dataToSend">The data to send</param>
|
||||
/// <returns>The number of bytes sent</returns>
|
||||
private int SendData(byte[] dataToSend)
|
||||
{
|
||||
IPAddress addy = IPAddress.Parse(_remoteAddress);
|
||||
|
||||
IPEndPoint ipEndPoint = new IPEndPoint(addy, _remotePort);
|
||||
|
||||
int numBytesSent = _udpClient.Send(dataToSend, dataToSend.Length, ipEndPoint);
|
||||
|
||||
return numBytesSent;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PublicFuctions
|
||||
|
||||
/// <summary>
|
||||
/// CommFpgaEthernet factory constructor
|
||||
/// </summary>
|
||||
/// <param name="deviceName"></param>
|
||||
/// <param name="configurationManager"></param>
|
||||
public CommFpgaEthernet(string deviceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceName;
|
||||
|
||||
_logger = logger;
|
||||
|
||||
_configurationManager = configurationManager;
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_localPort = _configuration.GetConfigurationValue("CommFpgaEthernet", "LocalPort", 0);
|
||||
_remotePort = _configuration.GetConfigurationValue("CommFpgaEthernet", "RemotePort", 0);
|
||||
_remoteAddress = _configuration.GetConfigurationValue("CommFpgaEthernet", "RemoteAddress", "127.0.0.1");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fpgaName"></param>
|
||||
/// <param name="localPort">The port on the local computer</param>
|
||||
/// <param name="remotePort">The port that the FPGA is using</param>
|
||||
/// <param name="remoteAddress">The address that the FPGA is using</param>
|
||||
public CommFpgaEthernet(string name, int localPort, int remotePort, string remoteAddress)
|
||||
{
|
||||
_name = name;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
_state = State.Uninitialized;
|
||||
|
||||
_localPort = localPort;
|
||||
_remotePort = remotePort;
|
||||
_remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ClearErrors()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string DetailedStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
return "This is a FPGA Ethernet called " + _name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool DisplayEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
//ErrorLogger.Instance().Write(err.Message + "\r\n" + err.StackTrace);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//Do not rethrow. Exception from error logger that has already been garbage collected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool FrontPanelEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public InstrumentMetadata Info
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
Initialize(string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fpga"></param>
|
||||
public void Initialize(string fpga)
|
||||
{
|
||||
//5 second timeout
|
||||
const int TIMEOUT = 5000;
|
||||
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Uninitialized)
|
||||
{
|
||||
_udpClient = new UdpClient(_localPort);
|
||||
|
||||
_udpClient.Client.ReceiveBufferSize = int.MaxValue;
|
||||
|
||||
_udpClient.Client.SendBufferSize = int.MaxValue;
|
||||
|
||||
_udpClient.Client.SendTimeout = TIMEOUT;
|
||||
|
||||
_udpClient.Client.ReceiveTimeout = TIMEOUT;
|
||||
|
||||
_state = State.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("expected the state to be Uninitialized, state was: " + _state.ToString() + " on card " + _name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SelfTestResult PerformSelfTest()
|
||||
{
|
||||
_selfTestResult = SelfTestResult.Unknown;
|
||||
return _selfTestResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a single register
|
||||
/// </summary>
|
||||
/// <param name="page">The page of the register to read from</param>
|
||||
/// <param name="address">The register address to read from</param>
|
||||
/// <returns>The data at the address</returns>
|
||||
public uint Read(string fpgaName, uint address)
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
FPGACmdMessage cmd = new FPGAReadRegisterCmdMessage((FPGACmdMessage.Page)0, address);
|
||||
|
||||
// this get populated in SendCommandGetResponse()
|
||||
FPGARspMessage rsp = new FPGAReadRegisterRspMessage(0, 0);
|
||||
|
||||
SendCommandGetResponse(cmd, ref rsp);
|
||||
|
||||
return rsp.GetData();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fpgaName"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="numberOfWordsToRead"></param>
|
||||
/// <param name="dataRead"></param>
|
||||
/// <param name="shallWeIncrementAddress"></param>
|
||||
public void ReadBlock(string fpgaName, uint address, uint numberOfWordsToRead, bool shallWeIncrementAddress, ref uint[] dataRead)
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (shallWeIncrementAddress)
|
||||
{
|
||||
FPGACmdMessage cmd = new FPGAReadRegisterCmdBlockIncrMessage((FPGACmdMessage.Page)0, address, numberOfWordsToRead, false);
|
||||
|
||||
// this get populated in SendCommandGetResponse()
|
||||
FPGARspMessage rsp = new FPGAReadRegisterBlockIncrRspMessage(0, ref dataRead);
|
||||
|
||||
SendCommandGetResponse(cmd, ref rsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Not Implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SelfTestResult SelfTestResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selfTestResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (_state == State.Ready)
|
||||
{
|
||||
_udpClient.Close();
|
||||
|
||||
_state = State.Uninitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public State Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write to a single register
|
||||
/// </summary>
|
||||
/// <param name="page">The page of the register to read from</param>
|
||||
/// <param name="address">The address to write to</param>
|
||||
/// <param name="value">The data to write</param>
|
||||
public void Write(string fpgaName, uint address, uint value)
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
FPGACmdMessage cmd = new FPGAWriteRegisterCmdMessage((FPGACmdMessage.Page)0, address, value);
|
||||
|
||||
// this get populated in SendCommandGetResponse()
|
||||
FPGARspMessage rsp = new FPGAWriteRegisterRspMessage(0, 0);
|
||||
|
||||
SendCommandGetResponse(cmd, ref rsp);
|
||||
|
||||
if (rsp.GetAddress() != address)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + ", received address: " + rsp.GetAddress().ToString("X8"));
|
||||
}
|
||||
else if (rsp.GetData() != 0xace0beef)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + " returned value: " + rsp.GetData().ToString("X8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="fpgaName"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="numberOfBytes"></param>
|
||||
/// <param name="data"></param>
|
||||
public void WriteBlock(string fpgaName, uint address, uint numberOfWordsToWrite, uint[] data, bool shallWeIncrementAddress)
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
FPGACmdMessage cmd = null;
|
||||
|
||||
if (shallWeIncrementAddress)
|
||||
{
|
||||
cmd = new FPGAWriteRegisterCmdBlockIncrMessage((FPGACmdMessage.Page)0, address, data, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = new FPGAWriteRegisterCmdBlockMessage((FPGACmdMessage.Page)0, address, data, false);
|
||||
}
|
||||
|
||||
// this get populated in SendCommandGetResponse()
|
||||
FPGARspMessage rsp = new FPGAWriteRegisterRspMessage(0, 0);
|
||||
|
||||
SendCommandGetResponse(cmd, ref rsp);
|
||||
|
||||
if (rsp.GetAddress() != address)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + ", received address: " + rsp.GetAddress().ToString("X8"));
|
||||
}
|
||||
else if (rsp.GetData() != 0xace0beef)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + " returned value: " + rsp.GetData().ToString("X8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="incrementAddress"></param>
|
||||
/// <param name="byteSwap"></param>
|
||||
public void WriteRegister(uint page, uint address, uint[] data, bool incrementAddress = true, bool byteSwap = true)
|
||||
{
|
||||
// lock up the FPGA resource
|
||||
lock (_syncObj)
|
||||
{
|
||||
if (page > (uint)FPGACmdMessage.Page.PAGE3)
|
||||
{
|
||||
throw new Exception("input parameter 'page' is out of range: " + page.ToString());
|
||||
}
|
||||
|
||||
FPGACmdMessage cmd;
|
||||
|
||||
if (incrementAddress)
|
||||
{
|
||||
cmd = new FPGAWriteRegisterCmdBlockIncrMessage((FPGACmdMessage.Page)page, address, data, byteSwap);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = new FPGAWriteRegisterCmdBlockMessage((FPGACmdMessage.Page)page, address, data, byteSwap);
|
||||
}
|
||||
|
||||
|
||||
// this get populated in SendCommandGetResponse()
|
||||
FPGARspMessage rsp = new FPGAWriteRegisterRspMessage(0, 0);
|
||||
|
||||
SendCommandGetResponse(cmd, ref rsp);
|
||||
|
||||
if (rsp.GetAddress() != address)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + ", received address: " + rsp.GetAddress().ToString("X8"));
|
||||
}
|
||||
else if (rsp.GetData() != 0xace0beef)
|
||||
{
|
||||
throw new Exception("Command write on address: " + address.ToString("X8") + " returned value: " + rsp.GetData().ToString("X8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads firmware
|
||||
/// </summary>
|
||||
/// <param name="fpgaName"></param>
|
||||
public void LoadFirmware(string fpgaName)
|
||||
{
|
||||
Initialize(fpgaName);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user