Exemplo n.º 1
0
        static int ParseTCode(GerberLineReader lineReader, string drillFileName, DrillState drillState, GerberImage image)
        {
            int            drillNumber;
            double         drillSize = 0.0;
            int            length    = 0;
            char           nextCharacter;
            bool           done         = false;
            DrillFileStats stats        = image.DrillStats;
            string         line         = String.Empty;
            string         errorMessage = String.Empty;

            nextCharacter = lineReader.Read();
            if (!Char.IsDigit(nextCharacter))
            {
                if (nextCharacter == 'C')
                {
                    lineReader.Position -= 2;
                    line = lineReader.ReadLineToEnd();
                    if (line == "TCST")
                    {
                        errorMessage = "Tool change stop switch found.";
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                    }

                    return(-1);
                }
            }

            lineReader.Position--;
            drillNumber = lineReader.GetIntegerValue(ref length);
            // T00 is a tool unload command.
            if (drillNumber == 0)
            {
                return(drillNumber);
            }

            if (drillNumber < ToolMin && drillNumber >= ToolMax)
            {
                errorMessage = String.Format(CultureInfo.CurrentCulture, "Drill number out of bounds:{0}.\n", drillNumber);
                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
            }

            drillState.CurrentTool = drillNumber;

            // Tool definition following tool number.
            if (lineReader.Position > 0)
            {
                while (!done)
                {
                    nextCharacter = lineReader.Read();
                    switch (nextCharacter)
                    {
                    case 'C':
                        drillSize = GetDoubleValue(lineReader, drillState.HeaderNumberFormat, GerberOmitZero.OmitZerosTrailing, drillState.DecimalPlaces);
                        if (drillState.Unit == GerberUnit.Millimeter)
                        {
                            drillSize /= 25.4;
                        }

                        else if (drillSize >= 4.0)
                        {
                            drillSize /= 1000.0;
                        }

                        if (drillSize <= 0 || drillSize >= 10000)
                        {
                            errorMessage = "Unreasonable drill size found.";
                            stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
                        }

                        else
                        {
                            // Allow a redefinition of a tool only if all parameters are the same.
                            if (image.ApertureArray[drillNumber] != null)
                            {
                                if (image.ApertureArray[drillNumber].Parameters[0] != drillSize ||
                                    image.ApertureArray[drillNumber].ApertureType != GerberApertureType.Circle ||
                                    image.ApertureArray[drillNumber].ParameterCount != 1 ||
                                    image.ApertureArray[drillNumber].Unit != GerberUnit.Inch)
                                {
                                    errorMessage = String.Format(CultureInfo.CurrentCulture, "Found redefinition if drill {0}.\n", drillNumber);
                                    stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError);
                                }
                            }

                            else
                            {
                                image.ApertureArray[drillNumber] = new ApertureDefinition();
                                image.ApertureArray[drillNumber].Parameters[0]  = drillSize;
                                image.ApertureArray[drillNumber].ApertureType   = GerberApertureType.Circle;
                                image.ApertureArray[drillNumber].ParameterCount = 1;
                                image.ApertureArray[drillNumber].Unit           = GerberUnit.Inch;
                            }
                        }

                        string drillUnit = (drillState.Unit == GerberUnit.Millimeter) ? "MM" : "INCH";
                        stats.AddToDrillList(drillNumber, (drillState.Unit == GerberUnit.Millimeter) ? drillSize * 25.4 : drillSize, drillUnit);
                        break;

                    case 'F':
                    case 'S':
                        lineReader.GetIntegerValue(ref length);
                        break;

                    default:
                        lineReader.Position--;
                        done = true;
                        break;
                    }
                }
            }

            return(drillNumber);
        }
