385 lines
12 KiB
C#
385 lines
12 KiB
C#
// 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 NLog;
|
|
using Raytheon.Common;
|
|
using Raytheon.Instruments;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace MeasurementManagerLib
|
|
{
|
|
/// <summary>
|
|
/// This class manages IFpgaComm instruments and provides an abstraction
|
|
/// </summary>
|
|
public class FpgaMeasurementManager : IDisposable
|
|
{
|
|
#region PrivateClassMembers
|
|
// fpga name to object
|
|
private readonly Dictionary<string, IFpgaComm> _fpgaDeviceMap;
|
|
// fpga to MemoryMap
|
|
private readonly Dictionary<string, MemoryMap> _fpgaMemMaps;
|
|
|
|
private static NLog.ILogger _logger;
|
|
#endregion
|
|
|
|
#region PrivateFuctions
|
|
|
|
/// <summary>
|
|
/// Finalizer.
|
|
/// </summary>
|
|
~FpgaMeasurementManager()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposing
|
|
/// </summary>
|
|
/// <param name="disposing"></param>
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
foreach (KeyValuePair<string, IFpgaComm> entry in _fpgaDeviceMap)
|
|
{
|
|
try
|
|
{
|
|
entry.Value.Shutdown();
|
|
}
|
|
catch (Exception err)
|
|
{
|
|
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initialize the communication to the fpga
|
|
/// </summary>
|
|
/// <param name="fpga">the name of the fpga as defined in the config file</param>
|
|
private void Initialize(string fpga)
|
|
{
|
|
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("could not find device: " + fpga);
|
|
}
|
|
|
|
_fpgaDeviceMap[fpga].Initialize(fpga);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PublicFuctions
|
|
|
|
/// <summary>
|
|
/// constructor with instrument manager
|
|
/// </summary>
|
|
/// <param name="instrumentManager"></param>
|
|
/// <param name="instrumentNames"></param>
|
|
/// <param name="instrumentDefFile"></param>
|
|
public FpgaMeasurementManager(IInstrumentManager instrumentManager, List<string> instrumentNames, string instrumentDefFile)
|
|
{
|
|
_logger = LogManager.GetCurrentClassLogger();
|
|
|
|
_fpgaDeviceMap = new Dictionary<string, IFpgaComm>();
|
|
|
|
foreach (string name in instrumentNames)
|
|
{
|
|
_fpgaDeviceMap[name] = instrumentManager.GetInstrument<IFpgaComm>(name);
|
|
_fpgaDeviceMap[name]?.Initialize(name);
|
|
}
|
|
|
|
// setup the memory maps
|
|
_fpgaMemMaps = new Dictionary<string, MemoryMap>(StringComparer.InvariantCultureIgnoreCase);
|
|
|
|
ConfigurationFile ini = new ConfigurationFile(instrumentDefFile);
|
|
|
|
foreach (KeyValuePair<string, IFpgaComm> entry in _fpgaDeviceMap)
|
|
{
|
|
string memMapFile = ini.ReadValue<string>(entry.Key, "MEM_MAP");
|
|
|
|
if (memMapFile.ToUpper().Trim() != "NONE")
|
|
{
|
|
_fpgaMemMaps.Add(entry.Key.ToUpper(), new MemoryMap(memMapFile));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dispose of resources
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
try
|
|
{
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
catch (Exception err)
|
|
{
|
|
try
|
|
{
|
|
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//Do not rethrow. Exception from error logger that has already been garbage collected
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the comm device
|
|
/// </summary>
|
|
/// <param name="fpga"></param>
|
|
/// <returns></returns>
|
|
public IFpgaComm GetFpgaCommDevice(string fpga)
|
|
{
|
|
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("could not find device: " + fpga);
|
|
}
|
|
|
|
return _fpgaDeviceMap[fpga.ToUpper()];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all of the fpga names
|
|
/// </summary>
|
|
/// <returns>A list of fpga device names</returns>
|
|
public List<string> GetFpgaNames()
|
|
{
|
|
List<string> fpgaList = new List<string>();
|
|
|
|
foreach (KeyValuePair<string, IFpgaComm> entry in _fpgaDeviceMap)
|
|
{
|
|
fpgaList.Add(entry.Key);
|
|
}
|
|
|
|
return fpgaList;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read a register that is defined by a memory map logical name
|
|
/// If a subitem is commanded, this returns just the value of the subitems
|
|
/// </summary>
|
|
/// <param name="fpga">the name of the fpga as defined in the config file</param>
|
|
/// <param name="memMapItemName">The name of the mem map item in the memory map file</param>
|
|
/// <returns></returns>
|
|
public uint RegisterRead(string fpga, string memMapItemName)
|
|
{
|
|
if (_fpgaMemMaps.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("no memory map exists for fpga: " + fpga);
|
|
}
|
|
|
|
MemoryMap.MemoryMapFields fields = _fpgaMemMaps[fpga.ToUpper()].GetRegisterInfoByString(memMapItemName);
|
|
|
|
uint registerValue = _fpgaDeviceMap[fpga.ToUpper()].Read(fpga, fields._address);
|
|
|
|
uint itemValue = Util.ParseRegisterItem(registerValue, fields._startBit, fields._numBits);
|
|
|
|
return itemValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read a register given an address
|
|
/// </summary>
|
|
/// <param name="fpga">the name of the fpga as defined in the config file</param>
|
|
/// <param name="address">the address to read</param>
|
|
/// <returns></returns>
|
|
public uint RegisterRead(string fpga, uint address)
|
|
{
|
|
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("could not find device: " + fpga);
|
|
}
|
|
|
|
return _fpgaDeviceMap[fpga.ToUpper()].Read(fpga, address);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read a register given an address with optional offset
|
|
/// </summary>
|
|
/// <param name="fpga"></param>
|
|
/// <param name="memMapItemName"></param>
|
|
/// <param name="offset"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="Exception"></exception>
|
|
public uint RegisterRead(string fpga, string memMapItemName, uint offset = 0)
|
|
{
|
|
if (_fpgaMemMaps.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("no memory map exists for fpga: " + fpga);
|
|
}
|
|
|
|
MemoryMap.MemoryMapFields fields = _fpgaMemMaps[fpga.ToUpper()].GetRegisterInfoByString(memMapItemName);
|
|
|
|
uint registerValue = _fpgaDeviceMap[fpga.ToUpper()].Read(fpga, fields._address + offset);
|
|
|
|
uint itemValue = Util.ParseRegisterItem(registerValue, fields._startBit, fields._numBits);
|
|
|
|
return itemValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// reads block from fpga
|
|
/// </summary>
|
|
/// <param name="fpga"></param>
|
|
/// <param name="address"></param>
|
|
/// <param name="numberOfWordsToRead"></param>
|
|
/// <param name="shallWeIncrementAddress"></param>
|
|
/// <param name="dataRead"></param>
|
|
/// <exception cref="Exception"></exception>
|
|
public void ReadBlock(string fpga, uint address, uint numberOfWordsToRead, bool shallWeIncrementAddress, ref uint[] dataRead)
|
|
{
|
|
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("FpgaMeasurementManager::ReadBlock - could not find device: " + fpga);
|
|
}
|
|
|
|
if (address == 0)
|
|
{
|
|
_fpgaDeviceMap[fpga.ToUpper()].ReadBlock(fpga, address, numberOfWordsToRead, shallWeIncrementAddress, ref dataRead);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Not yet implemented");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write a register given an address
|
|
/// </summary>
|
|
/// <param name="fpga">the name of the fpga as defined in the config file</param>
|
|
/// <param name="address">The address to write to</param>
|
|
/// <param name="dataToWrite">The data to write to the register</param>
|
|
public void RegisterWrite(string fpga, uint address, uint dataToWrite)
|
|
{
|
|
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("could not find device: " + fpga);
|
|
}
|
|
|
|
_fpgaDeviceMap[fpga.ToUpper().ToUpper()].Write(fpga, address, dataToWrite);
|
|
}
|
|
|
|
/// <summary>
|
|
/// write a register that is defined by a memory map logical name
|
|
/// If a sub item is commanded, the current values of the other items remain unchanged
|
|
/// </summary>
|
|
/// <param name="fpga">the name of the fpga as defined in the config file</param>
|
|
/// <param name="memMapItemName">The name of the mem map item in the memory map file</param>
|
|
/// <param name="dataToWrite">The data to write to the register</param>
|
|
/// <param name="offset">The offset off of memMapItemName</param>
|
|
public void RegisterWrite(string fpga, string memMapItemName, uint dataToWrite, uint offset = 0)
|
|
{
|
|
if (_fpgaMemMaps.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("no memory map exists for fpga: " + fpga);
|
|
}
|
|
|
|
MemoryMap.MemoryMapFields fields = _fpgaMemMaps[fpga.ToUpper()].GetRegisterInfoByString(memMapItemName);
|
|
|
|
uint address = fields._address + offset;
|
|
|
|
// if commanded to write to a sub register, only write out those bits
|
|
if (fields._numBits < 32)
|
|
{
|
|
// read existing value
|
|
uint originalValue = RegisterRead(fpga, address);
|
|
|
|
//Apply inverse mask to current register contents to zero out just the bits we want to write
|
|
uint maskValue = Util.ApplyBitMask(originalValue, fields._startBit, fields._numBits, true);
|
|
|
|
// Shift the desired data to set to match the zeroed register
|
|
dataToWrite = dataToWrite << fields._startBit;
|
|
|
|
dataToWrite = maskValue | dataToWrite;
|
|
}
|
|
|
|
_fpgaDeviceMap[fpga.ToUpper()].Write(fpga, address, dataToWrite);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="fpga"></param>
|
|
/// <param name="memMapItemName"></param>
|
|
/// <param name="dataToWrite"></param>
|
|
/// <param name="offset"></param>
|
|
public void RegisterWriteBlock(string fpga, string memMapItemName, uint numWordsToWrite, uint[] dataToWrite, bool shallWeIncrementAddress, uint offset = 0)
|
|
{
|
|
if (_fpgaMemMaps.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("no memory map exists for fpga: " + fpga);
|
|
}
|
|
|
|
MemoryMap.MemoryMapFields fields = _fpgaMemMaps[fpga.ToUpper()].GetRegisterInfoByString(memMapItemName);
|
|
|
|
uint address = fields._address + offset;
|
|
|
|
// if commanded to write to a sub register, only write out those bits
|
|
if (fields._numBits < 32)
|
|
{
|
|
throw new Exception("can only write a block of data to a 32 bit register. fpga: " + fpga);
|
|
}
|
|
|
|
_fpgaDeviceMap[fpga.ToUpper()].WriteBlock(fpga, address, numWordsToWrite, dataToWrite, shallWeIncrementAddress);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the default value (as specified in the memory map) to the register
|
|
/// If a sub item is commanded, the current values of the other items remain unchanged
|
|
/// </summary>
|
|
/// <param name="fpga">The name of the FPGA</param>
|
|
/// <param name="memMapItemName">The memory map item which we will restore the default.</param>
|
|
public void RegisterWriteDefault(string fpga, string memMapItemName)
|
|
{
|
|
if (_fpgaMemMaps.ContainsKey(fpga.ToUpper()) == false)
|
|
{
|
|
throw new Exception("no memory map exists for fpga: " + fpga);
|
|
}
|
|
|
|
MemoryMap.MemoryMapFields fields = _fpgaMemMaps[fpga.ToUpper()].GetRegisterInfoByString(memMapItemName);
|
|
|
|
uint dataToWrite = fields._regDefault;
|
|
|
|
// if commanded to write to a sub register, only write out those bits
|
|
if (fields._numBits < 32)
|
|
{
|
|
// read existing value
|
|
uint originalValue = RegisterRead(fpga, fields._address);
|
|
|
|
//Apply inverse mask to current register contents to zero out just the bits we want to write
|
|
uint maskValue = Util.ApplyBitMask(originalValue, fields._startBit, fields._numBits, true);
|
|
|
|
// Shift the desired data to set to match the zeroed register
|
|
dataToWrite = dataToWrite << fields._startBit;
|
|
|
|
dataToWrite = maskValue | dataToWrite;
|
|
}
|
|
|
|
_fpgaDeviceMap[fpga.ToUpper()].Write(fpga, fields._address, dataToWrite);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|