diff --git a/AltiumSharp/OriginalCircuit.AltiumSharp.csproj b/AltiumSharp/OriginalCircuit.AltiumSharp.csproj index 00d609f..bede400 100644 --- a/AltiumSharp/OriginalCircuit.AltiumSharp.csproj +++ b/AltiumSharp/OriginalCircuit.AltiumSharp.csproj @@ -37,7 +37,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/AltiumSharp/Records/Sch/SchPin.cs b/AltiumSharp/Records/Sch/SchPin.cs index c2fdc85..6ca25cb 100644 --- a/AltiumSharp/Records/Sch/SchPin.cs +++ b/AltiumSharp/Records/Sch/SchPin.cs @@ -95,6 +95,10 @@ public TextOrientations Orientation .WithFlag(PinConglomerateFlags.Flipped, value.HasFlag(TextOrientations.Flipped)); } + public IList Functions { get; } = new List(); + + public IList SelectedFunctions { get; } = new List(); + public SchPin() : base() { Electrical = PinElectricalType.Passive; diff --git a/AltiumSharp/SchDocReader.cs b/AltiumSharp/SchDocReader.cs index 24941ff..6d61dc1 100644 --- a/AltiumSharp/SchDocReader.cs +++ b/AltiumSharp/SchDocReader.cs @@ -30,7 +30,7 @@ private void ReadFileHeader() var parameters = ReadBlock(reader, size => ReadParameters(reader, size)); var weight = parameters["WEIGHT"].AsIntOrDefault(); - var primitives = ReadPrimitives(reader, null, null, null, null); + var primitives = ReadPrimitives(reader, null, null, null, null, null); Data.Items.AddRange(primitives); AssignOwners(primitives); diff --git a/AltiumSharp/SchDocWriter.cs b/AltiumSharp/SchDocWriter.cs index 3d5f878..197b463 100644 --- a/AltiumSharp/SchDocWriter.cs +++ b/AltiumSharp/SchDocWriter.cs @@ -46,7 +46,7 @@ private void WritePrimitives(BinaryWriter writer) var index = 0; var pinIndex = 0; WritePrimitive(writer, Data.Header, false, 0, ref index, ref pinIndex, - null, null, null, null); + null, null, null, null, null); } private void WriteAdditional() diff --git a/AltiumSharp/SchLibReader.cs b/AltiumSharp/SchLibReader.cs index 0ab346d..b20f76d 100644 --- a/AltiumSharp/SchLibReader.cs +++ b/AltiumSharp/SchLibReader.cs @@ -126,10 +126,11 @@ private SchComponent ReadComponent(string resourceName) var pinsWideText = ReadPinWideText(componentStorage); var pinsTextData = ReadPinTextData(componentStorage); var pinsSymbolLineWidth = ReadPinSymbolLineWidth(componentStorage); + var pinsFunctionData = ReadPinFunctionData(componentStorage); using (var reader = componentStorage.GetStream("Data").GetBinaryReader()) { - var primitives = ReadPrimitives(reader, pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth).ToList(); + var primitives = ReadPrimitives(reader, pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth, pinsFunctionData).ToList(); // First primitive read must be the component SchComponent var component = (SchComponent)primitives.First(); @@ -282,5 +283,43 @@ private Dictionary ReadPinSymbolLineWidth(CFStorage co return result; } + + /// + /// Reads a pin function data for the component at . + /// + private Dictionary ReadPinFunctionData(CFStorage componentStorage) + { + if (!componentStorage.TryGetStream("PinFunctionData", out var storage)) return null; + + BeginContext("PinFunctionData"); + + var result = new Dictionary(); + using (var reader = storage.GetBinaryReader()) + { + var headerParams = ReadBlock(reader, size => ReadParameters(reader, size)); + var header = headerParams["HEADER"].AsStringOrDefault(); + var weight = headerParams["WEIGHT"].AsIntOrDefault(); + AssertValue(nameof(header), header, "PinFunctionData"); + + while (reader.BaseStream.Position < reader.BaseStream.Length) + { + var (id, parameters) = ReadCompressedStorage(reader, stream => + { + using (var r = new BinaryReader(stream)) + { + return ReadBlock(r, s => ReadParameters(r, s, true, Encoding.Unicode)); + } + }); + var count = parameters["PINDEFINEDFUNCTIONSCOUNT"].AsIntOrDefault(); + CheckValue(nameof(count), count, parameters.Count - 1); + result.Add(int.Parse(id, CultureInfo.InvariantCulture), parameters); + } + CheckValue(nameof(weight), weight, result.Count); + } + + EndContext(); + + return result; + } } } diff --git a/AltiumSharp/SchLibWriter.cs b/AltiumSharp/SchLibWriter.cs index 900114c..d253bbf 100644 --- a/AltiumSharp/SchLibWriter.cs +++ b/AltiumSharp/SchLibWriter.cs @@ -95,27 +95,30 @@ private void WriteComponent(SchComponent component) var pinsWideText = new Dictionary(); var pinsTextData = new Dictionary(); var pinsSymbolLineWidth = new Dictionary(); + var pinsFunctionData = new Dictionary(); componentStorage.GetOrAddStream("Data").Write(writer => { - WriteComponentPrimitives(writer, component, pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth); + WriteComponentPrimitives(writer, component, pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth, pinsFunctionData); }); WritePinFrac(componentStorage, pinsFrac); WritePinTextData(componentStorage, pinsTextData); WriteComponentExtendedParameters(componentStorage, "PinWideText", pinsWideText); WriteComponentExtendedParameters(componentStorage, "PinSymbolLineWidth", pinsSymbolLineWidth); + WriteComponentExtendedParameters(componentStorage, "PinFunctionData", pinsFunctionData); } private static void WriteComponentPrimitives(BinaryWriter writer, SchComponent component, Dictionary pinsFrac, Dictionary pinsWideText, Dictionary pinsTextData, - Dictionary pinsSymbolLineWidth) + Dictionary pinsSymbolLineWidth, + Dictionary pinsFunctionData) { var index = 0; var pinIndex = 0; WritePrimitive(writer, component, true, 0, ref index, ref pinIndex, - pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth); + pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth, pinsFunctionData); } /// diff --git a/AltiumSharp/SchReader.cs b/AltiumSharp/SchReader.cs index 8082358..723bd7d 100644 --- a/AltiumSharp/SchReader.cs +++ b/AltiumSharp/SchReader.cs @@ -66,7 +66,8 @@ protected IDictionary ReadStorageEmbeddedImages() protected List ReadPrimitives(BinaryReader reader, Dictionary pinsFrac, Dictionary pinsWideText, Dictionary pinsTextData, - Dictionary pinsSymbolLineWidth) + Dictionary pinsSymbolLineWidth, + Dictionary pinsFunctionData) { if (reader == null) throw new ArgumentNullException(nameof(reader)); @@ -89,12 +90,14 @@ protected List ReadPrimitives(BinaryReader reader, ParameterCollection pinWideText = null; byte[] pinTextData = null; ParameterCollection pinSymbolLineWidth = null; + ParameterCollection pinFunctionData = null; pinsFrac?.TryGetValue(pinIndex, out pinFrac); pinsWideText?.TryGetValue(pinIndex, out pinWideText); pinsTextData?.TryGetValue(pinIndex, out pinTextData); pinsSymbolLineWidth?.TryGetValue(pinIndex, out pinSymbolLineWidth); + pinsFunctionData?.TryGetValue(pinIndex, out pinFunctionData); pinIndex++; - return ReadPinRecord(reader, size, pinFrac, pinWideText, pinTextData, pinSymbolLineWidth); + return ReadPinRecord(reader, size, pinFrac, pinWideText, pinTextData, pinSymbolLineWidth, pinFunctionData); }); primitive.SetRawData(ExtractStreamData(reader, primitiveStartPosition, reader.BaseStream.Position)); primitives.Add(primitive); @@ -274,7 +277,7 @@ protected static T ReadRecord(BinaryReader reader, } protected SchPin ReadPinRecord(BinaryReader reader, int size, (int x, int y, int length) pinFrac, - ParameterCollection pinWideText, byte[] pinTextData, ParameterCollection pinSymbolLineWidth) + ParameterCollection pinWideText, byte[] pinTextData, ParameterCollection pinSymbolLineWidth, ParameterCollection pinFunctionData) { if (reader == null) throw new ArgumentNullException(nameof(reader)); @@ -332,6 +335,20 @@ protected SchPin ReadPinRecord(BinaryReader reader, int size, (int x, int y, int pin.SymbolLineWidth = pinSymbolLineWidth["SYMBOL_LINEWIDTH"].AsEnumOrDefault(pin.SymbolLineWidth); } + if (pinFunctionData?.Count > 0) + { + var pinDefinedFunctionsCount = pinFunctionData[0].Value.AsInt(); + for (int i = 1; i < pinFunctionData.Count; i++) + { + pin.Functions.Add(pinFunctionData[i].Value.AsString()); + } + + if (pin.Functions.Count != pinDefinedFunctionsCount) + { + EmitWarning($"Pin function count mismatch: {pin.Functions.Count} != {pinDefinedFunctionsCount}"); + } + } + EndContext(); return pin; diff --git a/AltiumSharp/SchWriter.cs b/AltiumSharp/SchWriter.cs index 23cafb4..7b8c215 100644 --- a/AltiumSharp/SchWriter.cs +++ b/AltiumSharp/SchWriter.cs @@ -64,7 +64,7 @@ protected static void WritePrimitive(BinaryWriter writer, SchPrimitive primitive int ownerIndex, ref int index, ref int pinIndex, Dictionary pinsFrac, Dictionary pinsWideText, Dictionary pinsTextData, - Dictionary pinsSymbolLineWidth) + Dictionary pinsSymbolLineWidth, Dictionary pinsFunctionData) { if (primitive == null) throw new ArgumentNullException(nameof(primitive)); @@ -72,11 +72,14 @@ protected static void WritePrimitive(BinaryWriter writer, SchPrimitive primitive if (pinsSymbolLineWidth == null) throw new ArgumentNullException(nameof(pinsSymbolLineWidth)); + if (pinsFunctionData == null) + throw new ArgumentNullException(nameof(pinsFunctionData)); + primitive.OwnerIndex = ownerIndex; if (pinAsBinary && primitive is SchPin pin) { - WritePinRecord(writer, pin, out var pinFrac, out var pinWideText, out var pinTextData, out var pinSymbolLineWidth); + WritePinRecord(writer, pin, out var pinFrac, out var pinWideText, out var pinTextData, out var pinSymbolLineWidth, out var pinFunctionData); if (pinFrac.x != 0 || pinFrac.y != 0 || pinFrac.length != 0) { @@ -94,6 +97,10 @@ protected static void WritePrimitive(BinaryWriter writer, SchPrimitive primitive { pinsSymbolLineWidth.Add(pinIndex, pinSymbolLineWidth); } + if (pinFunctionData?.Count > 0) + { + pinsFunctionData.Add(pinIndex, pinFunctionData); + } pinIndex++; } @@ -107,7 +114,7 @@ protected static void WritePrimitive(BinaryWriter writer, SchPrimitive primitive foreach (var child in primitive.GetAllPrimitives()) { WritePrimitive(writer, child, pinAsBinary, currentIndex, ref index, ref pinIndex, - pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth); + pinsFrac, pinsWideText, pinsTextData, pinsSymbolLineWidth, pinsFunctionData); } } @@ -136,7 +143,8 @@ protected static void WriteAsciiRecord(BinaryWriter writer, SchPrimitive primiti /// Binary writer. /// Pin primitive to be serialized as a record. protected static void WritePinRecord(BinaryWriter writer, SchPin pin, out (int x, int y, int length) pinFrac, - out ParameterCollection pinWideText, out byte[] pinTextData, out ParameterCollection pinSymbolLineWidth) + out ParameterCollection pinWideText, out byte[] pinTextData, out ParameterCollection pinSymbolLineWidth, + out ParameterCollection pinFunctionData) { if (pin == null) throw new ArgumentNullException(nameof(pin)); @@ -194,6 +202,46 @@ protected static void WritePinRecord(BinaryWriter writer, SchPin pin, out (int x { { "SYMBOL_LINEWIDTH", pin.SymbolLineWidth } }; + + pinFunctionData = new ParameterCollection(); + + var hash = new HashSet(); + + if (pin.SelectedFunctions.Count > 0) + { + var pinHash = new HashSet(pin.Functions); + + pinFunctionData.Add("PINSELECTEDFUNCTIONSCOUNT", pin.SelectedFunctions.Count); + + for (int i = 0; i < pin.SelectedFunctions.Count; i++) + { + var selectedFunction = pin.SelectedFunctions[i]; + if (!pinHash.Contains(selectedFunction) || !hash.Add(selectedFunction)) + { + throw new NotSupportedException(); + } + + pinFunctionData.Add($"PINSELECTEDFUNCTION{i + 1}", selectedFunction); + } + } + + if (pin.Functions.Count > 0) + { + pinFunctionData.Add("PINDEFINEDFUNCTIONSCOUNT", pin.Functions.Count); + + hash.Clear(); + + for (int i = 0; i < pin.Functions.Count; i++) + { + var function = pin.Functions[i]; + if (!hash.Add(function)) + { + throw new NotSupportedException(); + } + + pinFunctionData.Add($"PINDEFINEDFUNCTION{i + 1}", function); + } + } } } } diff --git a/LibraryViewer/LibraryViewer.csproj b/LibraryViewer/LibraryViewer.csproj index 6303342..1afcad5 100644 --- a/LibraryViewer/LibraryViewer.csproj +++ b/LibraryViewer/LibraryViewer.csproj @@ -11,7 +11,7 @@ - + all