Exemplo n.º 2
0
        static bool ParseDrillSegment(string drillFileName, GerberLineReader lineReader, GerberImage image, DrillState drillState)
        {
            bool           foundEOF   = false;
            DrillFileStats stats      = image.DrillStats;
            GerberNet      currentNet = image.GerberNetList[0];

            currentNet.Level    = image.LevelList[0];
            currentNet.NetState = image.NetStateList[0];

            bool   done = false;
            string line;

            string[] command;
            string   errorMessage;
            char     nextCharacter;

            while (!lineReader.EndOfFile && !foundEOF)
            {
                nextCharacter = lineReader.Read();
                switch (nextCharacter)
                {
                case ';':       // Comment.
                    line = lineReader.ReadLineToEnd();
                    break;

                case 'D':
                    lineReader.Position--;
                    line = lineReader.ReadLineToEnd();
                    if (line.Substring(0, 6) == "DETECT")
                    {
                        stats.Detect = line.Substring(6, (line.Length - 7));
                    }

                    else
                    {
                        errorMessage = String.Format(CultureInfo.CurrentCulture, "Undefined header line: {0}.\n", line);
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                    }
                    break;

                case 'F':
                    lineReader.Position--;
                    line = lineReader.ReadLineToEnd();
                    if (line != "FMAT,2")
                    {
                        errorMessage = String.Format(CultureInfo.CurrentCulture, "Undefined header line: {0}.\n", line);
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                    }
                    break;

                case 'G':
                    DrillGCode gCode = ParseGCode(lineReader, image);
                    switch (gCode)
                    {
                    case DrillGCode.Rout:
                        errorMessage = "Rout Mode not supported.\n";
                        stats.AddNewError(-1, errorMessage, GerberErrorType.GerberNote, lineReader.LineNumber, drillFileName);
                        break;

                    case DrillGCode.Drill:
                        break;

                    case DrillGCode.Slot:
                        nextCharacter = lineReader.Read();
                        ParseCoordinate(lineReader, nextCharacter, image, drillState);
                        currentNet.StopX = drillState.CurrentX;
                        currentNet.StopY = drillState.CurrentY;
                        if (drillState.Unit == GerberUnit.Millimeter)
                        {
                            currentNet.StopX /= 25.4;
                            currentNet.StopY /= 25.4;
                        }

                        currentNet.ApertureState = GerberApertureState.On;
                        break;

                    case DrillGCode.Absolute:
                        drillState.CoordinateMode = DrillCoordinateMode.Absolute;
                        break;

                    case DrillGCode.Incrementle:
                        drillState.CoordinateMode = DrillCoordinateMode.Incremental;
                        break;

                    case DrillGCode.ZeroSet:
                        nextCharacter = lineReader.Read();
                        ParseCoordinate(lineReader, nextCharacter, image, drillState);
                        drillState.OriginX = drillState.CurrentX;
                        drillState.OriginY = drillState.CurrentY;
                        break;

                    default:
                        line = lineReader.ReadLineToEnd();
                        break;
                    }

                    break;

                case 'I':       // Inch header.
                    if (drillState.CurrentSection != DrillFileSection.Header)
                    {
                        break;
                    }

                    nextCharacter = lineReader.Read();
                    switch (nextCharacter)
                    {
                    // Inch
                    case 'N':
                        lineReader.Position -= 2;
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command[0] == "INCH")
                        {
                            drillState.Unit = GerberUnit.Inch;
                        }

                        if (command.Length == 2)
                        {
                            if (command[1] == "TZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                    drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                    drillState.DecimalPlaces      = 4;
                                }
                            }

                            else if (command[1] == "LZ")
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosTrailing;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces      = 4;
                            }

                            else
                            {
                                errorMessage = "Invalid zero suppression found after INCH.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                            }
                        }

                        else
                        {
                            // No TZ/LZ specified, use defaults.
                            if (drillState.AutoDetect)
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces      = 4;
                            }
                        }

                        break;

                    case 'C':
                        lineReader.Position -= 2;
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command.Length == 2)
                        {
                            if (command[1] == "ON")
                            {
                                drillState.CoordinateMode = DrillCoordinateMode.Incremental;
                            }

                            else if (command[1] == "OFF")
                            {
                                drillState.CoordinateMode = DrillCoordinateMode.Absolute;
                            }

                            else
                            {
                                errorMessage = "Invalid coordinate data found.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                            }
                        }

                        else
                        {
                            errorMessage = "Invalid data found.\n";
                            stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                        }

                        break;
                    }

                    break;

                case 'M':                             // M code or Metric
                    nextCharacter = lineReader.Read();
                    if (!Char.IsDigit(nextCharacter)) // Not a M## command.
                    {
                        // Should be a metric command in header.
                        // METRIC is only acceptable within the header section.
                        // The syntax is METRIC[,{TZ|LZ}][,{000.000|000.00|0000.00}] ??????
                        if (drillState.CurrentSection != DrillFileSection.Header)
                        {
                            break;
                        }

                        done = true;
                        lineReader.Position -= 2;       // Point back to the start on the line.
                        line    = lineReader.ReadLineToEnd();
                        command = line.Split(',');
                        if (command[0] == "METRIC")
                        {
                            drillState.Unit = GerberUnit.Millimeter;
                        }

                        if (command.Length > 1)
                        {
                            if (command[1] == "TZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros = GerberOmitZero.OmitZerosLeading;
                                }

                                done = false;
                            }

                            else if (command[1] == "LZ")
                            {
                                if (drillState.AutoDetect)
                                {
                                    image.Format.OmitZeros = GerberOmitZero.OmitZerosTrailing;
                                }

                                done = false;
                            }

                            else
                            {
                                errorMessage = "Invalid zero suppression found after METRIC.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                                done = true;
                            }

                            // Number format may or may not be specified.
                            if (!done && command.Length == 3)
                            {
                                if (drillState.AutoDetect)
                                {
                                    drillState.HeaderNumberFormat = drillState.DataNumberFormat = DrillNumberFormat.Format_000_000;
                                    drillState.DecimalPlaces      = 3;
                                }

                                if (command[2] == "0000.00")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_0000_00;
                                    drillState.DecimalPlaces    = 2;
                                }

                                else if (command[2] == "000.000")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_000_000;
                                    drillState.DecimalPlaces    = 3;
                                }

                                else if (command[2] == "000.00")
                                {
                                    drillState.DataNumberFormat = DrillNumberFormat.Format_000_00;
                                    drillState.DecimalPlaces    = 2;
                                }

                                else
                                {
                                    errorMessage = "Invalid number format found after TZ/LZ.\n";
                                    stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning, lineReader.LineNumber, drillFileName);
                                }
                            }
                        }

                        else
                        {
                            // No TZ/LZ or number format specified, use defaults.
                            if (drillState.AutoDetect)
                            {
                                image.Format.OmitZeros        = GerberOmitZero.OmitZerosLeading;
                                drillState.HeaderNumberFormat = DrillNumberFormat.Format_000_000;
                                drillState.DecimalPlaces      = 3;
                            }
                        }
                    }

                    else if (Char.IsDigit(nextCharacter))
                    {
                        // Must be an M## code.
                        lineReader.Position--;
                        DrillMCode mCode = ParseMCode(lineReader, drillState, image);
                        switch (mCode)
                        {
                        case DrillMCode.Header:
                            drillState.CurrentSection = DrillFileSection.Header;
                            break;

                        case DrillMCode.EndHeader:
                            drillState.CurrentSection = DrillFileSection.Data;
                            break;

                        case DrillMCode.Metric:
                            if (drillState.Unit == GerberUnit.Unspecified && drillState.CurrentSection != DrillFileSection.Header)
                            {
                                errorMessage = "M71 code found with no METRIC specification in header.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);

                                errorMessage = "Assuming all tool sizes are in millimeters.\n";
                                stats.AddNewError(-1, errorMessage, GerberErrorType.GerberWarning);


                                for (int toolNumber = ToolMin; toolNumber < ToolMax; toolNumber++)
                                {
                                    if (image.ApertureArray[toolNumber] != null)
                                    {
                                        double toolSize = image.ApertureArray[toolNumber].Parameters[0];
                                        stats.ModifyDrillList(toolNumber, toolSize, "MM");
                                        image.ApertureArray[toolNumber].Parameters[0] /= 25.4;
                                    }
                                }
                            }

                            if (drillState.AutoDetect)
                            {
                                drillState.DataNumberFormat = drillState.BackupNumberFormat;
                                drillState.Unit             = GerberUnit.Millimeter;
                            }

                            break;

                        case DrillMCode.Imperial:
                            if (drillState.AutoDetect)
                            {
                                if (drillState.DataNumberFormat != DrillNumberFormat.Format_00_0000)
                                {
                                    drillState.BackupNumberFormat = drillState.DataNumberFormat;            // Save format definition for later.
                                }
                                drillState.DataNumberFormat = DrillNumberFormat.Format_00_0000;
                                drillState.DecimalPlaces    = 4;
                                drillState.Unit             = GerberUnit.Inch;
                            }
                            break;

                        case DrillMCode.LongMessage:
                        case DrillMCode.Message:
                        case DrillMCode.CannedText:
                            line = lineReader.ReadLineToEnd();
                            // message here.
                            break;

                        case DrillMCode.NotImplemented:
                        case DrillMCode.EndPattern:
                        case DrillMCode.TipCheck:
                            break;

                        case DrillMCode.End:
                            line = lineReader.ReadLineToEnd();
                            break;

                        case DrillMCode.EndRewind:          // EOF.
                            //done = true;
                            foundEOF = true;
                            break;

                        default:
                            stats.AddNewError(-1, "Undefined M code.", GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
                            break;
                        }
                    }
                    break;

                case 'R':
                    if (drillState.CurrentSection == DrillFileSection.Header)
                    {
                        stats.AddNewError(-1, "R code not allowed in the header.", GerberErrorType.GerberError, lineReader.LineNumber, drillFileName);
                    }

                    else
                    {
                        double stepX = 0.0, stepY = 0.0;
                        int    length = 0;

                        image.DrillStats.R++;
                        double startX      = drillState.CurrentX;
                        double startY      = drillState.CurrentY;
                        int    repeatcount = lineReader.GetIntegerValue(ref length);
                        nextCharacter = lineReader.Read();
                        if (nextCharacter == 'X')
                        {
                            stepX         = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces);
                            nextCharacter = lineReader.Read();
                        }

                        if (nextCharacter == 'Y')
                        {
                            stepY = GetDoubleValue(lineReader, drillState.DataNumberFormat, image.Format.OmitZeros, drillState.DecimalPlaces);
                        }

                        else
                        {
                            lineReader.Position--;
                        }

                        for (int i = 1; i < repeatcount; i++)
                        {
                            drillState.CurrentX = startX + i * stepX;
                            drillState.CurrentY = startY + i * stepY;
                            currentNet          = AddDrillHole(image, drillState, currentNet);
                        }
                    }
                    break;

                case 'S':
                    // Ignore spindle speed.
                    lineReader.ReadLineToEnd();
                    break;

                case 'T':
                    int tool = ParseTCode(lineReader, drillFileName, drillState, image);
                    break;

                case 'X':
                case 'Y':
                    // Hole coordinate found. Do some parsing.
                    ParseCoordinate(lineReader, nextCharacter, image, drillState);

                    // Add the new drill hole.
                    currentNet = AddDrillHole(image, drillState, currentNet);
                    break;

                case '%':
                    drillState.CurrentSection = DrillFileSection.Data;
                    break;

                // Ignore white space or null characters.
                case '\n':
                case '\r':
                case ' ':
                case '\t':
                case '\0':
                    break;
                }
            }

            return(foundEOF);
        }