1 /*!
2  * \file src/drill.c
3  *
4  * \brief .
5  *
6  * <hr>
7  *
8  * <h1><b>Copyright.</b></h1>\n
9  *
10  * PCB, interactive printed circuit board design
11  *
12  * Copyright (C) 1994,1995,1996 Thomas Nau
13  *
14  * This module, drill.c, was written and is Copyright (C) 1997 harry eaton
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  *
30  * Contact addresses for paper mail and Email:
31  * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32  * Thomas.Nau@rz.uni-ulm.de
33  */
34 
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #include "data.h"
40 #include "error.h"
41 #include "mymem.h"
42 
43 #ifdef HAVE_LIBDMALLOC
44 #include <dmalloc.h>
45 #endif
46 
47 /*
48  * some local prototypes
49  */
50 static void FillDrill (DrillType *, ElementType *, PinType *);
51 static void InitializeDrill (DrillType *, PinType *, ElementType *);
52 
53 
54 static void
FillDrill(DrillType * Drill,ElementType * Element,PinType * Pin)55 FillDrill (DrillType *Drill, ElementType *Element, PinType *Pin)
56 {
57   Cardinal n;
58   ElementType **ptr;
59   PinType **pin;
60 
61   pin = GetDrillPinMemory (Drill);
62   *pin = Pin;
63   if (Element)
64     {
65       Drill->PinCount++;
66       for (n = Drill->ElementN - 1; n != -1; n--)
67 	if (Drill->Element[n] == Element)
68 	  break;
69       if (n == -1)
70 	{
71 	  ptr = GetDrillElementMemory (Drill);
72 	  *ptr = Element;
73 	}
74     }
75   else
76     Drill->ViaCount++;
77   if (TEST_FLAG (HOLEFLAG, Pin))
78     Drill->UnplatedCount++;
79 }
80 
81 static void
InitializeDrill(DrillType * drill,PinType * pin,ElementType * element)82 InitializeDrill (DrillType *drill, PinType *pin, ElementType *element)
83 {
84   void *ptr;
85 
86   drill->DrillSize = pin->DrillingHole;
87   drill->ElementN = 0;
88   drill->ViaCount = 0;
89   drill->PinCount = 0;
90   drill->UnplatedCount = 0;
91   drill->ElementMax = 0;
92   drill->Element = NULL;
93   drill->PinN = 0;
94   drill->Pin = NULL;
95   drill->PinMax = 0;
96   ptr = (void *) GetDrillPinMemory (drill);
97   *((PinType **) ptr) = pin;
98   if (element)
99     {
100       ptr = (void *) GetDrillElementMemory (drill);
101       *((ElementType **) ptr) = element;
102       drill->PinCount = 1;
103     }
104   else
105     drill->ViaCount = 1;
106   if (TEST_FLAG (HOLEFLAG, pin))
107     drill->UnplatedCount = 1;
108 }
109 
110 static int
DrillQSort(const void * va,const void * vb)111 DrillQSort (const void *va, const void *vb)
112 {
113   DrillType *a = (DrillType *) va;
114   DrillType *b = (DrillType *) vb;
115   return a->DrillSize - b->DrillSize;
116 }
117 
118 DrillInfoType *
GetDrillInfo(DataType * top)119 GetDrillInfo (DataType *top)
120 {
121   DrillInfoType *AllDrills;
122   DrillType *Drill = NULL;
123   DrillType savedrill, swapdrill;
124   bool DrillFound = false;
125   bool NewDrill;
126 
127   AllDrills = (DrillInfoType *)calloc (1, sizeof (DrillInfoType));
128   ALLPIN_LOOP (top);
129   {
130     if (!DrillFound)
131       {
132 	DrillFound = true;
133 	Drill = GetDrillInfoDrillMemory (AllDrills);
134 	InitializeDrill (Drill, pin, element);
135       }
136     else
137       {
138 	if (Drill->DrillSize == pin->DrillingHole)
139 	  FillDrill (Drill, element, pin);
140 	else
141 	  {
142 	    NewDrill = false;
143 	    DRILL_LOOP (AllDrills);
144 	    {
145 	      if (drill->DrillSize == pin->DrillingHole)
146 		{
147 		  Drill = drill;
148 		  FillDrill (Drill, element, pin);
149 		  break;
150 		}
151 	      else if (drill->DrillSize > pin->DrillingHole)
152 		{
153 		  if (!NewDrill)
154 		    {
155 		      NewDrill = true;
156 		      InitializeDrill (&swapdrill, pin, element);
157 		      Drill = GetDrillInfoDrillMemory (AllDrills);
158 		      Drill->DrillSize = pin->DrillingHole + 1;
159 		      Drill = drill;
160 		    }
161 		  savedrill = *drill;
162 		  *drill = swapdrill;
163 		  swapdrill = savedrill;
164 		}
165 	    }
166 	    END_LOOP;
167 	    if (AllDrills->Drill[AllDrills->DrillN - 1].DrillSize <
168 		pin->DrillingHole)
169 	      {
170 		Drill = GetDrillInfoDrillMemory (AllDrills);
171 		InitializeDrill (Drill, pin, element);
172 	      }
173 	  }
174       }
175   }
176   ENDALL_LOOP;
177   VIA_LOOP (top);
178   {
179     if (!DrillFound)
180       {
181 	DrillFound = true;
182 	Drill = GetDrillInfoDrillMemory (AllDrills);
183 	Drill->DrillSize = via->DrillingHole;
184 	FillDrill (Drill, NULL, via);
185       }
186     else
187       {
188 	if (Drill->DrillSize != via->DrillingHole)
189 	  {
190 	    DRILL_LOOP (AllDrills);
191 	    {
192 	      if (drill->DrillSize == via->DrillingHole)
193 		{
194 		  Drill = drill;
195 		  FillDrill (Drill, NULL, via);
196 		  break;
197 		}
198 	    }
199 	    END_LOOP;
200 	    if (Drill->DrillSize != via->DrillingHole)
201 	      {
202 		Drill = GetDrillInfoDrillMemory (AllDrills);
203 		Drill->DrillSize = via->DrillingHole;
204 		FillDrill (Drill, NULL, via);
205 	      }
206 	  }
207 	else
208 	  FillDrill (Drill, NULL, via);
209       }
210   }
211   END_LOOP;
212   qsort (AllDrills->Drill, AllDrills->DrillN, sizeof (DrillType), DrillQSort);
213   return (AllDrills);
214 }
215 
216 #define ROUND(x,n) ((int)(((x)+(n)/2)/(n))*(n))
217 
218 /*
219   Currently unused. Was used in ReportDrills() in report.c and in PrintFab()
220   in print.c (generation of the Gerber fab file), but not when generating the
221   actual CNC files, so the number of drills in the drill report and in the
222   CNC file could differ. This was confusing.
223 */
224 #if 0
225 /*!
226   \brief Join similar sized drill sets.
227 
228   \param d Set of all drills to look at, in subsets for each drill size.
229 
230   \param roundto Rounding error. Drills differing less than this value are
231   considered to be of the pame size and joined into a common set.
232 
233   \note In case of hits the number of drill sets changes, so the number of
234   distinct drill sizes changes as well. This can be confusing if
235   RoundDisplayInfo() is used for one kind of display/output, but not for others.
236 */
237 void
238 RoundDrillInfo (DrillInfoType *d, int roundto)
239 {
240   unsigned int i = 0;
241 
242   /* round in the case with only one drill, too */
243   if (d->DrillN == 1) {
244     d->Drill[0].DrillSize = ROUND (d->Drill[0].DrillSize, roundto);
245   }
246 
247   while ((d->DrillN > 0) && (i < d->DrillN - 1))
248     {
249       int diam1 = ROUND (d->Drill[i].DrillSize, roundto);
250       int diam2 = ROUND (d->Drill[i + 1].DrillSize, roundto);
251 
252       if (diam1 == diam2)
253 	{
254 	  int ei, ej;
255 
256 	  d->Drill[i].ElementMax
257 	    = d->Drill[i].ElementN + d->Drill[i+1].ElementN;
258 	  if (d->Drill[i].ElementMax)
259 	    {
260 	      d->Drill[i].Element = (ElementType **)realloc (d->Drill[i].Element,
261 					     d->Drill[i].ElementMax *
262 					     sizeof (ElementType *));
263 
264 	      for (ei = 0; ei < d->Drill[i+1].ElementN; ei++)
265 		{
266 		  for (ej = 0; ej < d->Drill[i].ElementN; ej++)
267 		    if (d->Drill[i].Element[ej] == d->Drill[i + 1].Element[ei])
268 		      break;
269 		  if (ej == d->Drill[i].ElementN)
270 		    d->Drill[i].Element[d->Drill[i].ElementN++]
271 		      = d->Drill[i + 1].Element[ei];
272 		}
273 	    }
274 	  free (d->Drill[i + 1].Element);
275 	  d->Drill[i + 1].Element = NULL;
276 
277 	  d->Drill[i].PinMax = d->Drill[i].PinN + d->Drill[i + 1].PinN;
278 	  d->Drill[i].Pin = (PinType **)realloc (d->Drill[i].Pin,
279 				     d->Drill[i].PinMax *
280 				     sizeof (PinType *));
281 	  memcpy (d->Drill[i].Pin + d->Drill[i].PinN, d->Drill[i + 1].Pin,
282 		  d->Drill[i + 1].PinN * sizeof (PinType *));
283 	  d->Drill[i].PinN += d->Drill[i + 1].PinN;
284 	  free (d->Drill[i + 1].Pin);
285 	  d->Drill[i + 1].Pin = NULL;
286 
287 	  d->Drill[i].PinCount += d->Drill[i + 1].PinCount;
288 	  d->Drill[i].ViaCount += d->Drill[i + 1].ViaCount;
289 	  d->Drill[i].UnplatedCount += d->Drill[i + 1].UnplatedCount;
290 
291 	  d->Drill[i].DrillSize = diam1;
292 
293 	  memmove (d->Drill + i + 1,
294 		   d->Drill + i + 2,
295 		   (d->DrillN - i - 2) * sizeof (DrillType));
296 	  d->DrillN--;
297 	}
298       else
299 	{
300 	  d->Drill[i].DrillSize = diam1;
301 	  i++;
302 	}
303     }
304 }
305 #endif
306 
307 void
FreeDrillInfo(DrillInfoType * Drills)308 FreeDrillInfo (DrillInfoType *Drills)
309 {
310   DRILL_LOOP (Drills);
311   {
312     free (drill->Element);
313     free (drill->Pin);
314   }
315   END_LOOP;
316   free (Drills->Drill);
317   free (Drills);
318 }
319