private static PcbGraphics PolylineHelper(PcbUnits coordinateUnits,Piece item) { PcbGraphicsLayer l = PcbGraphicsLayer.TopSilk; PcbLineType t = PcbLineType.Solid; if (Piece.GraphicsLayerMapping.ContainsKey(item.CurrentLayer)) { l = Piece.GraphicsLayerMapping[item.CurrentLayer]; } else { WarningListener.AddFormat(new NotImplementedException(), "Default graphics layer used instead of #{0}",item.CurrentLayer); } if (Piece.LineTypeMapping.ContainsKey(item.CurrentLineType)) { t = Piece.LineTypeMapping[item.CurrentLineType]; } else { WarningListener.AddFormat(new NotImplementedException(), "Default line type used instead of {0}",Enum.GetName(typeof(Piece.LineType),item.CurrentLineType)); } PcbGraphics g = new PcbGraphics(coordinateUnits,coordinateUnits,l,item.XY.Count - 1); for (int i = 1; i < item.XY.Count; i++) { g.Lines.Add(new PcbSilkLine(item.XY[i - 1],item.XY[i],coordinateUnits,coordinateUnits,item.Width,t)); } return(g); }
private static PcbLayer DeterminePcbLayer(PadStack.StackLine line) { PcbLayer layer; switch ((PadStack.SpecialLayers)line.Layer) { case PadStack.SpecialLayers.Top: layer = PcbLayer.Top; break; case PadStack.SpecialLayers.Inner: layer = PcbLayer.InternalBottom; break; case PadStack.SpecialLayers.Bottom: layer = PcbLayer.Bottom; break; default: layer = (PcbLayer)(Enum.GetValues(typeof(PcbLayer)).Length + line.Layer - 1); WarningListener.Add(new NotImplementedException(), "Padstack non-special layer recognition is only partially implemented!"); break; } return(layer); }
private static void ProcessDecalPieces(PcbDesign res,PcbUnits coordinateUnits,Partdecal decal) { //Pieces are graphics and traces res.Traces.Capacity += decal.Pieces.Count(x => x.CurrentType == Piece.PieceType.Copper); res.Graphics.Capacity += decal.Pieces.Count(x => x.CurrentType != Piece.PieceType.Copper); foreach (var item in decal.Pieces) { switch (item.CurrentType) { case Piece.PieceType.Open: res.Graphics.Add(PolylineHelper(coordinateUnits,item)); break; case Piece.PieceType.Closed: res.Graphics.Add(PolylineHelper(coordinateUnits,item)); break; case Piece.PieceType.Copper: //Should move it to LINES instead of PARTDECAL res.Traces.Add( new PcbTrace(item.CurrentLayer == Piece.LayerAllNumber ? PcbLayer.All : (PcbLayer)item.CurrentLayer, item.Width,coordinateUnits,coordinateUnits,item.XY)); break; default: WarningListener.AddFormat(new NotImplementedException(), "Decal type {0} ignored.",Enum.GetName(typeof(Piece.PieceType),item.CurrentType)); break; } } }
/// <summary> /// Write *.RGN file contents into a string /// </summary> /// <param name="design"></param> /// <returns>String ready to be written into a file</returns> public string Write(PcbDesign design) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; design.SynchronizeUnits(PcbUnits.Thou); design.SynchronizeCoordinateUnits(PcbUnits.TenNanometers); StringBuilder res = new StringBuilder(Signature); res.AppendFormat(Header, this[design.CoordinateUnits]); StringBuilder temp = new StringBuilder(); //Objects (pads and graphics) foreach (var item in design.Pads) { try { temp.AppendFormat(PadInObjects, item.Number, string.Format(this[item.Style.Shape], item.Style.Dimension1 + (item.Layer == PcbLayer.Drill ? 10 : 0), //10 thou ring for drill holes (ARES7 does not support Dim1=Dim2) item.Style.Drill > 0 ? item.Style.Drill : item.Style.Dimension2), this[item.Layer], item.X, item.Y, item.Flags ?? StandardPadFlags); } catch (NotImplementedException e) { WarningListener.Add(e); } } foreach (var item in design.Graphics) { foreach (var line in item.Lines) { try { temp.AppendFormat(GraphicsLineInObjects, this[item.Layer], line.Start.X, line.Start.Y, line.End.X, line.End.Y); } catch (NotImplementedException e) { WarningListener.Add(e); } } } res.AppendFormat(Objects, temp.ToString().TrimEnd(Environment.NewLine.ToCharArray())); temp.Clear(); //Vias res.AppendFormat(Vias, ""); //Layers and traces var layers = design.GetLayers(true); foreach (var item in layers) { var objects = design.GetObjectsFromLayer(item, true).Cast <PcbTrace>(); foreach (var trace in objects) { temp.AppendFormat(TraceInLayer, trace.Thickness, trace.Segments, string.Join(" ", trace.XY.ToList().Select(x => string.Format("{0} {1}", x.X, x.Y)))); } res.AppendFormat(Layer, this[item], temp.ToString().TrimEnd(Environment.NewLine.ToCharArray())); } return(res.ToString()); }
public static PcbDesign Parse(string contents) { //Parse units from the header int i = contents.IndexOf(FileHeaderDesignator,1); int j = contents.LastIndexOf(FileHeaderSeparator,i) + 1; string temp = contents.Substring(j,i - j); PcbUnits coordinateUnits = HeaderUnits.First(x => x.Value == temp).Key; //Get section boundaries i = contents.IndexOf(LineSeparator,i) + 1; Dictionary <ControlStatement,int> sections = new Dictionary <ControlStatement,int>(ControlStatements.Length); for (int k = 0; k < ControlStatements.Length; k++) { j = contents.IndexOf(ControlStatements[k],i); if (j > -1) { j = contents.IndexOf(LineSeparator,j) + 1; if (j < contents.Length) { if (contents[j] == LineSeparator) { j++; } if (contents[j] == CaretReset) { j += 2; } } sections.Add((ControlStatement)k,j); } } //Parse partdecal int currentSectionStart = sections[ControlStatement.PARTDECAL]; int currentSectionEnd = FindSectionEnd(sections,ControlStatement.PARTDECAL); int currentSectionLength = currentSectionEnd - currentSectionStart; Partdecal decal = null; try { decal = Partdecal.Parse(contents.Substring(currentSectionStart,currentSectionLength)); } catch (Exception e) { WarningListener.Add(e); } //Others are not needed yet return(PADSToPcbDesign(coordinateUnits,decal)); }
static void Main(string[] args) { PADS.PieceHeaderCompatibilityMode = true; #if DEBUG args = new string[] { @"E:\cr.asc", @"E:\cr.RGN" }; #endif string output = Convert(File.ReadAllText(args[0]), EdaToolFormat.PADS_ASCII_PowerPcb, EdaToolFormat.RegionFile_ARES7); if (args.Length > 1) { File.WriteAllText(args[1], output); } if (WarningListener.Any) { Console.WriteLine("Warnings:"); Console.WriteLine(WarningListener.ToString()); } Console.WriteLine("Done."); Console.ReadKey(); }
private static PcbPadStyle DeterminePadStyle(PadStack.StackLine line,PcbUnits coordinateUnits) { PcbPadStyle style; bool drilled = line.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Present; switch (line.CurrentShape) { case PadStack.Shape.Round: //"Round" pads with drill argument are used for drilled pads (not annular pads!) style = new PcbPadStyle(drilled ? PcbPadShape.CircularTH : PcbPadShape.CircularSMT, coordinateUnits,line.Size,0, drilled ? (double)line.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Value : 0); break; case PadStack.Shape.Square: style = new PcbPadStyle(drilled ? PcbPadShape.RectangularTH : PcbPadShape.RectangularSMT, coordinateUnits,line.Size,line.Size, drilled ? (double)line.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Value : 0); break; case PadStack.Shape.Annular: style = new PcbPadStyle(drilled ? PcbPadShape.CircularTH : PcbPadShape.CircularSMT, coordinateUnits,line.Size, (double)line.Arguments[(int)PadStack.StackLine.DependentArguments.InternalDiameter].Value, drilled ? (double)line.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Value : 0); break; case PadStack.Shape.RectangularFinger: style = new PcbPadStyle(PcbPadShape.RectangularSMT,coordinateUnits,line.Size, (double)line.Arguments[(int)PadStack.StackLine.DependentArguments.FingerLength].Value); WarningListener.Add(new NotImplementedException("Only Length argument is supported for RectangularFinger pad style!")); break; default: throw new NotImplementedException(string.Format( "Pad shape {0} ignored.",Enum.GetName(typeof(PadStack.Shape),line.CurrentShape))); } return(style); }
private static PcbDesign PADSToPcbDesign(PcbUnits coordinateUnits,Partdecal decal) { PcbDesign res = new PcbDesign(); //Partdecal try { if (decal != null) { ProcessDecalPieces(res,coordinateUnits,decal); ProcessDecalPads(res,coordinateUnits,decal); } } catch (Exception e) { WarningListener.Add(e); } //Others are not implemented yet //Header info res.SynchronizeCoordinateUnits(coordinateUnits); return(res); }
public static Partdecal Parse(string section) { if (section.Length == 0) { return(null); } TextReader reader = new StringReader(section); //StringBuilder temp = new StringBuilder(section.Length); //Header string[] split = reader.ReadLine().Split(' '); int pieces = int.Parse(split[(int)Header.Pieces]); int padstacks = int.Parse(split[(int)Header.Stacks]); int pinTerminals = int.Parse(split[(int)Header.Terminals]); Partdecal res = new Partdecal(pieces,pinTerminals,padstacks, split[(int)Header.Name],PartdecalUnits.First(x => x.Value == split[(int)Header.Units]).Key); int headerEnded = section.IndexOf(LineSeparator) + 1; int j; //Pieces foreach (var item in Piece.TypeString) { j = headerEnded; for (int i = 0; i < pieces; i++) { j = section.IndexOf(item.Value,j); if (j < 0) { break; } try { res.Pieces.Add(Piece.Parse(section.Substring(j),typeof(Piece.PartdecalHeader))); } catch (Exception e) { WarningListener.Add(e); } finally { j += item.Value.Length + 1; } } } //padstacks j = headerEnded; for (int i = 0; i < padstacks; i++) { j = section.IndexOf(PadStack.PadstackPrefix,j); if (j < 0) { break; } try { res.PadStacks.Add(PadStack.Parse(section.Substring(j))); } catch (Exception e) { WarningListener.Add(e); } finally { j += PadStack.PadstackPrefix.Length + 1; } } //terminals j = headerEnded; for (int i = 0; i < pinTerminals; i++) { j = section.IndexOf(Terminal.TerminalPrefix,j); if (j < 0) { break; } try { res.Terminals.Add(Terminal.Parse(section.Substring(j),i + 1)); } catch (Exception e) { WarningListener.Add(e); } finally { j += Terminal.TerminalPrefix.Length; } } return(res); }
private static void ProcessDecalPads(PcbDesign res,PcbUnits coordinateUnits,Partdecal decal) { //Terminals + padstacks = pads PadStack defaultStack = decal.PadStacks.FirstOrDefault(x => x.PinDesignator == PadStack.AllTerminalsDesignator); res.Pads.Capacity += decal.Terminals.Count; foreach (var item in decal.Terminals) { var padstack = FindSuitablePadstack(decal,item,defaultStack); if (padstack == null) { WarningListener.Add(new ArgumentException(),"Can't find a suitable padstack for the terminal #" + item.PinDesignator); continue; } var drillLine = padstack.StackLines.FirstOrDefault(x => x.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Present); if (drillLine != null) { //Detect drill-only holes double d = (double)drillLine.Arguments[(int)PadStack.StackLine.DependentArguments.DrillSize].Value; if (d >= drillLine.Size) { res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,PcbLayer.Drill, new PcbPadStyle(PcbPadShape.CircularTH,coordinateUnits,d,0,d))); continue; } } List <PadStack.StackLine> usefulLines = padstack.StackLines.Where(x => (x.Size != 0 || x.Arguments.Any(y => y.Present))).ToList(); if (usefulLines.Count == 3) //Recognize layer "ALL" { //PADS requires minimum of 3 layers specified, 0x0 size indicates that the pad is not actually present //If some stacklines have 0 size and no useful arguments (shape does not count), then we effectively have less stacklines if (usefulLines.Select(x => x.Layer).Union(PadStack.AllLayerPattern).Count() == 3) { //Find layer that contains the most arguments (drill for example appears only for component-side layer) int maxArgs = 0; for (int i = 1; i < usefulLines.Count; i++) { if (usefulLines[maxArgs].Arguments.Count(x => x.Present) < usefulLines[i].Arguments.Count(x => x.Present)) { maxArgs = i; } } res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,PcbLayer.All, DeterminePadStyle(usefulLines[maxArgs],coordinateUnits))); continue; } } //If this is not a special case, parse stacklines one-by-one foreach (var line in usefulLines) { PcbPadStyle style = DeterminePadStyle(line,coordinateUnits); PcbLayer layer = DeterminePcbLayer(line); res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y,layer,style)); //-1 stands for both "Internal layers", but we can return only a single layer, so fix it afterwards if (layer == PcbLayer.InternalBottom) { res.Pads.Add(new PcbPad(item.PinDesignator,coordinateUnits,item.X,item.Y, PcbLayer.InternalTop,style)); } } } }