// 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
{
///
/// This class manages IFpgaComm instruments and provides an abstraction
///
public class FpgaMeasurementManager : IDisposable
{
#region PrivateClassMembers
// fpga name to object
private readonly Dictionary _fpgaDeviceMap;
// fpga to MemoryMap
private readonly Dictionary _fpgaMemMaps;
private static NLog.ILogger _logger;
#endregion
#region PrivateFuctions
///
/// Finalizer.
///
~FpgaMeasurementManager()
{
Dispose(false);
}
///
/// Disposing
///
///
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
foreach (KeyValuePair entry in _fpgaDeviceMap)
{
try
{
entry.Value.Shutdown();
}
catch (Exception err)
{
_logger?.Error(err.Message + "\r\n" + err.StackTrace);
}
}
}
}
///
/// Initialize the communication to the fpga
///
/// the name of the fpga as defined in the config file
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
///
/// constructor with instrument manager
///
///
///
///
public FpgaMeasurementManager(IInstrumentManager instrumentManager, List instrumentNames, string instrumentDefFile)
{
_logger = LogManager.GetCurrentClassLogger();
_fpgaDeviceMap = new Dictionary();
foreach (string name in instrumentNames)
{
_fpgaDeviceMap[name] = instrumentManager.GetInstrument(name);
_fpgaDeviceMap[name]?.Initialize(name);
}
// setup the memory maps
_fpgaMemMaps = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
ConfigurationFile ini = new ConfigurationFile(instrumentDefFile);
foreach (KeyValuePair entry in _fpgaDeviceMap)
{
string memMapFile = ini.ReadValue(entry.Key, "MEM_MAP");
if (memMapFile.ToUpper().Trim() != "NONE")
{
_fpgaMemMaps.Add(entry.Key.ToUpper(), new MemoryMap(memMapFile));
}
}
}
///
/// Dispose of resources
///
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
}
}
}
///
/// Get the comm device
///
///
///
public IFpgaComm GetFpgaCommDevice(string fpga)
{
if (_fpgaDeviceMap.ContainsKey(fpga.ToUpper()) == false)
{
throw new Exception("could not find device: " + fpga);
}
return _fpgaDeviceMap[fpga.ToUpper()];
}
///
/// Returns all of the fpga names
///
/// A list of fpga device names
public List GetFpgaNames()
{
List fpgaList = new List();
foreach (KeyValuePair entry in _fpgaDeviceMap)
{
fpgaList.Add(entry.Key);
}
return fpgaList;
}
///
/// 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
///
/// the name of the fpga as defined in the config file
/// The name of the mem map item in the memory map file
///
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;
}
///
/// Read a register given an address
///
/// the name of the fpga as defined in the config file
/// the address to read
///
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);
}
///
/// Read a register given an address with optional offset
///
///
///
///
///
///
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;
}
///
/// reads block from fpga
///
///
///
///
///
///
///
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");
}
}
///
/// Write a register given an address
///
/// the name of the fpga as defined in the config file
/// The address to write to
/// The data to write to the register
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);
}
///
/// 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
///
/// the name of the fpga as defined in the config file
/// The name of the mem map item in the memory map file
/// The data to write to the register
/// The offset off of memMapItemName
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);
}
///
///
///
///
///
///
///
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);
}
///
/// 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
///
/// The name of the FPGA
/// The memory map item which we will restore the default.
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
}
}