Files
GenericTeProgramLibrary/Source/TSRealLib/Common/Raytheon.Common/Lib/MemoryMap.cs
2025-03-13 12:04:22 -07:00

317 lines
9.4 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 System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
namespace Raytheon.Common
{
/// <summary>
/// A class that reads a memory map upon construction and then serves up the fields of an entry upon request
/// </summary>
public class MemoryMap
{
#region PrivateClassMembers
public struct MemoryMapFields
{
public readonly uint _page;
public readonly uint _address;
public readonly int _startBit;
public readonly int _numBits;
public readonly uint _regDefault;
public readonly double _scaleFactor;
public MemoryMapFields(uint page, uint address, int startBit, int numBits, uint regDefault, double scaleFactor)
{
_page = page;
_address = address;
_startBit = startBit;
_numBits = numBits;
_regDefault = regDefault;
_scaleFactor = scaleFactor;
}
}
private struct BitInfo
{
public int _start;
public int _numOfBits;
}
private const string _NEWLINE = "\r\n";
private Dictionary<string, MemoryMapFields> _mapData;
private double _scaleFactor = 1.0;
#endregion
#region PrivateFuctions
/// <summary>
///
/// </summary>
/// <param name="fileLocation"></param>
/// <returns></returns>
private Dictionary<string, MemoryMapFields> CreateMemoryMapDictionary(string fileLocation)
{
Dictionary<string, MemoryMapFields> temp = new Dictionary<string, MemoryMapFields>();
//Open file for processing (read-only)
using (FileStream readStream = new FileStream(fileLocation, FileMode.Open, FileAccess.Read))
{
//Process the memmap
ProcessFile(readStream, temp);
}
return temp;
}
/// <summary>
/// Processes the memory map files into a data structure
/// </summary>
/// <param name="fs"></param>
/// <param name="memoryMap"></param>
private void ProcessFile(FileStream fs, Dictionary<string, MemoryMapFields> memoryMap)
{
uint page = 0;
uint address = 0;
uint regDefault = 0;
char[] delimit = { ' ' };
uint prevPage = 0;
uint prevAddress = 0;
uint parentRegDefault = 0;
using (StreamReader reader = new StreamReader(fs))
{
while (!reader.EndOfStream)
{
//Read a line from the file
string line = reader.ReadLine();
//Parse the line by spaces (remove empty entries)
string[] fields = line.Split(delimit, StringSplitOptions.RemoveEmptyEntries);
//If nothing to read, stop processing
if (fields.Length == 0)
{
break;
}
//Get the key (Register Name)
string key = fields[0].ToUpper();
//Check for duplicates
if (memoryMap.ContainsKey(key))
{
throw new Exception("Duplicate item found in file: " + fs.Name + ", Item key: " + key);
}
//Check if the register is a parent or child
//A child will use its parent address and gets it default value from its parent
if (line.StartsWith(" "))
{
regDefault = parentRegDefault;
page = prevPage;
address = prevAddress;
}
else
{
//Get the page number
page = ProcessPageNum(fields[1]);
//Get register address
address = ProcessDecimalHex(fields[1]);
//Get register default values
regDefault = ProcessDecimalHex(fields[5]);
//Get scale factor
_scaleFactor = ProcessScaleFactor(line);
}
//Process bits
BitInfo bitInfo = ProcessBitInfo(fields[3]);
double scaleFactor = _scaleFactor;
// parse out the default value for this child item
if (bitInfo._numOfBits < 32)
{
// clear the upper bits
int numBitsToClear = 32 - (bitInfo._start + bitInfo._numOfBits);
regDefault = regDefault << numBitsToClear;
// clear lower bits and place into position
int numBitsForPosition = bitInfo._start + numBitsToClear;
regDefault = regDefault >> numBitsForPosition;
}
else
{
parentRegDefault = regDefault;
}
memoryMap.Add(key, new MemoryMapFields(page, address, bitInfo._start, bitInfo._numOfBits, regDefault, scaleFactor));
// hold onto previous values for child items
prevPage = page;
prevAddress = address;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="pageNumber"></param>
/// <returns></returns>
private uint ProcessPageNum(string pageNumber)
{
//Delimiter used to parse string
char[] delimit = { '.' };
//Array of parsed string
string[] strPageValues = pageNumber.Split(delimit);
//Convert first array element
uint value = uint.Parse(strPageValues[0]);
//Return conversion
return value;
}
/// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
private uint ProcessDecimalHex(string address)
{
//Delimiter used to parse string
char[] delimit = { '.' };
//Array of parsed string
string[] strValues = address.Split(delimit);
string strCombined = "";
//Address = 0.XXXX.XXXX, register values = XXXX.XXXX
if (strValues.Length == 3)
{
strCombined = strValues[1] + strValues[2];
}
else
{
strCombined = strValues[0] + strValues[1];
}
//Convert hex number to UInt
uint value = uint.Parse(strCombined, System.Globalization.NumberStyles.HexNumber);
//Return value
return value;
}
/// <summary>
///
/// </summary>
/// <param name="bits"></param>
/// <returns></returns>
private BitInfo ProcessBitInfo(string bits)
{
//Structure for bit information
BitInfo temp;
//Delimiter used to parse string
char[] delimit = { ':' };
char[] trimChar = { '(', ')' };
string trimBits = bits.Trim(trimChar);
string[] values = trimBits.Split(delimit);
if (values.Length == 2)
{
//values represents a range of bits
int start = int.Parse(values[1]);
int end = int.Parse(values[0]);
//Add one for zero offset
temp._start = start;
temp._numOfBits = end - start + 1;
}
else
{
//Only a single bit
temp._numOfBits = 1;
temp._start = int.Parse(values[0]);
}
return temp;
}
/// <summary>
///
/// </summary>
/// <param name="scaleFactor"></param>
/// <returns></returns>
private double ProcessScaleFactor(string scaleFactor)
{
const string PATTERN = @"[+-]?[0-9]{1,}\.[0-9]{1,}[e][+-]?[0-9]{1,}";
//Find Scale Factor (default = 1)
string sf = "1";
foreach (Match match in Regex.Matches(scaleFactor, PATTERN))
{
sf = match.Value;
}
double value = double.Parse(sf);
return value;
}
#endregion
#region PublicFuctions
/// <summary>
/// The constructor
/// </summary>
/// <param name="memMapLocation">The memory map file</param>
public MemoryMap(string memMapLocation)
{
_mapData = CreateMemoryMapDictionary(memMapLocation);
}
/// <summary>
///
/// </summary>
/// <param name="registerName">The name of the register</param>
/// <returns></returns>
public MemoryMapFields GetRegisterInfoByString(string registerName)
{
if (_mapData.ContainsKey(registerName.ToUpper()) == false)
{
throw new Exception("The requested register: " + registerName + " is not in the memory map");
}
return _mapData[registerName.ToUpper()];
}
#endregion
}
}