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 <[email protected]>
5 * Copyright (C) 2007, 2008, 2012-2013 Alexander Lunev <[email protected]>
6 * Copyright (C) 2012-2022 KiCad Developers, see AUTHORS.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
26#include <pcad/pcb_pad.h>
27#include <pcad/pcb_pad_shape.h>
28
29#include <board.h>
30#include <footprint.h>
31#include <pad.h>
32#include <pcb_track.h>
33#include <trigo.h>
34#include <xnode.h>
35
36#include <wx/string.h>
37
38namespace PCAD2KICAD {
39
40
41PCB_PAD::PCB_PAD( PCB_CALLBACKS* aCallbacks, BOARD* aBoard ) :
42 PCB_COMPONENT( aCallbacks, aBoard )
43{
44 m_objType = wxT( 'P' );
45 m_Number = 0;
46 m_Hole = 0;
47 m_IsHolePlated = true;
48 m_defaultPinDes = wxEmptyString;
49}
50
51
53{
54 int i;
55
56 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
57 delete m_Shapes[i];
58}
59
60
61void PCB_PAD::Parse( XNODE* aNode, const wxString& aDefaultUnits,
62 const wxString& aActualConversion )
63{
64 XNODE* lNode;
65 XNODE* cNode;
66 long num;
67 wxString propValue, str, emsg;
68 PCB_PAD_SHAPE* padShape;
69
71 lNode = FindNode( aNode, wxT( "padNum" ) );
72
73 if( lNode )
74 {
75 lNode->GetNodeContent().ToLong( &num );
76 m_Number = (int) num;
77 }
78
79 lNode = FindNode( aNode, wxT( "padStyleRef" ) );
80
81 if( lNode )
82 {
83 lNode->GetAttribute( wxT( "Name" ), &propValue );
84 propValue.Trim( false );
85 m_name.text = propValue;
86 }
87
88 lNode = FindNode( aNode, wxT( "pt" ) );
89
90 if( lNode )
91 {
92 SetPosition( lNode->GetNodeContent(), aDefaultUnits, &m_positionX, &m_positionY,
93 aActualConversion );
94 }
95
96 lNode = FindNode( aNode, wxT( "rotation" ) );
97
98 if( lNode )
99 {
100 str = lNode->GetNodeContent();
101 str.Trim( false );
103 }
104
105 lNode = FindNode( aNode, wxT( "netNameRef" ) );
106
107 if( lNode )
108 {
109 lNode->GetAttribute( wxT( "Name" ), &propValue );
110 propValue.Trim( false );
111 propValue.Trim( true );
112 m_net = propValue;
114 }
115
116 lNode = FindNode( aNode, wxT( "defaultPinDes" ) );
117
118 if( lNode )
119 {
120 lNode->GetAttribute( wxT( "Name" ), &propValue );
121
122 //propValue.Trim( false );
123 m_defaultPinDes = propValue;
124 }
125
126 lNode = aNode;
127
128 while( lNode && lNode->GetName() != wxT( "www.lura.sk" ) )
129 lNode = lNode->GetParent();
130
131 lNode = FindNode( lNode, wxT( "library" ) );
132
133 if ( !lNode )
134 THROW_IO_ERROR( wxT( "Unable to find library section" ) );
135
136 lNode = FindNode( lNode, wxT( "padStyleDef" ) );
137
138 while( lNode )
139 {
140 lNode->GetAttribute( wxT( "Name" ), &propValue );
141
142 if( propValue.IsSameAs( m_name.text, false) )
143 break;
144
145 lNode = lNode->GetNext();
146 }
147
148 if ( !lNode )
149 THROW_IO_ERROR( wxString::Format( wxT( "Unable to find padStyleDef " ) + m_name.text ) );
150
151 cNode = FindNode( lNode, wxT( "holeDiam" ) );
152
153 if( cNode )
154 SetWidth( cNode->GetNodeContent(), aDefaultUnits, &m_Hole, aActualConversion );
155
156 if( FindNodeGetContent( lNode, wxT( "isHolePlated" ) ).IsSameAs( wxT( "False" ), false ) )
157 m_IsHolePlated = false;
158
159 cNode = FindNode( lNode, wxT( "padShape" ) );
160
161 while( cNode )
162 {
163 if( cNode->GetName().IsSameAs( wxT( "padShape" ), false ) )
164 {
165 // we support only Pads on specific layers......
166 // we do not support pads on "Plane", "NonSignal" , "Signal" ... layerr
167 if( FindNode( cNode, wxT( "layerNumRef" ) ) )
168 {
169 padShape = new PCB_PAD_SHAPE( m_callbacks, m_board );
170 padShape->Parse( cNode, aDefaultUnits, aActualConversion );
171 m_Shapes.Add( padShape );
172 }
173 }
174
175 cNode = cNode->GetNext();
176 }
177}
178
179
181{
182 int i;
183
185
186 if( m_objType == wxT( 'P' ) )
188
189 for( i = 0; i < (int)m_Shapes.GetCount(); i++ )
191}
192
193
194void PCB_PAD::AddToFootprint( FOOTPRINT* aFootprint, const EDA_ANGLE& aRotation,
195 bool aEncapsulatedPad )
196{
197 PCB_PAD_SHAPE* padShape;
198 wxString padShapeName = wxT( "Ellipse" );
199 PAD_ATTRIB padType;
200 int i;
201 int width = 0;
202 int height = 0;
203
204 PAD* pad = new PAD( aFootprint );
205
206 if( !m_IsHolePlated && m_Hole )
207 {
208 // mechanical hole
209 pad->SetShape( PAD_SHAPE::CIRCLE );
210 pad->SetAttribute( PAD_ATTRIB::NPTH );
211
212 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
213 pad->SetDrillSize( wxSize( m_Hole, m_Hole ) );
214 pad->SetSize( wxSize( m_Hole, m_Hole ) );
215
216 // Mounting Hole: Solder Mask Margin from Top Layer Width size.
217 // Used the default zone clearance (simplify)
218 if( m_Shapes.GetCount() && m_Shapes[0]->m_Shape.IsSameAs( wxT( "MtHole" ), false ) )
219 {
220 int sm_margin = ( m_Shapes[0]->m_Width - m_Hole ) / 2;
221 pad->SetLocalSolderMaskMargin( sm_margin );
222 pad->SetLocalClearance( sm_margin + pcbIUScale.mmToIU( 0.254 ) );
223 }
224
225 pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
226 }
227 else
228 {
229 ( m_Hole ) ? padType = PAD_ATTRIB::PTH : padType = PAD_ATTRIB::SMD;
230
231 // form layer mask
232 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
233 {
234 padShape = m_Shapes[i];
235
236 if( padShape->m_Width > 0 && padShape->m_Height > 0 )
237 {
238 if( padShape->m_KiCadLayer == F_Cu ||
239 padShape->m_KiCadLayer == B_Cu )
240 {
241 padShapeName = padShape->m_Shape;
242 width = padShape->m_Width;
243 height = padShape->m_Height;
244
245 // assume this is SMD pad
246 if( padShape->m_KiCadLayer == F_Cu )
247 pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
248 else
249 pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
250
251 break;
252 }
253 }
254 }
255
256 if( width == 0 || height == 0 )
257 {
258 delete pad;
259 return;
260 }
261
262 if( padType == PAD_ATTRIB::PTH )
263 // actually this is a thru-hole pad
264 pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
265
266 pad->SetNumber( m_name.text );
267
268 if( padShapeName.IsSameAs( wxT( "Oval" ), false )
269 || padShapeName.IsSameAs( wxT( "Ellipse" ), false )
270 || padShapeName.IsSameAs( wxT( "MtHole" ), false ) )
271 {
272 if( width != height )
273 pad->SetShape( PAD_SHAPE::OVAL );
274 else
275 pad->SetShape( PAD_SHAPE::CIRCLE );
276 }
277 else if( padShapeName.IsSameAs( wxT( "Rect" ), false ) )
278 {
279 pad->SetShape( PAD_SHAPE::RECT );
280 }
281 else if( padShapeName.IsSameAs( wxT( "RndRect" ), false ) )
282 {
283 pad->SetShape( PAD_SHAPE::ROUNDRECT );
284 }
285 else if( padShapeName.IsSameAs( wxT( "Polygon" ), false ) )
286 {
287 pad->SetShape( PAD_SHAPE::RECT ); // approximation
288 }
289
290 pad->SetSize( VECTOR2I( width, height ) );
291 pad->SetDelta( VECTOR2I( 0, 0 ) );
292 pad->SetOrientation( m_rotation + aRotation );
293
294 pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
295 pad->SetOffset( VECTOR2I( 0, 0 ) );
296 pad->SetDrillSize( VECTOR2I( m_Hole, m_Hole ) );
297
298 pad->SetAttribute( padType );
299
300 // Set the proper net code
301 NETINFO_ITEM* netinfo = m_board->FindNet( m_net );
302
303 if( netinfo == nullptr ) // I believe this should not happen, but just in case
304 {
305 // It is a new net
306 netinfo = new NETINFO_ITEM( m_board, m_net );
307 m_board->Add( netinfo );
308 }
309
310 pad->SetNetCode( netinfo->GetNetCode() );
311 }
312
313 if( !aEncapsulatedPad )
314 {
315 // pad's "Position" is not relative to the footprint's, whereas Pos0 is relative to
316 // the footprint's but is the unrotated coordinate.
318 pad->SetPos0( padpos );
319 RotatePoint( padpos, aFootprint->GetOrientation() );
320 pad->SetPosition( padpos + aFootprint->GetPosition() );
321 }
322
323 aFootprint->Add( pad );
324}
325
326
328{
329 PCB_PAD_SHAPE* padShape;
330 int i;
331 int width = 0;
332 int height = 0;
333
334 if( m_objType == wxT( 'V' ) ) // via
335 {
336 // choose one of the shapes
337 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
338 {
339 padShape = m_Shapes[i];
340
341 if( padShape->m_Width > 0 && padShape->m_Height > 0 )
342 {
343 if( padShape->m_KiCadLayer == F_Cu
344 || padShape->m_KiCadLayer == B_Cu )
345 {
346 width = padShape->m_Width;
347 height = padShape->m_Height;
348
349 break;
350 }
351 }
352 }
353
354 if( width == 0 || height == 0 )
355 return;
356
358 {
359 PCB_VIA* via = new PCB_VIA( m_board );
360 m_board->Add( via );
361
362 via->SetPosition( VECTOR2I( m_positionX, m_positionY ) );
363 via->SetEnd( VECTOR2I( m_positionX, m_positionY ) );
364
365 via->SetWidth( height );
366 via->SetViaType( VIATYPE::THROUGH );
367 via->SetLayerPair( F_Cu, B_Cu );
368 via->SetDrill( m_Hole );
369
370 via->SetLayer( m_KiCadLayer );
371 via->SetNetCode( m_netCode );
372 }
373 }
374 else // pad
375 {
376 FOOTPRINT* footprint = new FOOTPRINT( m_board );
377 m_board->Add( footprint, ADD_MODE::APPEND );
378
380
382 AddToFootprint( footprint, ANGLE_0, true );
383 }
384}
385
386} // namespace PCAD2KICAD
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:711
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1417
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:1658
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:561
VECTOR2I GetPosition() const override
Definition: footprint.h:188
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
Handle the data for a net.
Definition: netinfo.h:66
int GetNetCode() const
Definition: netinfo.h:113
Definition: pad.h:59
int GetNetCode(const wxString &aNetName) const
Definition: pcb_component.h:58
PCB_CALLBACKS * m_callbacks
Definition: pcb_component.h:78
virtual void Parse(XNODE *aNode, const wxString &aDefaultUnits, const wxString &aActualConversion)
PCB_PAD(PCB_CALLBACKS *aCallbacks, BOARD *aBoard)
Definition: pcb_pad.cpp:41
wxString m_defaultPinDes
Definition: pcb_pad.h:64
void AddToBoard() override
Definition: pcb_pad.cpp:327
virtual void Parse(XNODE *aNode, const wxString &aDefaultUnits, const wxString &aActualConversion)
Definition: pcb_pad.cpp:61
PCB_PAD_SHAPES_ARRAY m_Shapes
Definition: pcb_pad.h:61
void AddToFootprint(FOOTPRINT *aFootprint) override
Definition: pcb_pad.h:49
virtual void Flip() override
Definition: pcb_pad.cpp:180
Hold an XML or S-expression element.
Definition: xnode.h:44
XNODE * GetParent() const
Definition: xnode.h:72
XNODE * GetNext() const
Definition: xnode.h:67
@ TENTHS_OF_A_DEGREE_T
Definition: eda_angle.h:30
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:412
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:825
@ F_Paste
Definition: layer_ids.h:101
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_Cu
Definition: layer_ids.h:64
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:544
int StrToInt1Units(const wxString &aStr)
void SetWidth(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aWidth, const wxString &aActualConversion)
XNODE * FindNode(XNODE *aChild, const wxString &aTag)
void SetPosition(const wxString &aStr, const wxString &aDefaultMeasurementUnit, int *aX, int *aY, const wxString &aActualConversion)
wxString FindNodeGetContent(XNODE *aChild, const wxString &aTag)
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:81
@ NPTH
like PAD_PTH, but not plated
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618