/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 1992-2017 Jean_Pierre Charras * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file gendrill_file_writer_base.h * @brief helper classes to handle hole info for drill files generators. */ #ifndef GENDRILL_FILE_WRITER_BASE_H #define GENDRILL_FILE_WRITER_BASE_H // holes can have an attribute in Excellon drill files, similar to attributes // in Gerber X2 format // They are only comments for a better identification of holes (vias, pads...) // Set to 1 to add these comments and 0 to not use these comments #define USE_ATTRIB_FOR_HOLES 1 #include class BOARD_ITEM; // hole attribute, mainly to identify vias and pads and add this info as comment // in NC drill files enum class HOLE_ATTRIBUTE { HOLE_UNKNOWN, // uninitialized type HOLE_VIA_THROUGH, // a via hole (always plated) from top to bottom HOLE_VIA_BURIED, // a via hole (always plated) not through hole HOLE_PAD, // a plated or not plated pad hole HOLE_MECHANICAL // a mechanical pad (provided, not used) }; // the DRILL_TOOL class handles tools used in the excellon drill file: class DRILL_TOOL { public: int m_Diameter; // the diameter of the used tool // (for oblong, the smaller size) int m_TotalCount; // how many times it is used (round and oblong) int m_OvalCount; // oblong count bool m_Hole_NotPlated; // Is the hole plated or not plated HOLE_ATTRIBUTE m_HoleAttribute; // Attribute (used in Excellon drill file) public: DRILL_TOOL( int aDiameter, bool a_NotPlated ) { m_TotalCount = 0; m_OvalCount = 0; m_Diameter = aDiameter; m_Hole_NotPlated = a_NotPlated; m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_UNKNOWN; } }; /** * Handle hole which must be drilled (diameter, position and layers). * * For buried or micro vias, the hole is not on all layers. So we must generate a drill file * for each layer pair (adjacent layers). Not plated holes are always through holes, and must * be output on a specific drill file because they are drilled after the PCB process is finished. */ class HOLE_INFO { public: HOLE_INFO() { m_ItemParent = nullptr; m_Hole_NotPlated = false; m_Hole_Diameter = 0; m_Tool_Reference = 0; m_Hole_Orient = ANGLE_0; m_Hole_Shape = 0; m_Hole_Bottom_Layer = B_Cu; m_Hole_Top_Layer = F_Cu; m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_UNKNOWN; } public: BOARD_ITEM* m_ItemParent; // The pad or via parent of this hole int m_Hole_Diameter; // hole value, and for oblong: min(hole size x, hole // size y). int m_Tool_Reference; // Tool reference for this hole = 1 ... n (values <=0 // must not be used). VECTOR2I m_Hole_Size; // hole size for oblong holes EDA_ANGLE m_Hole_Orient; // Hole rotation (= pad rotation) for oblong holes int m_Hole_Shape; // hole shape: round (0) or oval (1) VECTOR2I m_Hole_Pos; // hole position PCB_LAYER_ID m_Hole_Bottom_Layer; // hole ending layer (usually back layer) PCB_LAYER_ID m_Hole_Top_Layer; // hole starting layer (usually front layer): // m_Hole_Top_Layer < m_Hole_Bottom_Layer bool m_Hole_NotPlated; // hole not plated. Must be in a specific drill file or // section. HOLE_ATTRIBUTE m_HoleAttribute; // Attribute, used in Excellon drill file and to sort holes // by type. }; /** * Helper to handle drill precision format in excellon files. */ class DRILL_PRECISION { public: DRILL_PRECISION( int l = 2, int r = 4 ) { m_Lhs = l; m_Rhs = r; } wxString GetPrecisionString() { wxString text; text << m_Lhs << wxT( ":" ) << m_Rhs; return text; } int m_Lhs; // Left digit number (integer value of coordinates) int m_Rhs; // Right digit number (decimal value of coordinates) }; typedef std::pair DRILL_LAYER_PAIR; /** * Create drill maps and drill reports and drill files. * * Drill files are created by specialized derived classes, depending on the file format. */ class GENDRILL_WRITER_BASE { public: enum ZEROS_FMT { // Zero format in coordinates DECIMAL_FORMAT, // Floating point coordinates SUPPRESS_LEADING, // Suppress leading zeros SUPPRESS_TRAILING, // Suppress trailing zeros KEEP_ZEROS // keep zeros }; enum TYPE_FILE { // type of holes in file: PTH, NPTH, mixed PTH_FILE, // PTH only, this is the default also for blind/buried holes NPTH_FILE, // NPTH only MIXED_FILE // PHT+NPTH (mixed) }; virtual ~GENDRILL_WRITER_BASE() { } /** * Set the option to make separate drill files for PTH and NPTH. * * @param aMerge set to true to make only one file containing PTH and NPTH or false to * create 2 separate files. */ void SetMergeOption( bool aMerge ) { m_merge_PTH_NPTH = aMerge; } /** * Return the plot offset (usually the position of the drill/place origin). */ VECTOR2I GetOffset() { return m_offset; } /** * Set the page info used to plot drill maps. * * If NULL, a A4 page format will be used. * * @param aPageInfo is a reference to the page info, usually used to plot/display the board. */ void SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; } /** * Initialize the format for the drill map file. * * @param aMapFmt a PlotFormat value (one of PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, * PLOT_FORMAT_GERBER, PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF * the most useful are PLOT_FORMAT_PDF and PLOT_FORMAT_POST. */ void SetMapFileFormat( PLOT_FORMAT aMapFmt ) { m_mapFileFmt = aMapFmt; } /** * Create the full set of map files for the board, in PS, PDF ... format * (use SetMapFileFormat() to select the format). * * File names are computed from the board name and layer ID. * * @param aPlotDirectory is the output folder. * @param aReporter is a REPORTER to return activity or any message (can be NULL) */ bool CreateMapFilesSet( const wxString& aPlotDirectory, REPORTER* aReporter = nullptr ); /** * Create a plain text report file giving a list of drill values and drill count for through * holes, oblong holes, and for buried vias, drill values and drill count per layer pair * there is only one report for all drill files even when buried or blinds vias exist. * * Here is a sample created by this function: * Drill report for F:/tmp/interf_u/interf_u.brd * Created on 04/10/2012 20:48:38 * Selected Drill Unit: Imperial (inches) * * Drill report for plated through holes : * T1 0,025" 0,64mm (88 holes) * T2 0,031" 0,79mm (120 holes) * T3 0,032" 0,81mm (151 holes) (with 1 slot) * T4 0,040" 1,02mm (43 holes) * T5 0,079" 2,00mm (1 hole) (with 1 slot) * T6 0,120" 3,05mm (1 hole) (with 1 slot) * * Total plated holes count 404 * * * Drill report for buried and blind vias : * * Drill report for holes from layer Soudure to layer Interne1 : * * Total plated holes count 0 * * * Drill report for holes from layer Interne1 to layer Interne2 : * T1 0,025" 0,64mm (3 holes) * * Total plated holes count 3 * * * Drill report for holes from layer Interne2 to layer Composant : * T1 0,025" 0,64mm (1 hole) * * Total plated holes count 1 * * * Drill report for unplated through holes : * T1 0,120" 3,05mm (1 hole) (with 1 slot) * * Total unplated holes count 1 * * @param aFullFileName is the name of the file to create. * @return true if the file is created. */ bool GenDrillReportFile( const wxString& aFullFileName ); /** * Returns the file extension of the drill writer format */ wxString GetDrillFileExt() const { return m_drillFileExtension; } protected: /** * Plot a map of drill marks for holes. * * Hole list must be created before calling this function, by buildHolesList() for the * right holes set (PTH, NPTH, buried/blind vias ...) the paper sheet to use to plot the * map is set in m_pageInfo ( calls SetPageInfo() to set it ). If NULL, A4 format will * be used. * * @param aFullFileName is the full filename of the map file to create. * @param aFormat is one of the supported plot formats (see enum PlotFormat ). */ bool genDrillMapFile( const wxString& aFullFileName, PLOT_FORMAT aFormat ); /** * Create the list of holes and tools for a given board. * * The list is sorted by increasing drill size. Only holes included within aLayerPair * are listed. If aLayerPair identifies with [F_Cu, B_Cu], then pad holes are always * included also. * * @param aLayerPair is an inclusive range of layers. * @param aGenerateNPTH_list : * true to create NPTH only list (with no plated holes) * false to created plated holes list (with no NPTH ) */ void buildHolesList( DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list ); int getHolesCount() const { return m_holeListBuffer.size(); } /** * Write the drill marks in HPGL, POSTSCRIPT or other supported formats/ * * Each hole size has a symbol (circle, cross X, cross + ...) up to PLOTTER::MARKER_COUNT * different values. If more than PLOTTER::MARKER_COUNT different values, these other * values share the same mark shape. * * @param aPlotter is a PLOTTER instance (HPGL, POSTSCRIPT ... plotter). */ bool plotDrillMarks( PLOTTER* aPlotter ); /// Get unique layer pairs by examining the micro and blind_buried vias. std::vector getUniqueLayerPairs() const; /** * Print m_toolListBuffer[] tools to aOut and returns total hole count. * * @param aOut is the current OUTPUTFORMATTER to print summary. * @param aSummaryNPTH is true to print summary for NPTH, false for PTH. */ unsigned printToolSummary( OUTPUTFORMATTER& aOut, bool aSummaryNPTH ) const; /** * @return a string from aPair to identify the layer layer pair. * string is ""-"" * used to generate a filename for drill files and drill maps */ const std::string layerPairName( DRILL_LAYER_PAIR aPair ) const; /** * @return a string from aLayer to identify the layer. * string are "front" "back" or "in" */ const std::string layerName( PCB_LAYER_ID aLayer ) const; /** * @param aPair is the layer pair. * @param aNPTH use true to generate the filename of NPTH holes. * @param aMerge_PTH_NPTH use true to generate the filename of a file which containd both * NPH and NPTH holes. * @return a filename which identify the drill file function. * it is the board name with the layer pair names added, and for separate * (PTH and NPTH) files, "-NPH" or "-NPTH" added */ virtual const wxString getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH ) const; /** * @param aLayerPair is the layer pair (Drill from rom first layer to second layer) * @param aHoleType is type of drill file (PTH, NPTH, mixed) * @param aCompatNCdrill is true when generating NC (Excellon) compatible drill file * @return a wxString containing the .FileFunction attribute. * the standard X2 FileFunction for drill files is * %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried], * Drill[Route][Mixed]*% * There is no X1 version, as the Gerber drill files uses only X2 format * There is a compatible NC drill version. */ const wxString BuildFileFunctionAttributeString( DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHoleType, bool aCompatNCdrill = false ) const; protected: // Use derived classes to build a fully initialized GENDRILL_WRITER_BASE class. GENDRILL_WRITER_BASE( BOARD* aPcb ) { m_pcb = aPcb; m_conversionUnits = 1.0; m_unitsMetric = true; m_mapFileFmt = PLOT_FORMAT::PDF; m_pageInfo = nullptr; m_merge_PTH_NPTH = false; m_zeroFormat = DECIMAL_FORMAT; } BOARD* m_pcb; wxString m_drillFileExtension; // .drl or .gbr, depending on format bool m_unitsMetric; // true = mm, false = inches ZEROS_FMT m_zeroFormat; // the zero format option for output file DRILL_PRECISION m_precision; // The current coordinate precision (not // used in decimal format). double m_conversionUnits; // scaling factor to convert the board // unites to Excellon/Gerber units (i.e // inches or mm) VECTOR2I m_offset; // Drill offset coordinates bool m_merge_PTH_NPTH; // True to generate only one drill file std::vector m_holeListBuffer; // Buffer containing holes std::vector m_toolListBuffer; // Buffer containing tools PLOT_FORMAT m_mapFileFmt; // the format of the map drill file, // if this map is needed const PAGE_INFO* m_pageInfo; // the page info used to plot drill maps // If NULL, use a A4 page format }; #endif // #define GENDRILL_FILE_WRITER_BASE_H