KiCad PCB EDA Suite
pcb_pad.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2007, 2008 Lubo Racko <developer@lura.sk>
5  * Copyright (C) 2007, 2008, 2012-2013 Alexander Lunev <al.lunev@yahoo.com>
6  * Copyright (C) 2012 KiCad Developers, see CHANGELOG.TXT for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
30 #include <wx/wx.h>
31 #include <trigo.h>
32 
33 #include <pcb_pad.h>
34 
35 namespace PCAD2KICAD {
36 
37 PCB_PAD::PCB_PAD( PCB_CALLBACKS* aCallbacks, BOARD* aBoard ) : PCB_COMPONENT( aCallbacks, aBoard )
38 {
39  m_objType = wxT( 'P' );
40  m_number = 0;
41  m_hole = 0;
42  m_isHolePlated = true;
43  m_defaultPinDes = wxEmptyString;
44 }
45 
46 
48 {
49  int i;
50 
51  for( i = 0; i < (int) m_shapes.GetCount(); i++ )
52  {
53  delete m_shapes[i];
54  }
55 }
56 
57 
58 void PCB_PAD::Parse( XNODE* aNode,
59  const wxString& aDefaultMeasurementUnit,
60  const wxString& aActualConversion )
61 {
62  XNODE* lNode, *cNode;
63  long num;
64  wxString propValue, str, emsg;
65  PCB_PAD_SHAPE* padShape;
66 
67  m_rotation = 0;
68  lNode = FindNode( aNode, wxT( "padNum" ) );
69 
70  if( lNode )
71  {
72  lNode->GetNodeContent().ToLong( &num );
73  m_number = (int) num;
74  }
75 
76  lNode = FindNode( aNode, wxT( "padStyleRef" ) );
77 
78  if( lNode )
79  {
80  lNode->GetAttribute( wxT( "Name" ), &propValue );
81  propValue.Trim( false );
82  m_name.text = propValue;
83  }
84 
85  lNode = FindNode( aNode, wxT( "pt" ) );
86 
87  if( lNode )
88  SetPosition( lNode->GetNodeContent(), aDefaultMeasurementUnit,
89  &m_positionX, &m_positionY, aActualConversion );
90 
91  lNode = FindNode( aNode, wxT( "rotation" ) );
92 
93  if( lNode )
94  {
95  str = lNode->GetNodeContent();
96  str.Trim( false );
97  m_rotation = StrToInt1Units( str );
98  }
99 
100  lNode = FindNode( aNode, wxT( "netNameRef" ) );
101 
102  if( lNode )
103  {
104  lNode->GetAttribute( wxT( "Name" ), &propValue );
105  propValue.Trim( false );
106  propValue.Trim( true );
107  m_net = propValue;
109  }
110 
111  lNode = FindNode( aNode, wxT( "defaultPinDes" ) );
112 
113  if( lNode )
114  {
115  lNode->GetAttribute( wxT( "Name" ), &propValue );
116  //propValue.Trim( false );
117  m_defaultPinDes = propValue;
118  }
119 
120  lNode = aNode;
121 
122  while( lNode && lNode->GetName() != wxT( "www.lura.sk" ) )
123  lNode = lNode->GetParent();
124 
125  lNode = FindNode( lNode, wxT( "library" ) );
126  if ( !lNode )
127  THROW_IO_ERROR( wxT( "Unable to find library section" ) );
128 
129  lNode = FindNode( lNode, wxT( "padStyleDef" ) );
130 
131  while( lNode )
132  {
133  lNode->GetAttribute( wxT( "Name" ), &propValue );
134 
135  if( propValue.IsSameAs( m_name.text, false) )
136  break;
137 
138  lNode = lNode->GetNext();
139  }
140 
141  if ( !lNode )
142  THROW_IO_ERROR( wxString::Format( wxT( "Unable to find padStyleDef " ) + m_name.text ) );
143 
144  cNode = FindNode( lNode, wxT( "holeDiam" ) );
145 
146  if( cNode )
147  SetWidth( cNode->GetNodeContent(), aDefaultMeasurementUnit, &m_hole, aActualConversion );
148 
149  if( FindNodeGetContent( lNode, wxT( "isHolePlated" ) ) == wxT( "False" ) )
150  m_isHolePlated = false;
151 
152  cNode = FindNode( lNode, wxT( "padShape" ) );
153 
154  while( cNode )
155  {
156  if( cNode->GetName() == wxT( "padShape" ) )
157  {
158  // we support only Pads on specific layers......
159  // we do not support pads on "Plane", "NonSignal" , "Signal" ... layerr
160  if( FindNode( cNode, wxT( "layerNumRef" ) ) )
161  {
162  padShape = new PCB_PAD_SHAPE( m_callbacks, m_board );
163  padShape->Parse( cNode, aDefaultMeasurementUnit, aActualConversion );
164  m_shapes.Add( padShape );
165  }
166  }
167 
168  cNode = cNode->GetNext();
169  }
170 }
171 
172 
174 {
175  int i;
176 
178 
179  if( m_objType == wxT( 'P' ) )
181 
182  for( i = 0; i < (int)m_shapes.GetCount(); i++ )
184 }
185 
186 
187 void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad )
188 {
189  PCB_PAD_SHAPE* padShape;
190  wxString padShapeName = wxT( "Ellipse" );
191  PAD_ATTR_T padType;
192  int i;
193  int width = 0;
194  int height = 0;
195 
196  D_PAD* pad = new D_PAD( aModule );
197 
198  if( !m_isHolePlated && m_hole )
199  {
200  // mechanical hole
201  pad->SetShape( PAD_SHAPE_CIRCLE );
203 
205  pad->SetDrillSize( wxSize( m_hole, m_hole ) );
206  pad->SetSize( wxSize( m_hole, m_hole ) );
207 
208  // Mounting Hole: Solder Mask Margin from Top Layer Width size.
209  // Used the default zone clearance (simplify)
210  if( m_shapes.GetCount() && m_shapes[0]->m_shape == wxT( "MtHole" ) )
211  {
212  int sm_margin = ( m_shapes[0]->m_width - m_hole ) / 2;
213  pad->SetLocalSolderMaskMargin( sm_margin );
214  pad->SetLocalClearance( sm_margin + Millimeter2iu( 0.254 ) );
215  }
216 
217  pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
218  }
219  else
220  {
221  ( m_hole ) ? padType = PAD_ATTRIB_PTH : padType = PAD_ATTRIB_SMD;
222 
223  // form layer mask
224  for( i = 0; i < (int) m_shapes.GetCount(); i++ )
225  {
226  padShape = m_shapes[i];
227 
228  if( padShape->m_width > 0 && padShape->m_height > 0 )
229  {
230  if( padShape->m_KiCadLayer == F_Cu ||
231  padShape->m_KiCadLayer == B_Cu )
232  {
233  padShapeName = padShape->m_shape;
234  width = padShape->m_width;
235  height = padShape->m_height;
236 
237  // assume this is SMD pad
238  if( padShape->m_KiCadLayer == F_Cu )
239  pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
240  else
241  pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
242  break;
243  }
244  }
245  }
246 
247  if( width == 0 || height == 0 )
248  {
249  delete pad;
250  return;
251  }
252 
253  if( padType == PAD_ATTRIB_PTH )
254  // actually this is a thru-hole pad
255  pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
256 
257  pad->SetName( m_name.text );
258 
259  if( padShapeName == wxT( "Oval" )
260  || padShapeName == wxT( "Ellipse" )
261  || padShapeName == wxT( "MtHole" ) )
262  {
263  if( width != height )
264  pad->SetShape( PAD_SHAPE_OVAL );
265  else
266  pad->SetShape( PAD_SHAPE_CIRCLE );
267  }
268  else if( padShapeName == wxT( "Rect" ) )
269  pad->SetShape( PAD_SHAPE_RECT );
270  else if( padShapeName == wxT( "RndRect" ) )
272  else if( padShapeName == wxT( "Polygon" ) )
273  pad->SetShape( PAD_SHAPE_RECT ); // approximation
274 
275  pad->SetSize( wxSize( width, height ) );
276  pad->SetDelta( wxSize( 0, 0 ) );
277  pad->SetOrientation( m_rotation + aRotation );
278 
280  pad->SetOffset( wxPoint( 0, 0 ) );
281  pad->SetDrillSize( wxSize( m_hole, m_hole ) );
282 
283  pad->SetAttribute( padType );
284 
285  // Set the proper net code
286  NETINFO_ITEM* netinfo = m_board->FindNet( m_net );
287  if( netinfo == NULL ) // I believe this should not happen, but just in case
288  {
289  // It is a new net
290  netinfo = new NETINFO_ITEM( m_board, m_net );
291  m_board->Add( netinfo );
292  }
293 
294  pad->SetNetCode( netinfo->GetNet() );
295  }
296 
297  if( !aEncapsulatedPad )
298  {
299  // pad's "Position" is not relative to the module's,
300  // whereas Pos0 is relative to the module's but is the unrotated coordinate.
301  wxPoint padpos( m_positionX, m_positionY );
302  pad->SetPos0( padpos );
303  RotatePoint( &padpos, aModule->GetOrientation() );
304  pad->SetPosition( padpos + aModule->GetPosition() );
305  }
306 
307  aModule->Add( pad );
308 }
309 
310 
312 {
313  PCB_PAD_SHAPE* padShape;
314  int i;
315  int width = 0;
316  int height = 0;
317 
318  if( m_objType == wxT( 'V' ) ) // via
319  {
320  // choose one of the shapes
321  for( i = 0; i < (int) m_shapes.GetCount(); i++ )
322  {
323  padShape = m_shapes[i];
324 
325  if( padShape->m_width > 0 && padShape->m_height > 0 )
326  {
327  if( padShape->m_KiCadLayer == F_Cu
328  || padShape->m_KiCadLayer == B_Cu )
329  {
330  width = padShape->m_width;
331  height = padShape->m_height;
332 
333  break;
334  }
335  }
336  }
337 
338  if( width == 0 || height == 0 )
339  return;
340 
341  if( IsCopperLayer( m_KiCadLayer ) )
342  {
343  VIA* via = new VIA( m_board );
344  m_board->Add( via );
345 
346  via->SetPosition( wxPoint( m_positionX, m_positionY ) );
347  via->SetEnd( wxPoint( m_positionX, m_positionY ) );
348 
349  via->SetWidth( height );
351  via->SetLayerPair( F_Cu, B_Cu );
352  via->SetDrill( m_hole );
353 
354  via->SetLayer( m_KiCadLayer );
355  via->SetNetCode( m_netCode );
356  }
357  }
358  else // pad
359  {
360  MODULE* module = new MODULE( m_board );
361  m_board->Add( module, ADD_MODE::APPEND );
362 
364 
365  module->SetPosition( wxPoint( m_positionX, m_positionY ) );
366  AddToModule( module, 0, true );
367 
368  }
369 }
370 
371 } // namespace PCAD2KICAD
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
double GetOrientation() const
Definition: class_module.h:206
PAD_ATTR_T
Enum PAD_ATTR_T is the set of pad shapes, used with D_PAD::{Set,Get}Attribute() The double name is fo...
Definition: pad_shapes.h:78
void SetPosition(const wxPoint &aPoint) override
Definition: class_track.h:424
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
void SetPosition(wxString aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, const wxString &aActualConversion)
void SetEnd(const wxPoint &aEnd)
Definition: class_track.h:112
void AddToBoard() override
Definition: pcb_pad.cpp:311
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:520
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
virtual void Parse(XNODE *aNode, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
bool SetNetCode(int aNetCode, bool aNoAssert)
Sets net using a net code.
void SetWidth(wxString aStr, const wxString &aDefaultMeasurementUnit, int *aWidth, const wxString &aActualConversion)
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:166
PCB_PAD(PCB_CALLBACKS *aCallbacks, BOARD *aBoard)
Definition: pcb_pad.cpp:37
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:240
virtual void Parse(XNODE *aNode, const wxString &aDefaultMeasurementUnit, const wxString &aActualConversion)
Definition: pcb_pad.cpp:58
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
void AddToModule(MODULE *aModule) override
Definition: pcb_pad.h:55
void SetWidth(int aWidth)
Definition: class_track.h:109
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
LSET is a set of PCB_LAYER_IDs.
#define NULL
void SetName(const wxString &aName)
Set the pad name (sometimes called pad number, although it can be an array reference like AA12).
Definition: class_pad.h:131
XNODE * GetParent() const
Definition: xnode.h:73
void SetPos0(const wxPoint &aPos)
Definition: class_pad.h:224
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
wxString m_defaultPinDes
Definition: pcb_pad.h:63
void SetSize(const wxSize &aSize)
Definition: class_pad.h:230
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer.
void SetPosition(const wxPoint &aPos) override
virtual void Flip() override
Definition: pcb_pad.cpp:173
void SetAttribute(PAD_ATTR_T aAttribute)
Definition: class_pad.cpp:512
void SetLocalClearance(int aClearance)
Definition: class_pad.h:369
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
XNODE holds an XML or S-expression element.
Definition: xnode.h:43
void SetDrillShape(PAD_DRILL_SHAPE_T aShape)
Definition: class_pad.h:342
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
XNODE * GetNext() const
Definition: xnode.h:68
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:201
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
void SetLocalSolderMaskMargin(int aMargin)
Definition: class_pad.h:365
Plated through hole pad.
Definition: pad_shapes.h:80
void SetDrill(int aDrill)
Function SetDrill sets the drill value for vias.
Definition: class_track.h:486
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
void SetShape(PAD_SHAPE_T aShape)
Set the new shape of this pad.
Definition: class_pad.h:155
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:531
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
PCB_CALLBACKS * m_callbacks
Definition: pcb_component.h:75
PCB_PAD_SHAPES_ARRAY m_shapes
Definition: pcb_pad.h:46
int GetNetCode(wxString aNetName)
Definition: pcb_component.h:72
wxPoint GetPosition() const override
Definition: class_module.h:201
void SetOffset(const wxPoint &aOffset)
Definition: class_pad.h:247
void SetViaType(VIATYPE aViaType)
Definition: class_track.h:385
static constexpr int Millimeter2iu(double mm)
int StrToInt1Units(const wxString &aStr)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void SetLayerSet(LSET aLayers) override
Definition: class_pad.h:348
void SetDelta(const wxSize &aSize)
Definition: class_pad.h:237