/* * This EAGLE User Language Program generates a script file * of a part or a symbol in a library scaled in relation to the origin. * * Version 1.00 by Hansjörg Sämann, September 1999 * * NO WARRANTY WILL BE GIVEN FOR ANYTHING !!! * * Open a package or a symbol in a library and place a text * like "S=0.5" (or "s=2") on any layer in the package * or symbol to specify the scale factor. To scale up the scale * factor must be greater than 1, to scale down the scale factor * must be less than 1. No spaces are allowed. * Then run the ULP. * The generated script file can be read into the same or * another part or symbol in the same or another library. * Don't forget to remove the scale specification text when * you have finished your work! * * Only elements of visible layers will be considered. * * If the ULP has finished you will get the message "finished". * If the ULP was not succesfull you will get the message * "finished (errorlevel x)". The following values for x are * used by this ULP: * * -1 = ULP wasn't run in a library * -2 = ULP wasn't run in a package or a symbol * -3 = No valid scale factor is specified * */ /* * program paramters */ enum {No, Yes}; /* end program paramters */ /* * global constants */ enum {px, py}; enum {ECOk = 0, ECNotALibrary = -1, ECNotAPartOrSymbol = -2, ECNoScaleSpec = -3}; /* * global variables */ int ExitCode; real Scale = 0; string ScaleSpecText = "S="; int ScaleSpecPnt []; int ActLayer = -1; int ActRatio = -1; int ActSize = -1; int ActSpacing = -1; int ActPour = -1; int ActDrill = -1; int ActDiameter = -1; int ActWidth = -1; int LayerOn []; string PourTexts [] = {"solid", "hatch"}; int GrdUnit; string GrdUnitTexts [] = {"mic", "mm", "mil", "inch"}; string MirrorTexts [] = {"", "M"}; string ShapeTexts [] = {"Square", "Round", "Octagon", "Xlongoct", "YLongoct"}; string PinDirTexts[] = {"NC", "In", "Out", "I/O", "OC", "Pwr", "Pas", "Hiz", "Sup"}; string PinFuncTexts[] = {"None", "Dot", "Clk", "DotClk"}; string PinLengthTexts[] = {"Point", "Short", "Middle", "Long"}; string PinVisiTexts[] = {"Off", "Pad", "Pin", "Both"}; int PinCorrectValues [] = {0, 25400, 50800, 76200}; int P0 []; int P1 []; int P2 []; int P3 []; /* * converts the internal used unit (1/10000mm) to * the actual used grid unit */ real Norm(int i) { real a; switch (GrdUnit) { case GRID_UNIT_MIC: a = u2mic(i); break; case GRID_UNIT_MM: a = u2mm(i); break; case GRID_UNIT_MIL: a = u2mil(i); break; case GRID_UNIT_INCH: a = u2inch(i); } return a; } /* * looks for the scale factor specification and * returns if a valid one was found or not */ int GetScale(UL_TEXT T) { string s; ++ScaleSpecPnt[0]; if (strstr(strupr(T.value), ScaleSpecText) == 0) { s = strsub(T.value, 2); if (strlen(s) == 0) return 0; for (int i = 0; s[i]; ++i) { if (!isdigit(s[i])) if ((s[i] != '.')) return 0; } Scale = strtod(s); return 1; } return 0; } /* * checks which layers are visible */ void GetLayersOn(UL_LAYER L) { if (L.visible) LayerOn[L.number] = L.visible; } /* * initiates a layer change if necessary * and returns if a layer is visible or not */ int HndlLayer(int l) { if (LayerOn[l]) { if (l != ActLayer) { ActLayer = l; printf("Layer %d;\n", ActLayer); } return 1; } else return 0; } /* * initiates a ratio change if necessary */ void HndlRatio(int r) { if (r != ActRatio) { ActRatio = r; printf("Change Ratio %d;\n", ActRatio); } } /* * initiates a size change if necessary */ void HndlSize(int s) { if (s != ActSize) { ActSize = s; printf("Change Size %f;\n", Norm(ActSize)); } } /* * initiates a spacing change if necessary */ void HndlSpacing(int s) { if (s != ActSpacing) { ActSpacing = s; printf("Change Spacing %f;\n", Norm(ActSpacing)); } } /* * initiates a pour change if necessary */ void HndlPour(int p) { if (p != ActPour) { ActPour = p; printf("Change Pour %s;\n", PourTexts[ActPour]); } } /* * initiates a drill change if necessary */ void HndlDrill(int d) { if (d != ActDrill) { ActDrill = d; printf("Change Drill %f;\n", Norm(ActDrill)); } } /* * initiates a diameter change if necessary */ void HndlDiameter(int d) { if (d != ActDiameter) { ActDiameter = d; printf("Change Diameter %f;\n", Norm(ActDiameter)); } } /* * initiates a width change if necessary */ void HndlWidth(int w) { if (w != ActWidth) { ActWidth = w; printf("Change Width %f;\n", Norm(ActWidth)); } } /* * calculates and returns a scaled value */ int CalcScaledValue(real v) { return round(v*Scale); } /* * calculates a scaled point */ void CalcScaledPoint(real x, real y) { P0[px] = round(x*Scale); P0[py] = round(y*Scale); } /* * writes necessary environment information * to the top of the file */ void SCRHeader(UL_LIBRARY L) { printf("Set Wire_Style 2;\n"); GrdUnit = L.grid.unit; printf("Grid %s;\n", GrdUnitTexts[L.grid.unit]); } /* * scales an arc */ void ScaleArc(UL_ARC A) { if (HndlLayer(A.layer)) { CalcScaledPoint(A.x1,A.y1); P1[px] = P0[px]; P1[py] = P0[py]; CalcScaledPoint(A.x2,A.y2); P3[px] = P0[px]; P3[py] = P0[py]; CalcScaledPoint(A.xc,A.yc); P2[px] = P1[px] - ((P1[px] - P0[px]) * 2); P2[py] = P1[py] - ((P1[py] - P0[py]) * 2); printf("Arc CCW %f (%f %f) (%f %f) (%f %f);\n", Norm(CalcScaledValue(A.width)), Norm(P1[px]), Norm(P1[py]), Norm(P2[px]), Norm(P2[py]), Norm(P3[px]), Norm(P3[py])); } } /* * scales a circle */ void ScaleCircle(UL_CIRCLE C) { if (HndlLayer(C.layer)) { CalcScaledPoint(C.x,C.y); P1[px] = P0[px]; P1[py] = P0[py]; P2[px] = P0[px] + CalcScaledValue(C.radius); P2[py] = P0[py]; printf("Circle %f (%f %f) (%f %f);\n", Norm(CalcScaledValue(C.width)), Norm(P1[px]), Norm(P1[py]), Norm(P2[px]), Norm(P2[py])); } } /* * scales a wire */ void ScaleWire(UL_WIRE W) { if (HndlLayer(W.layer)) { CalcScaledPoint(W.x2,W.y2); P1[px] = P0[px]; P1[py] = P0[py]; CalcScaledPoint(W.x1,W.y1); printf("Wire %f (%f %f) (%f %f);\n", Norm(CalcScaledValue(W.width)), Norm(P0[px]), Norm(P0[py]), Norm(P1[px]), Norm(P1[py])); } } /* * scales a rectangle */ void ScaleRectangle(UL_RECTANGLE R) { if (HndlLayer(R.layer)) { CalcScaledPoint(R.x2,R.y2); P1[px] = P0[px]; P1[py] = P0[py]; CalcScaledPoint(R.x1,R.y1); printf("Rect (%f %f) (%f %f)\n", Norm(P0[px]), Norm(P0[py]), Norm(P1[px]), Norm(P1[py])); } } /* * scales a contact (pad or SMD) */ void ScaleContact(UL_CONTACT C) { int fr, ls, lc; if (C.pad) { if (LayerOn[LAYER_PADS]) { HndlDrill(CalcScaledValue(C.pad.drill)); CalcScaledPoint(C.pad.x,C.pad.y); printf("Pad '%s' %s %f (%f %f);\n", C.pad.name, ShapeTexts[C.pad.shape], Norm(CalcScaledValue(C.pad.diameter)), Norm(P0[px]), Norm(P0[py])); } } if (C.smd) { if (HndlLayer(C.smd.layer)) { CalcScaledPoint(C.smd.x,C.smd.y); printf("Smd '%s' %f %f (%f %f);\n", C.smd.name, Norm(CalcScaledValue(C.smd.dx)), Norm(CalcScaledValue(C.smd.dy)), Norm(P0[px]), Norm(P0[py])); } } } /* * scales a pin */ void ScalePin(UL_PIN P) { if (LayerOn[LAYER_PINS]) { switch (int(round(P.angle))) { case 0: P0[px] = P.x + PinCorrectValues[P.length]; CalcScaledPoint(P0[px],P.y); P0[px] = P0[px] - PinCorrectValues[P.length]; break; case 90: P0[py] = P.y + PinCorrectValues[P.length]; CalcScaledPoint(P.x,P0[py]); P0[py] = P0[py] - PinCorrectValues[P.length]; break; case 180: P0[px] = P.x - PinCorrectValues[P.length]; CalcScaledPoint(P0[px],P.y); P0[px] = P0[px] + PinCorrectValues[P.length]; break; case 270: P0[py] = P.y - PinCorrectValues[P.length]; CalcScaledPoint(P.x,P0[py]); P0[py] = P0[py] + PinCorrectValues[P.length]; } printf("Pin '%s' %s %s %s R%d %s %d (%f %f);\n", P.name, PinDirTexts[P.direction], PinFuncTexts[P.function], PinLengthTexts[P.length], int(round(P.angle)), PinVisiTexts[P.visible], P.swaplevel, Norm(P0[px]), Norm(P0[py])); } } /* * scales a hole */ void ScaleHole(UL_HOLE H) { if (LayerOn[LAYER_HOLES]) { CalcScaledPoint(H.x,H.y); printf("Hole %f (%f %f);\n", Norm(CalcScaledValue(H.drill)), Norm(P0[px]), Norm(P0[py])); } } /* * scales a polygon */ void ScalePolygon(UL_POLYGON P) { int i = 0; int j = 0; if (HndlLayer(P.layer)) { HndlSpacing(P.spacing); HndlPour(P.pour); printf("Polygon %f ", Norm(CalcScaledValue(P.width))); P.wires(W) i++; P.wires(W) { CalcScaledPoint(W.x1,W.y1); P1[px] = P0[px]; P1[py] = P0[py]; ++j; if (j == 1) printf("(%f %f) ", Norm(P1[px]), Norm(P1[py])); else if (j%2 > 0) printf(" (%f %f) ", Norm(P1[px]), Norm(P1[py])); else printf("(%f %f) \\\n", Norm(P1[px]), Norm(P1[py])); if (--i == 0) { CalcScaledPoint(W.x2,W.y2); P1[px] = P0[px]; P1[py] = P0[py]; if (j%2 > 0) printf("(%f %f);\n", Norm(P1[px]), Norm(P1[py])); else printf(" (%f %f);\n", Norm(P1[px]), Norm(P1[py])); } } } } /* * scales a text */ void ScaleText(UL_TEXT T) { if (ScaleSpecPnt[0] != ++ScaleSpecPnt[1]) { if (HndlLayer(T.layer)) { HndlSize(CalcScaledValue(T.size)); HndlRatio(T.ratio); CalcScaledPoint(T.x,T.y); P1[px] = P0[px]; P1[py] = P0[py]; printf("Text '%s' %sR%d (%f %f);\n", T.value, MirrorTexts[T.mirror], int(round(T.angle)), Norm(P1[px]), Norm(P1[py])); } } } /* * processes a package */ void DoPackage(UL_PACKAGE P) { P.arcs(A) { ScaleArc(A); } P.circles(C) { ScaleCircle(C); } P.contacts(Cn) { ScaleContact(Cn); } P.holes(H) { ScaleHole(H); } P.polygons(Ply) { ScalePolygon(Ply); } P.rectangles(R) { ScaleRectangle(R); } P.texts(T) { ScaleText(T); } P.wires(W) { ScaleWire(W); } } /* * processes a symbol */ void DoSymbol(UL_SYMBOL S) { S.arcs(A) { ScaleArc(A); } S.circles(C) { ScaleCircle(C); } S.rectangles(R) { ScaleRectangle(R); } S.pins(Pn) { ScalePin(Pn); } S.polygons(P) { ScalePolygon(P); } S.texts(T) { ScaleText(T); } S.wires(W) { ScaleWire(W); } } /* * main program */ ExitCode = ECNotALibrary; if (library) library(L) { L.layers(Ls) GetLayersOn(Ls); ExitCode = ECNotAPartOrSymbol; if (package) package(P) { ExitCode = ECNoScaleSpec; P.texts(T) { if (GetScale(T)) { ExitCode = ECOk; break; } } if (ExitCode == ECOk) { output(filesetext(P.name, ".SCR")) { SCRHeader(L); DoPackage(P); } } } if (symbol) symbol(S) { ExitCode = ECNoScaleSpec; S.texts(T) { if (GetScale(T)) { ExitCode = ECOk; break; } } if (ExitCode == ECOk) { output(filesetext(S.name, ".SCR")) { ExitCode = ECOk; SCRHeader(L); DoSymbol(S); } } } } exit(ExitCode);