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
/**
* @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-2012 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2012 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
public:
DRILL_TOOL( int diametre )
{
m_TotalCount = 0;
m_OvalCount = 0;
m_Diameter = diametre;
}
};
/* 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 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
public:
HOLE_INFO()
{
m_Hole_NotPlated = false;
}
};
/* 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;
}
};
/**
* 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,
SUPPRESS_LEADING,
SUPPRESS_TRAILING,
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_mergePTHNPTH;
std::vector<HOLE_INFO> m_holeListBuffer; // Buffer containing holes
std::vector<DRILL_TOOL> m_toolListBuffer; // Buffer containing tools
public:
EXCELLON_WRITER( BOARD* aPcb, wxPoint aOffset )
{
m_file = NULL;
m_pcb = aPcb;
m_zeroFormat = DECIMAL_FORMAT;
m_conversionUnits = 0.0001;
m_unitsDecimal = false;
m_mirror = false;
m_mergePTHNPTH = false;
m_minimalHeader = false;
}
~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
* @param aRightDigits = number of digits for mantissa part of coordinates
*/
void SetFormat( bool aMetric, zeros_fmt aZerosFmt, int aLeftDigits, int aRightDigits );
/**
* 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
* @param aMergePTHNPTH : true to create only one list which contains both PTH and NPTH
*/
void SetOptions( bool aMirror, bool aMinimalHeader, wxPoint aOffset, bool aMergePTHNPTH )
{
m_mirror = aMirror;
m_offset = aOffset;
m_minimalHeader = aMinimalHeader;
m_mergePTHNPTH = aMergePTHNPTH;
}
/**
* 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 )
* @param aMergePTHNPTH : true to create only one list which contains both PTH and NPTH
*/
void BuildHolesList( int aFirstLayer, int aLastLayer,
bool aExcludeThroughHoles,
bool aGenerateNPTH_list,
bool aMergePTHNPTH );
int GetHolesCount() const { return m_holeListBuffer.size(); }
/**
* 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 tu 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.
* @param aFullFileNameWithoutExt : the full filename of the file to create,
* without extension (will be added according to the format)
* @param aSheet : the paper sheet to use for plot
* @param aFormat : one of the supported plot formats (see enum PlotFormat )
*/
bool GenDrillMapFile( const wxString& aFullFileNameWithoutExt,
const PAGE_INFO& aSheet,
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 );
};
#endif // #ifndef _GENDRILL_EXCELLON_WRITER_