gendrill_Excellon_writer.h 11.5 KB
Newer Older
1
/**
2 3
 * @file gendrill_Excellon_writer.h
 * @brief Classes used in drill files, map files and report files generation.
4 5
 */

6
/*
7
 * This program source code file is part of KiCad, a free EDA CAD application.
8
 *
9 10
 * Copyright (C) 1992-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
 * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * 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
 */
dickelbeck's avatar
dickelbeck committed
29

30 31
#ifndef _GENDRILL_EXCELLON_WRITER_
#define _GENDRILL_EXCELLON_WRITER_
dickelbeck's avatar
dickelbeck committed
32

33 34 35 36 37 38 39
#include <vector>


class BOARD;
class PLOTTER;


40
/* the DRILL_TOOL class  handles tools used in the excellon drill file */
dickelbeck's avatar
dickelbeck committed
41 42 43
class DRILL_TOOL
{
public:
44 45 46
    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
47 48 49

public:
    DRILL_TOOL( int diametre )
dickelbeck's avatar
dickelbeck committed
50 51 52 53 54 55 56 57
    {
        m_TotalCount = 0;
        m_OvalCount  = 0;
        m_Diameter   = diametre;
    }
};


58 59 60 61 62
/* the HOLE_INFO class 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.
Wayne Stambaugh's avatar
Wayne Stambaugh committed
63
 */
dickelbeck's avatar
dickelbeck committed
64 65 66
class HOLE_INFO
{
public:
Dick Hollenbeck's avatar
Dick Hollenbeck committed
67 68 69 70 71 72 73 74 75 76
    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)
    wxSize      m_Hole_Size;            // hole size for oblong holes
    double      m_Hole_Orient;          // Hole rotation (= pad rotation) for oblong holes
    int         m_Hole_Shape;           // hole shape: round (0) or oval (1)
    wxPoint     m_Hole_Pos;             // hole position
    LAYER_ID    m_Hole_Bottom_Layer;    // hole starting layer (usually back layer)
    LAYER_ID    m_Hole_Top_Layer;       // hole ending layer (usually front layer):
                                        // m_Hole_First_Layer < m_Hole_Last_Layer
    bool        m_Hole_NotPlated;       // hole not plated. Must be in a specific drill file
Wayne Stambaugh's avatar
Wayne Stambaugh committed
77

78 79 80 81 82
public:
    HOLE_INFO()
    {
        m_Hole_NotPlated = false;
    }
dickelbeck's avatar
dickelbeck committed
83 84 85
};


86
/* the DRILL_PRECISION helper class to handle drill precision format in excellon files
87
 */
88
class DRILL_PRECISION
dickelbeck's avatar
dickelbeck committed
89 90
{
public:
91
    int m_lhs;      // Left digit number (integer value of coordinates)
Wayne Stambaugh's avatar
Wayne Stambaugh committed
92
    int m_rhs;      // Right digit number (decimal value of coordinates)
dickelbeck's avatar
dickelbeck committed
93

94
public: DRILL_PRECISION( int l = 2, int r = 4 )
95 96 97
    {
        m_lhs = l; m_rhs = r;
    }
98 99


100 101 102
    wxString GetPrecisionString()
    {
        wxString text;
103 104

        text << m_lhs << wxT( ":" ) << m_rhs;
105 106
        return text;
    }
dickelbeck's avatar
dickelbeck committed
107 108
};

109

110 111 112 113
/**
 * EXCELLON_WRITER is a class mainly used to create Excellon drill files
 * However, this class is also used to create drill maps and drill report
 */
114 115 116 117 118 119 120 121 122 123
class EXCELLON_WRITER
{
public:
    enum zeros_fmt {
        // Zero format in coordinates
        DECIMAL_FORMAT,
        SUPPRESS_LEADING,
        SUPPRESS_TRAILING,
        KEEP_ZEROS
    };
Wayne Stambaugh's avatar
Wayne Stambaugh committed
124 125 126

    wxPoint                  m_Offset;                  // offset coordinates
    bool                     m_ShortHeader;             // true to generate the smallest header (strip comments)
127 128 129 130

private:
    FILE*                    m_file;                    // The output file
    BOARD*                   m_pcb;
Wayne Stambaugh's avatar
Wayne Stambaugh committed
131
    bool                     m_minimalHeader;           // True to use minimal header
132 133 134
                                                        // in excellon file (strip comments)
    bool                     m_unitsDecimal;            // true = decimal, false = inches
    zeros_fmt                m_zeroFormat;              // the zero format option for output file
Wayne Stambaugh's avatar
Wayne Stambaugh committed
135
    DRILL_PRECISION          m_precision;               // The current coordinate precision (not used in decimal format)
136 137 138
    double                   m_conversionUnits;         // scaling factor to convert the board unites to Excellon units
                                                        // (i.e inches or mm)
    bool                     m_mirror;
Wayne Stambaugh's avatar
Wayne Stambaugh committed
139
    wxPoint                  m_offset;                  // Drill offset coordinates
140
    bool                     m_mergePTHNPTH;
141 142
    std::vector<HOLE_INFO>   m_holeListBuffer;          // Buffer containing holes
    std::vector<DRILL_TOOL>  m_toolListBuffer;          // Buffer containing tools
143

Wayne Stambaugh's avatar
Wayne Stambaugh committed
144 145
public:
    EXCELLON_WRITER( BOARD* aPcb, wxPoint aOffset )
146
    {
147
        m_file = NULL;
148 149 150 151 152
        m_pcb  = aPcb;
        m_zeroFormat      = DECIMAL_FORMAT;
        m_conversionUnits = 0.0001;
        m_unitsDecimal    = false;
        m_mirror = false;
153
        m_mergePTHNPTH = false;
154 155
        m_minimalHeader = false;
    }
dickelbeck's avatar
dickelbeck committed
156 157


158 159 160 161
    ~EXCELLON_WRITER()
    {
    }

162 163
    /**
     * Return the plot offset (usually the position
Wayne Stambaugh's avatar
Wayne Stambaugh committed
164
     * of the auxiliary axis
165 166
     */
    const wxPoint GetOffset() { return m_offset; }
167 168

