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 The 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <pcad/pcad_pad.h>
23#include <pcad/pcad_pad_shape.h>
24
25#include <board.h>
26#include <footprint.h>
27#include <pad.h>
28#include <pcb_track.h>
29#include <trigo.h>
30#include <xnode.h>
31
32#include <wx/string.h>
33
34namespace PCAD2KICAD {
35
36
37PCAD_PAD::PCAD_PAD( PCAD_CALLBACKS* aCallbacks, BOARD* aBoard ) :
38 PCAD_PCB_COMPONENT( aCallbacks, aBoard )
39{
40 m_ObjType = wxT( 'P' );
41 m_Number = 0;
42 m_Hole = 0;
43 m_IsHolePlated = true;
44 m_defaultPinDes = wxEmptyString;
45}
46
47
49{
50 int i;
51
52 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
53 delete m_Shapes[i];
54}
55
56
57void PCAD_PAD::Parse( XNODE* aNode, const wxString& aDefaultUnits,
58 const wxString& aActualConversion )
59{
60 XNODE* lNode;
61 XNODE* cNode;
62 long num;
63 wxString propValue, str, emsg;
64 PCAD_PAD_SHAPE* padShape;
65
67 lNode = FindNode( aNode, wxT( "padNum" ) );
68
69 if( lNode )
70 {
71 lNode->GetNodeContent().ToLong( &num );
72 m_Number = (int) num;
73 }
74
75 lNode = FindNode( aNode, wxT( "padStyleRef" ) );
76
77 if( lNode )
78 {
79 lNode->GetAttribute( wxT( "Name" ), &propValue );
80 propValue.Trim( false );
81 m_Name.text = propValue;
82 }
83
84 lNode = FindNode( aNode, wxT( "pt" ) );
85
86 if( lNode )
87 {
88 SetPosition( lNode->GetNodeContent(), aDefaultUnits, &m_PositionX, &m_PositionY,
89 aActualConversion );
90 }
91
92 lNode = FindNode( aNode, wxT( "rotation" ) );
93
94 if( lNode )
95 {
96 str = lNode->GetNodeContent();
97 str.Trim( false );
99 }
100
101 lNode = FindNode( aNode, wxT( "netNameRef" ) );
102
103 if( lNode )
104 {
105 lNode->GetAttribute( wxT( "Name" ), &propValue );
106 propValue.Trim( false );
107 propValue.Trim( true );
108 m_Net = propValue;
110 }
111
112 lNode = FindNode( aNode, wxT( "defaultPinDes" ) );
113
114 if( lNode )
115 {
116 lNode->GetAttribute( wxT( "Name" ), &propValue );
117
118 //propValue.Trim( false );
119 m_defaultPinDes = propValue;
120 }
121
122 lNode = aNode;
123
124 while( lNode && lNode->GetName() != wxT( "www.lura.sk" ) )
125 lNode = lNode->GetParent();
126
127 lNode = FindNode( lNode, wxT( "library" ) );
128
129 if ( !lNode )
130 THROW_IO_ERROR( wxT( "Unable to find library section" ) );
131
132 lNode = FindNode( lNode, wxT( "padStyleDef" ) );
133
134 while( lNode )
135 {
136 lNode->GetAttribute( wxT( "Name" ), &propValue );
137
138 if( propValue.IsSameAs( m_Name.text, false) )
139 break;
140
141 lNode = lNode->GetNext();
142 }
143
144 if ( !lNode )
145 THROW_IO_ERRORF( wxT( "Unable to find padStyleDef %s" ), m_Name.text );
146
147 cNode = FindNode( lNode, wxT( "holeDiam" ) );
148
149 if( cNode )
150 SetWidth( cNode->GetNodeContent(), aDefaultUnits, &m_Hole, aActualConversion );
151
152 if( FindNodeGetContent( lNode, wxT( "isHolePlated" ) ).IsSameAs( wxT( "False" ), false ) )
153 m_IsHolePlated = false;
154
155 cNode = FindNode( lNode, wxT( "padShape" ) );
156
157 while( cNode )
158 {
159 if( cNode->GetName().IsSameAs( wxT( "padShape" ), false ) )
160 {
161 // we support only Pads on specific layers......
162 // we do not support pads on "Plane", "NonSignal" , "Signal" ... layerr
163 if( FindNode( cNode, wxT( "layerNumRef" ) ) )
164 {
165 padShape = new PCAD_PAD_SHAPE( m_callbacks, m_board );
166 padShape->Parse( cNode, aDefaultUnits, aActualConversion );
167 m_Shapes.Add( padShape );
168 }
169 }
170
171 cNode = cNode->GetNext();
172 }
173}
174
175
177{
178 int i;
179
181
182 if( m_ObjType == wxT( 'P' ) )
184
185 for( i = 0; i < (int)m_Shapes.GetCount(); i++ )
186 m_Shapes[i]->m_KiCadLayer = m_board->FlipLayer( m_Shapes[i]->m_KiCadLayer );
187}
188
189
190void PCAD_PAD::AddToFootprint( FOOTPRINT* aFootprint, const EDA_ANGLE& aRotation,
191 bool aEncapsulatedPad )
192{
193 PCAD_PAD_SHAPE* padShape;
194 wxString padShapeName = wxT( "Ellipse" );
195 PAD_ATTRIB padType;
196 int i;
197 int width = 0;
198 int height = 0;
199
200 PAD* pad = new PAD( aFootprint );
201
202 if( !m_IsHolePlated && m_Hole )
203 {
204 // mechanical hole
205 pad->SetPadstackMode( PADSTACK::MODE::NORMAL ); // PCAD doesn't have complex padstacks
207 pad->SetAttribute( PAD_ATTRIB::NPTH );
208
209 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
210 pad->SetDrillSize( VECTOR2I( m_Hole, m_Hole ) );
212
213 // Mounting Hole: Solder Mask Margin from Top Layer Width size.
214 // Used the default zone clearance (simplify)
215 if( m_Shapes.GetCount() && m_Shapes[0]->m_Shape.IsSameAs( wxT( "MtHole" ), false ) )
216 {
217 int sm_margin = ( m_Shapes[0]->m_Width - m_Hole ) / 2;
218 pad->SetLocalSolderMaskMargin( sm_margin );
219 pad->SetLocalClearance( sm_margin + pcbIUScale.mmToIU( 0.254 ) );
220 }
221
222 pad->SetLayerSet( LSET::AllCuMask() | LSET( { B_Mask, F_Mask } ) );
223 }
224 else
225 {
226 ( m_Hole ) ? padType = PAD_ATTRIB::PTH : padType = PAD_ATTRIB::SMD;
227
228 // form layer mask
229 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
230 {
231 padShape = m_Shapes[i];
232
233 if( padShape->m_Width > 0 && padShape->m_Height > 0 )
234 {
235 if( padShape->m_KiCadLayer == F_Cu ||
236 padShape->m_KiCadLayer == B_Cu )
237 {
238 padShapeName = padShape->m_Shape;
239 width = padShape->m_Width;
240 height = padShape->m_Height;
241
242 // assume this is SMD pad
243 if( padShape->m_KiCadLayer == F_Cu )
244 pad->SetLayerSet( LSET( { F_Cu, F_Paste, F_Mask } ) );
245 else
246 pad->SetLayerSet( LSET( { B_Cu, B_Paste, B_Mask } ) );
247
248 break;
249 }
250 }
251 }
252
253 if( width == 0 || height == 0 )
254 {
255 delete pad;
256 return;
257 }
258
259 if( padType == PAD_ATTRIB::PTH )
260 // actually this is a thru-hole pad
261 pad->SetLayerSet( LSET::AllCuMask() | LSET( { B_Mask, F_Mask } ) );
262
263 pad->SetNumber( m_Name.text );
264 pad->SetPadstackMode( PADSTACK::MODE::NORMAL ); // PCAD doesn't have complex padstacks
265
266 if( padShapeName.IsSameAs( wxT( "Oval" ), false )
267 || padShapeName.IsSameAs( wxT( "Ellipse" ), false )
268 || padShapeName.IsSameAs( wxT( "MtHole" ), false ) )
269 {
270 if( width != height )
272 else
274 }
275 else if( padShapeName.IsSameAs( wxT( "Rect" ), false ) )
276 {
278 }
279 else if( padShapeName.IsSameAs( wxT( "RndRect" ), false ) )
280 {
282 }
283 else if( padShapeName.IsSameAs( wxT( "Polygon" ), false ) )
284 {
285 pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE ); // approximation
286 }
287
288 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( width, height ) );
289 pad->SetDelta( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
290 pad->SetOrientation( m_Rotation + aRotation );
291
292 pad->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
293 pad->SetOffset( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
294 pad->SetDrillSize( VECTOR2I( m_Hole, m_Hole ) );
295
296 pad->SetAttribute( padType );
297
298 // Set the proper net code
299 NETINFO_ITEM* netinfo = m_board->FindNet( m_Net );
300
301 if( netinfo == nullptr ) // I believe this should not happen, but just in case
302 {
303 // It is a new net
304 netinfo = new NETINFO_ITEM( m_board, m_Net );
305 m_board->Add( netinfo );
306 }
307
308 pad->SetNetCode( netinfo->GetNetCode() );
309 }
310
311 if( !aEncapsulatedPad )
312 {
314 RotatePoint( padpos, aFootprint->GetOrientation() );
315 pad->SetPosition( padpos + aFootprint->GetPosition() );
316 }
317
318 aFootprint->Add( pad );
319}
320
321
323{
324 PCAD_PAD_SHAPE* padShape;
325 int i;
326 int width = 0;
327 int height = 0;
328
329 if( m_ObjType == wxT( 'V' ) ) // via
330 {
331 // choose one of the shapes
332 for( i = 0; i < (int) m_Shapes.GetCount(); i++ )
333 {
334 padShape = m_Shapes[i];
335
336 if( padShape->m_Width > 0 && padShape->m_Height > 0 )
337 {
338 if( padShape->m_KiCadLayer == F_Cu
339 || padShape->m_KiCadLayer == B_Cu )
340 {
341 width = padShape->m_Width;
342 height = padShape->m_Height;
343
344 break;
345 }
346 }
347 }
348
349 if( width == 0 || height == 0 )
350 return;
351
353 {
354 PCB_VIA* via = new PCB_VIA( m_board );
355 m_board->Add( via );
356
357 via->SetPosition( VECTOR2I( m_PositionX, m_PositionY ) );
358 via->SetEnd( VECTOR2I( m_PositionX, m_PositionY ) );
359
360 via->SetPadstackMode( PADSTACK::MODE::NORMAL ); // PCAD doesn't have complex padstacks
361 via->SetWidth( PADSTACK::ALL_LAYERS, height );
362 via->SetViaType( VIATYPE::THROUGH );
363 via->SetLayerPair( F_Cu, B_Cu );
364 via->SetDrill( m_Hole );
365
366 via->SetLayer( m_KiCadLayer );
367 via->SetNetCode( m_NetCode );
368 }
369 }
370 else // pad
371 {
372 if( !aFootprint )
373 {
374 aFootprint = new FOOTPRINT( m_board );
375 m_board->Add( aFootprint, ADD_MODE::APPEND );
376 aFootprint->SetPosition( VECTOR2I( m_PositionX, m_PositionY ) );
377 }
378
379 m_Name.text = m_defaultPinDes;
380
381 AddToFootprint( aFootprint, ANGLE_0, true );
382 }
383}
384
385} // namespace PCAD2KICAD
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
void SetPosition(const VECTOR2I &aPos) override
EDA_ANGLE GetOrientation() const
Definition footprint.h:438
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
VECTOR2I GetPosition() const override
Definition footprint.h:435
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:595
Handle the data for a net.
Definition netinfo.h:50
int GetNetCode() const
Definition netinfo.h:104
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
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:190
PCAD_PAD_SHAPES_ARRAY m_Shapes
Definition pcad_pad.h:53
PCAD_PAD(PCAD_CALLBACKS *aCallbacks, BOARD *aBoard)
Definition pcad_pad.cpp:37
void AddToBoard(FOOTPRINT *aFootprint=nullptr) override
Definition pcad_pad.cpp:322
virtual void Flip() override
Definition pcad_pad.cpp:176
wxString m_defaultPinDes
Definition pcad_pad.h:56
virtual void Parse(XNODE *aNode, const wxString &aDefaultUnits, const wxString &aActualConversion)
Definition pcad_pad.cpp:57
int GetNetCode(const wxString &aNetName) const
PCAD_PCB_COMPONENT(PCAD_CALLBACKS *aCallbacks, BOARD *aBoard)
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:67
XNODE * GetParent() const
Definition xnode.h:107
XNODE * GetNext() const
Definition xnode.h:102
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
@ TENTHS_OF_A_DEGREE_T
Definition eda_angle.h:30
static std::string padShapeName(const std::string &aStem, const PADSTACK &aPadstack, PCB_LAYER_ID aPadLayer)
A uniform padstack keeps the bare name, so it still reads as one shape and not as a stack.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:703
@ F_Paste
Definition layer_ids.h:100
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ B_Paste
Definition layer_ids.h:101
@ F_Cu
Definition layer_ids.h:60
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:96
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:102
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:98
@ PTH
Plated through hole pad.
Definition padstack.h:97
@ ROUNDRECT
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:53
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:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683