1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
|
/**
* @file gendrill_Excellon_writer.h
* @brief Classes used in drill files, map files and report files generation.
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2015 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2015 KiCad Developers, see change_log.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
*/
#ifndef _GENDRILL_EXCELLON_WRITER_
#define _GENDRILL_EXCELLON_WRITER_
#include <vector>
class BOARD;
class PLOTTER;
// 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
public:
DRILL_TOOL( int aDiameter, bool a_NotPlated )
{
m_TotalCount = 0;
m_OvalCount = 0;
m_Diameter = aDiameter;
m_Hole_NotPlated = a_NotPlated;
}
};
/* 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.
*/
class HOLE_INFO
{
public:
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 ending layer (usually back layer)
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
public:
HOLE_INFO()
{
m_Hole_NotPlated = false;
m_Hole_Diameter = 0;
m_Tool_Reference = 0;
m_Hole_Orient = 0.0;
m_Hole_Shape = 0;
m_Hole_Bottom_Layer = B_Cu;
m_Hole_Top_Layer = F_Cu;
}
};
/* the DRILL_PRECISION helper class to handle drill precision format in excellon files
*/
class DRILL_PRECISION
{
public:
int m_lhs; // Left digit number (integer value of coordinates)
int m_rhs; // Right digit number (decimal value of coordinates)
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;
}
};
typedef std::pair<LAYER_ID, LAYER_ID> LAYER_PAIR;
class OUTPUTFORMATTER;
/**
* 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
*/
class EXCELLON_WRITER
{
public:
enum ZEROS_FMT { // Zero format in coordinates
DECIMAL_FORMAT, // Floating point coordinates
SUPPRESS_LEADING, // Suppress leading zeros
SUPPRESS_TRAILING, // Suppress trainling zeros
KEEP_ZEROS // keep zeros
};
wxPoint m_Offset; // offset coordinates
bool m_ShortHeader; // true to generate the smallest header (strip comments)
private:
FILE* m_file; // The output file
BOARD* m_pcb;
bool m_minimalHeader; // True to use minimal header
// in excellon file (strip comments)
bool m_unitsDecimal; // true = decimal, 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 units
// (i.e inches or mm)
bool m_mirror;
wxPoint m_offset; // Drill offset coordinates
bool m_merge_PTH_NPTH; // True to generate only one drill file
std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
PlotFormat 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
public:
EXCELLON_WRITER( BOARD* aPcb );
~EXCELLON_WRITER()
{
}
/**
* Return the plot offset (usually the position
* of the auxiliary axis
*/
const wxPoint GetOffset() { return m_offset; }
/**
* Function SetFormat
* 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
* if <= 0 (default), a suitable value will be used, depending on units
* @param aRightDigits = number of digits for mantissa part of coordinates
* if <= 0 (default), a suitable value will be used, depending on units
*/
void SetFormat( bool aMetric, ZEROS_FMT aZerosFmt = DECIMAL_FORMAT,
int aLeftDigits = 0, int aRightDigits = 0 );
/**
* Sets the page info used to plot drill maps
* If NULL, a A4 page format will be used
* @param aPageInfo = a reference to the page info, usually used to plot/display the board
*/
void SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; }
/**
* Function SetMapFileFormat
* Initialize the format for the drill map file
* @param SetMapFileFormat = 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( PlotFormat aMapFmt ) { m_mapFileFmt = aMapFmt; }
/**
* Function SetOptions
* Initialize internal parameters to match drill options
* @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
*/
void SetOptions( bool aMirror, bool aMinimalHeader, wxPoint aOffset, bool aMerge_PTH_NPTH )
{
m_mirror = aMirror;
m_offset = aOffset;
m_minimalHeader = aMinimalHeader;
m_merge_PTH_NPTH = aMerge_PTH_NPTH;
}
/**
* Function BuildHolesList
* 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( LAYER_PAIR aLayerPair,
bool aGenerateNPTH_list );
int GetHolesCount() const { return m_holeListBuffer.size(); }
/**
* Function CreateDrillandMapFilesSet
* Creates the full set of Excellon drill file for the board
* filenames are computed from the board name, and layers id
* @param aPlotDirectory = the output folder
* @param aGenDrill = true to generate the EXCELLON drill file
* @param aGenMap = true to generate a drill map file
* @param aReporter = a REPORTER to return activity or any message (can be NULL)
*/
void CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
bool aGenDrill, bool aGenMap,
REPORTER * aReporter = NULL );
/**
* Function CreateDrillFile
* Creates an Excellon drill file
* @param aFile = an opened file to write to will be closed by CreateDrillFile
* @return hole count
*/
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
*
* 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 : the name of the file to create
* m_unitsDecimal = false to use inches, true to use mm in report file
*
* @return success if the file is created
*/
bool GenDrillReportFile( const wxString& aFullFileName );
/**
* Function GenDrillMapFile
* Plot a map of drill marks for holes.
* 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 : the full filename of the map file to create,
* @param aFormat : one of the supported plot formats (see enum PlotFormat )
*/
bool GenDrillMapFile( const wxString& aFullFileName, PlotFormat aFormat );
private:
/* 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
*/
void WriteEXCELLONHeader();
void WriteEXCELLONEndOfFile();
/* Created a line like:
* X48000Y19500
* According to the selected format
*/
void WriteCoordinates( char* aLine, double aCoordX, double aCoordY );
/** 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).
*/
bool PlotDrillMarks( PLOTTER* aPlotter );
/// Get unique layer pairs by examining the micro and blind_buried vias.
std::vector<LAYER_PAIR> getUniqueLayerPairs() const;
/**
* Function printToolSummary
* prints m_toolListBuffer[] tools to aOut and returns total hole count.
* @param aOut = the current OUTPUTFORMATTER to print summary
* @param aSummaryNPTH = true to print summary for NPTH, false for PTH
*/
unsigned printToolSummary( OUTPUTFORMATTER& aOut, bool aSummaryNPTH ) const;
const std::string layerPairName( LAYER_PAIR aPair ) const;
const std::string layerName( LAYER_ID aLayer ) const;
const wxString drillFileName( LAYER_PAIR aPair, bool aNPTH ) const;
};
#endif // #ifndef _GENDRILL_EXCELLON_WRITER_
|