KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcad_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-2023 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/pcad_pad.h>
27#include <pcad/pcad_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
41PCAD_PAD::PCAD_PAD( PCAD_CALLBACKS* aCallbacks, BOARD* aBoard ) :
42 PCAD_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 PCAD_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 PCAD_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 PCAD_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++ )
190 m_Shapes[i]->m_KiCadLayer = m_board->FlipLayer( m_Shapes[i]->m_KiCadLayer );
191}
192
193
194void PCAD_PAD::AddToFootprint( FOOTPRINT* aFootprint, const EDA_ANGLE& aRotation,
195 bool aEncapsulatedPad )
196{
197 PCAD_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( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
210 pad->SetAttribute( PAD_ATTRIB::NPTH );
211
212 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
213 pad->SetDrillSize( VECTOR2I( 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( { 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( { F_Cu, F_Paste, F_Mask } ) );
248 else
249 pad->SetLayerSet( LSET( { 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( { 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( PADSTACK::ALL_LAYERS, PAD_SHAPE::OVAL );
274 else
275 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
276 }
277 else if( padShapeName.IsSameAs( wxT( "Rect" ), false ) )
278 {
279 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE );
280 }
281 else if( padShapeName.IsSameAs( wxT( "RndRect" ), false ) )
282 {
283 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
284 }
285 else if( padShapeName.IsSameAs( wxT( "Polygon" ), false ) )
286 {
287 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE ); // approximation
288 }
289
290 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( width, height ) );
291 pad->SetDelta( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
292 pad->SetOrientation( m_Rotation + aRotation );
293
294 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
295 pad->SetOffset( PADSTACK::ALL_LAYERS, 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 {
316 RotatePoint( padpos, aFootprint->GetOrientation() );
317 pad->SetPosition( padpos + aFootprint->GetPosition() );
318 }
319
320 aFootprint->Add( pad );
321}
322
323
325{
326 PCAD_PAD_SHAPE* padShape;
327 int i;
328 int width = 0;
329 int height = 0;
330
331 if( m_ObjType == wxT( 'V' ) ) // via
332 {
333 // choose one of the shapes
334 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
335 {
336 padShape = m_Shapes[i];
337
338 if( padShape->m_Width > 0 && padShape->m_Height > 0 )
339 {
340 if( padShape->m_KiCadLayer == F_Cu
341 || padShape->m_KiCadLayer == B_Cu )
342 {
343 width = padShape->m_Width;
344 height = padShape->m_Height;
345
346 break;
347 }
348 }
349 }
350
351 if( width == 0 || height == 0 )
352 return;
353
355 {
356 PCB_VIA* via = new PCB_VIA( m_board );
357 m_board->Add( via );
358
359 via->SetPosition( VECTOR2I( m_PositionX, m_PositionY ) );
360 via->SetEnd( VECTOR2I( m_PositionX, m_PositionY ) );
361
362 via->SetWidth( PADSTACK::ALL_LAYERS, height );
363 via->SetViaType( VIATYPE::THROUGH );
364 via->SetLayerPair( F_Cu, B_Cu );
365 via->SetDrill( m_Hole );
366
367 via->SetLayer( m_KiCadLayer );
368 via->SetNetCode( m_NetCode );
369 }
370 }
371 else // pad
372 {
373 if( !aFootprint )
374 {
375 aFootprint = new FOOTPRINT( m_board );
376 m_board->Add( aFootprint, ADD_MODE::APPEND );
377 aFootprint->SetPosition( VECTOR2I( m_PositionX, m_PositionY ) );
378 }
379
381
382 AddToFootprint( aFootprint, ANGLE_0, true );
383 }
384}
385
386} // namespace PCAD2KICAD
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:290
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: board.cpp:1000
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
Definition: board.cpp:1918
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayer) const
Definition: board.cpp:732
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2341
EDA_ANGLE GetOrientation() const
Definition: footprint.h:227
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition: footprint.cpp:982
VECTOR2I GetPosition() const override
Definition: footprint.h:224
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:36
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
Handle the data for a net.
Definition: netinfo.h:56
int GetNetCode() const
Definition: netinfo.h:108
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition: padstack.h:144
Definition: pad.h:54
virtual void Parse(XNODE *aNode, const wxString &aDefaultUnits, const wxString &aActualConversion)
void AddToFootprint(FOOTPRINT *aFootprint, const EDA_ANGLE &aRotation, bool aEncapsulatedPad)
Definition: pcad_pad.cpp:194
PCAD_PAD_SHAPES_ARRAY m_Shapes
Definition: pcad_pad.h:57
PCAD_PAD(PCAD_CALLBACKS *aCallbacks, BOARD *aBoard)
Definition: pcad_pad.cpp:41
void AddToBoard(FOOTPRINT *aFootprint=nullptr) override
Definition: pcad_pad.cpp:324
virtual void Flip() override
Definition: pcad_pad.cpp:180
wxString m_defaultPinDes
Definition: pcad_pad.h:60
virtual void Parse(XNODE *aNode, const wxString &aDefaultUnits, const wxString &aActualConversion)
Definition: pcad_pad.cpp:61
int GetNetCode(const wxString &aNetName) const
Hold an XML or S-expression element.
Definition: xnode.h:43
XNODE * GetParent() const
Definition: xnode.h:71
XNODE * GetNext() const
Definition: xnode.h:66
static constexpr EDA_ANGLE ANGLE_0
Definition: eda_angle.h:401
@ TENTHS_OF_A_DEGREE_T
Definition: eda_angle.h:30
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
Definition: layer_ids.h:531
@ F_Paste
Definition: layer_ids.h:104
@ B_Mask
Definition: layer_ids.h:98
@ B_Cu
Definition: layer_ids.h:65
@ F_Mask
Definition: layer_ids.h:97
@ B_Paste
Definition: layer_ids.h:105
@ F_Cu
Definition: layer_ids.h:64
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: padstack.h:81
constexpr int mmToIU(double mm) const
Definition: base_units.h:88
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691