You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
11 KiB

12 years ago
12 years ago
  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. /**
  26. * @file pcb_pad.cpp
  27. */
  28. #include <wx/wx.h>
  29. #include <wx/config.h>
  30. #include <trigo.h>
  31. #include <pcb_pad.h>
  32. namespace PCAD2KICAD {
  33. PCB_PAD::PCB_PAD( PCB_CALLBACKS* aCallbacks, BOARD* aBoard ) : PCB_COMPONENT( aCallbacks, aBoard )
  34. {
  35. m_objType = wxT( 'P' );
  36. m_number = 0;
  37. m_hole = 0;
  38. m_isHolePlated = true;
  39. m_defaultPinDes = wxEmptyString;
  40. }
  41. PCB_PAD::~PCB_PAD()
  42. {
  43. int i;
  44. for( i = 0; i < (int) m_shapes.GetCount(); i++ )
  45. {
  46. delete m_shapes[i];
  47. }
  48. }
  49. void PCB_PAD::Parse( XNODE* aNode,
  50. const wxString& aDefaultMeasurementUnit,
  51. const wxString& aActualConversion )
  52. {
  53. XNODE* lNode, *cNode;
  54. long num;
  55. wxString propValue, str, emsg;
  56. PCB_PAD_SHAPE* padShape;
  57. m_rotation = 0;
  58. lNode = FindNode( aNode, wxT( "padNum" ) );
  59. if( lNode )
  60. {
  61. lNode->GetNodeContent().ToLong( &num );
  62. m_number = (int) num;
  63. }
  64. lNode = FindNode( aNode, wxT( "padStyleRef" ) );
  65. if( lNode )
  66. {
  67. lNode->GetAttribute( wxT( "Name" ), &propValue );
  68. propValue.Trim( false );
  69. m_name.text = propValue;
  70. }
  71. lNode = FindNode( aNode, wxT( "pt" ) );
  72. if( lNode )
  73. SetPosition( lNode->GetNodeContent(), aDefaultMeasurementUnit,
  74. &m_positionX, &m_positionY, aActualConversion );
  75. lNode = FindNode( aNode, wxT( "rotation" ) );
  76. if( lNode )
  77. {
  78. str = lNode->GetNodeContent();
  79. str.Trim( false );
  80. m_rotation = StrToInt1Units( str );
  81. }
  82. lNode = FindNode( aNode, wxT( "netNameRef" ) );
  83. if( lNode )
  84. {
  85. lNode->GetAttribute( wxT( "Name" ), &propValue );
  86. propValue.Trim( false );
  87. propValue.Trim( true );
  88. m_net = propValue;
  89. m_netCode = GetNetCode( m_net );
  90. }
  91. lNode = FindNode( aNode, wxT( "defaultPinDes" ) );
  92. if( lNode )
  93. {
  94. lNode->GetAttribute( wxT( "Name" ), &propValue );
  95. //propValue.Trim( false );
  96. m_defaultPinDes = propValue;
  97. }
  98. lNode = aNode;
  99. while( lNode && lNode->GetName() != wxT( "www.lura.sk" ) )
  100. lNode = lNode->GetParent();
  101. lNode = FindNode( lNode, wxT( "library" ) );
  102. if ( !lNode )
  103. THROW_IO_ERROR( wxT( "Unable to find library section" ) );
  104. lNode = FindNode( lNode, wxT( "padStyleDef" ) );
  105. while( lNode )
  106. {
  107. lNode->GetAttribute( wxT( "Name" ), &propValue );
  108. if( propValue.IsSameAs( m_name.text, false) )
  109. break;
  110. lNode = lNode->GetNext();
  111. }
  112. if ( !lNode )
  113. THROW_IO_ERROR( wxString::Format( wxT( "Unable to find padStyleDef " ) + m_name.text ) );
  114. cNode = FindNode( lNode, wxT( "holeDiam" ) );
  115. if( cNode )
  116. SetWidth( cNode->GetNodeContent(), aDefaultMeasurementUnit, &m_hole, aActualConversion );
  117. if( FindNodeGetContent( lNode, wxT( "isHolePlated" ) ) == wxT( "False" ) )
  118. m_isHolePlated = false;
  119. cNode = FindNode( lNode, wxT( "padShape" ) );
  120. while( cNode )
  121. {
  122. if( cNode->GetName() == wxT( "padShape" ) )
  123. {
  124. // we support only Pads on specific layers......
  125. // we do not support pads on "Plane", "NonSignal" , "Signal" ... layerr
  126. if( FindNode( cNode, wxT( "layerNumRef" ) ) )
  127. {
  128. padShape = new PCB_PAD_SHAPE( m_callbacks, m_board );
  129. padShape->Parse( cNode, aDefaultMeasurementUnit, aActualConversion );
  130. m_shapes.Add( padShape );
  131. }
  132. }
  133. cNode = cNode->GetNext();
  134. }
  135. }
  136. void PCB_PAD::Flip()
  137. {
  138. int i;
  139. PCB_COMPONENT::Flip();
  140. if( m_objType == wxT( 'P' ) )
  141. m_rotation = -m_rotation;
  142. for( i = 0; i < (int)m_shapes.GetCount(); i++ )
  143. m_shapes[i]->m_KiCadLayer = FlipLayer( m_shapes[i]->m_KiCadLayer );
  144. }
  145. void PCB_PAD::AddToModule( MODULE* aModule, int aRotation, bool aEncapsulatedPad )
  146. {
  147. PCB_PAD_SHAPE* padShape;
  148. wxString padShapeName = wxT( "Ellipse" );
  149. PAD_ATTR_T padType;
  150. int i;
  151. int width = 0;
  152. int height = 0;
  153. D_PAD* pad = new D_PAD( aModule );
  154. if( !m_isHolePlated && m_hole )
  155. {
  156. // mechanical hole
  157. pad->SetShape( PAD_SHAPE_CIRCLE );
  158. pad->SetAttribute( PAD_ATTRIB_HOLE_NOT_PLATED );
  159. pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
  160. pad->SetDrillSize( wxSize( m_hole, m_hole ) );
  161. pad->SetSize( wxSize( m_hole, m_hole ) );
  162. // Mounting Hole: Solder Mask Margin from Top Layer Width size.
  163. // Used the default zone clearance (simplify)
  164. if( m_shapes.GetCount() && m_shapes[0]->m_shape == wxT( "MtHole" ) )
  165. {
  166. int sm_margin = ( m_shapes[0]->m_width - m_hole ) / 2;
  167. pad->SetLocalSolderMaskMargin( sm_margin );
  168. pad->SetLocalClearance( sm_margin + Millimeter2iu( 0.254 ) );
  169. }
  170. pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
  171. }
  172. else
  173. {
  174. ( m_hole ) ? padType = PAD_ATTRIB_STANDARD : padType = PAD_ATTRIB_SMD;
  175. // form layer mask
  176. for( i = 0; i < (int) m_shapes.GetCount(); i++ )
  177. {
  178. padShape = m_shapes[i];
  179. if( padShape->m_width > 0 && padShape->m_height > 0 )
  180. {
  181. if( padShape->m_KiCadLayer == F_Cu ||
  182. padShape->m_KiCadLayer == B_Cu )
  183. {
  184. padShapeName = padShape->m_shape;
  185. width = padShape->m_width;
  186. height = padShape->m_height;
  187. // assume this is SMD pad
  188. if( padShape->m_KiCadLayer == F_Cu )
  189. pad->SetLayerSet( LSET( 3, F_Cu, F_Paste, F_Mask ) );
  190. else
  191. pad->SetLayerSet( LSET( 3, B_Cu, B_Paste, B_Mask ) );
  192. break;
  193. }
  194. }
  195. }
  196. if( width == 0 || height == 0 )
  197. {
  198. delete pad;
  199. return;
  200. }
  201. if( padType == PAD_ATTRIB_STANDARD )
  202. // actually this is a thru-hole pad
  203. pad->SetLayerSet( LSET::AllCuMask() | LSET( 2, B_Mask, F_Mask ) );
  204. pad->SetName( m_name.text );
  205. if( padShapeName == wxT( "Oval" )
  206. || padShapeName == wxT( "Ellipse" )
  207. || padShapeName == wxT( "MtHole" ) )
  208. {
  209. if( width != height )
  210. pad->SetShape( PAD_SHAPE_OVAL );
  211. else
  212. pad->SetShape( PAD_SHAPE_CIRCLE );
  213. }
  214. else if( padShapeName == wxT( "Rect" )
  215. || padShapeName == wxT( "RndRect" ) )
  216. pad->SetShape( PAD_SHAPE_RECT );
  217. else if( padShapeName == wxT( "Polygon" ) )
  218. pad->SetShape( PAD_SHAPE_RECT ); // approximation
  219. pad->SetSize( wxSize( width, height ) );
  220. pad->SetDelta( wxSize( 0, 0 ) );
  221. pad->SetOrientation( m_rotation + aRotation );
  222. pad->SetDrillShape( PAD_DRILL_SHAPE_CIRCLE );
  223. pad->SetOffset( wxPoint( 0, 0 ) );
  224. pad->SetDrillSize( wxSize( m_hole, m_hole ) );
  225. pad->SetAttribute( padType );
  226. // Set the proper net code
  227. NETINFO_ITEM* netinfo = m_board->FindNet( m_net );
  228. if( netinfo == NULL ) // I believe this should not happen, but just in case
  229. {
  230. // It is a new net
  231. netinfo = new NETINFO_ITEM( m_board, m_net );
  232. m_board->Add( netinfo );
  233. }
  234. pad->SetNetCode( netinfo->GetNet() );
  235. }
  236. if( !aEncapsulatedPad )
  237. {
  238. // pad's "Position" is not relative to the module's,
  239. // whereas Pos0 is relative to the module's but is the unrotated coordinate.
  240. wxPoint padpos( m_positionX, m_positionY );
  241. pad->SetPos0( padpos );
  242. RotatePoint( &padpos, aModule->GetOrientation() );
  243. pad->SetPosition( padpos + aModule->GetPosition() );
  244. }
  245. aModule->Add( pad );
  246. }
  247. void PCB_PAD::AddToBoard()
  248. {
  249. PCB_PAD_SHAPE* padShape;
  250. int i;
  251. int width = 0;
  252. int height = 0;
  253. if( m_objType == wxT( 'V' ) ) // via
  254. {
  255. // choose one of the shapes
  256. for( i = 0; i < (int) m_shapes.GetCount(); i++ )
  257. {
  258. padShape = m_shapes[i];
  259. if( padShape->m_width > 0 && padShape->m_height > 0 )
  260. {
  261. if( padShape->m_KiCadLayer == F_Cu
  262. || padShape->m_KiCadLayer == B_Cu )
  263. {
  264. width = padShape->m_width;
  265. height = padShape->m_height;
  266. break;
  267. }
  268. }
  269. }
  270. if( width == 0 || height == 0 )
  271. return;
  272. if( IsCopperLayer( m_KiCadLayer ) )
  273. {
  274. VIA* via = new VIA( m_board );
  275. m_board->Add( via );
  276. via->SetTimeStamp( 0 );
  277. via->SetPosition( wxPoint( m_positionX, m_positionY ) );
  278. via->SetEnd( wxPoint( m_positionX, m_positionY ) );
  279. via->SetWidth( height );
  280. via->SetViaType( VIATYPE::THROUGH );
  281. via->SetLayerPair( F_Cu, B_Cu );
  282. via->SetDrill( m_hole );
  283. via->SetLayer( m_KiCadLayer );
  284. via->SetNetCode( m_netCode );
  285. }
  286. }
  287. else // pad
  288. {
  289. MODULE* module = new MODULE( m_board );
  290. m_board->Add( module, ADD_MODE::APPEND );
  291. m_name.text = m_defaultPinDes;
  292. module->SetPosition( wxPoint( m_positionX, m_positionY ) );
  293. AddToModule( module, 0, true );
  294. }
  295. }
  296. } // namespace PCAD2KICAD