    /**
169
     * Function SetFormat
170 171 172 173 174 175 176 177 178
     * Initialize internal parameters to match the given format
     * @param aMetric = true for metric coordinates, false for imperial units
     * @param aZerosFmt =  DECIMAL_FORMAT, SUPPRESS_LEADING, SUPPRESS_TRAILING, KEEP_ZEROS
     * @param aLeftDigits = number of digits for integer part of coordinates
     * @param aRightDigits = number of digits for mantissa part of coordinates
     */
    void SetFormat( bool aMetric, zeros_fmt aZerosFmt, int aLeftDigits, int aRightDigits );

    /**
179
     * Function SetOptions
180
     * Initialize internal parameters to match drill options
181 182 183
     * @param aMirror = true to create mirrored coordinates (Y coordinates negated)
     * @param aMinimalHeader = true to use a minimal header (no comments, no info)
     * @param aOffset = drill coordinates offset
184
     * @param aMergePTHNPTH : true to create only one list which contains both PTH and NPTH
185
     */
186
    void SetOptions( bool aMirror, bool aMinimalHeader, wxPoint aOffset, bool aMergePTHNPTH )
187 188 189 190
    {
        m_mirror = aMirror;
        m_offset = aOffset;
        m_minimalHeader = aMinimalHeader;
191
        m_mergePTHNPTH = aMergePTHNPTH;
192 193
    }

194 195 196 197 198 199 200 201 202 203 204 205
    /**
     * Function BuildHolesList
     * Create the list of holes and tools for a given board
     * The list is sorted by increasing drill values
     * Only holes from aFirstLayer to aLastLayer copper layers  are listed (for vias, because
     * pad holes are always through holes)
     * @param aFirstLayer = first layer to consider. if < 0 aFirstLayer is ignored
     * @param aLastLayer = last layer to consider. if < 0 aLastLayer is ignored
     * @param aExcludeThroughHoles Exclude through holes if true.
     * @param aGenerateNPTH_list :
     *       true to create NPTH only list (with no plated holes)
     *       false to created plated holes list (with no NPTH )
206
     * @param aMergePTHNPTH : true to create only one list which contains both PTH and NPTH
207 208
     */
    void BuildHolesList( int aFirstLayer, int aLastLayer,
Wayne Stambaugh's avatar
Wayne Stambaugh committed
209 210 211
                         bool aExcludeThroughHoles,
                         bool aGenerateNPTH_list,
                         bool aMergePTHNPTH );
212 213

    int  GetHolesCount() const { return m_holeListBuffer.size(); }
214 215

    /**
216
     * Function CreateDrillFile
217
     * Creates an Excellon drill file
Wayne Stambaugh's avatar
Wayne Stambaugh committed
218
     * @param aFile = an opened file to write to will be closed by CreateDrillFile
219 220
     * @return hole count
     */
221 222 223 224 225 226 227 228
    int  CreateDrillFile( FILE * aFile );

    /**
     * Function GenDrillReportFile
     *  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
Wayne Stambaugh's avatar
Wayne Stambaugh committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
     *
     * 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
     *
270 271 272 273 274 275
     * @param aFullFileName : the name of the file to create
     *  m_unitsDecimal = false tu use inches, true to use mm in report file
     *
     * @return success if the file is created
     */
    bool GenDrillReportFile( const wxString& aFullFileName );
276

277 278 279
    /**
     * Function GenDrillMapFile
     * Plot a map of drill marks for holes.
280
     * @param aFullFileNameWithoutExt : the full filename of the file to create,
Wayne Stambaugh's avatar
Wayne Stambaugh committed
281 282
     *              without extension (will be added according to the format)
     * @param aSheet : the paper sheet to use for plot
283 284
     * @param aFormat : one of the supported plot formats (see enum PlotFormat )
     */
285
    bool GenDrillMapFile( const wxString& aFullFileNameWithoutExt,
286 287
                          const PAGE_INFO& aSheet,
                          PlotFormat aFormat );
288
private:
Wayne Stambaugh's avatar
Wayne Stambaugh committed
289 290 291 292 293 294 295
    /* Print the DRILL file header. The full header is:
     * M48
     * ;DRILL file {PCBNEW (2007-11-29-b)} date 17/1/2008-21:02:35
     * ;FORMAT={ <precision> / absolute / <units> / <numbers format>}
     * FMAT,2
     * INCH,TZ
     */
296
    void WriteEXCELLONHeader();
Wayne Stambaugh's avatar
Wayne Stambaugh committed
297

298
    void WriteEXCELLONEndOfFile();
Wayne Stambaugh's avatar
Wayne Stambaugh committed
299 300 301 302 303

    /* Created a line like:
     * X48000Y19500
     * According to the selected format
     */
304 305
    void WriteCoordinates( char* aLine, double aCoordX, double aCoordY );

306 307 308 309 310 311 312 313
    /** Helper function.
     * Writes 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 = a PLOTTER instance (HPGL, POSTSCRIPT ... plotter).
     */
Wayne Stambaugh's avatar
Wayne Stambaugh committed
314
    bool PlotDrillMarks( PLOTTER* aPlotter );
315
};
dickelbeck's avatar
dickelbeck committed
316 317


318
#endif  //  #ifndef _GENDRILL_EXCELLON_WRITER_