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.

138 lines
4.0 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  5. * Author: SYSUEric <jzzhuang666@gmail.com>.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <wx/regex.h>
  21. #include "odb_component.h"
  22. #include "odb_util.h"
  23. #include "hash_eda.h"
  24. #include "pcb_io_odbpp.h"
  25. ODB_COMPONENT& COMPONENTS_MANAGER::AddComponent( const FOOTPRINT* aFp,
  26. const EDA_DATA::PACKAGE& aPkg )
  27. {
  28. auto& comp = m_compList.emplace_back( m_compList.size(), aPkg.m_index );
  29. comp.m_center = ODB::AddXY( aFp->GetPosition() );
  30. EDA_ANGLE angle = aFp->GetOrientation();
  31. if( angle != ANGLE_0 )
  32. {
  33. // odb Rotation is expressed in degrees and is always clockwise.
  34. // while kicad EDA_ANGLE is anticlockwise.
  35. angle = ANGLE_360 - angle;
  36. comp.m_rot = ODB::Double2String( angle.Normalize().AsDegrees() );
  37. }
  38. if( aFp->IsFlipped() )
  39. {
  40. comp.m_mirror = wxT( "M" );
  41. }
  42. comp.m_comp_name = aFp->GetReference().ToAscii();
  43. comp.m_part_name = wxString::Format( "%s_%s", aFp->GetFPID().GetFullLibraryName(),
  44. aFp->GetFPID().GetLibItemName().wx_str() );
  45. // ODB++ cannot handle spaces in these fields
  46. ODB::RemoveWhitespace( comp.m_comp_name );
  47. ODB::RemoveWhitespace( comp.m_part_name );
  48. if( comp.m_comp_name.IsEmpty() )
  49. {
  50. // The spec requires a component name; some ODB++ parsers can't handle it being empty
  51. comp.m_comp_name = wxString::Format( "UNNAMED%zu", m_compList.size() );
  52. }
  53. for( PCB_FIELD* field : aFp->GetFields() )
  54. {
  55. if( field->GetId() == FIELD_T::REFERENCE )
  56. continue;
  57. wxString key = field->GetName();
  58. ODB::RemoveWhitespace( key );
  59. comp.m_prp[key] = wxString::Format( "'%s'", field->GetText() );
  60. }
  61. if( aFp->IsDNP() )
  62. {
  63. AddSystemAttribute( comp, ODB_ATTR::NO_POP{ true } );
  64. }
  65. if( aFp->GetAttributes() & FP_SMD )
  66. {
  67. AddSystemAttribute( comp, ODB_ATTR::COMP_MOUNT_TYPE::MT_SMD );
  68. }
  69. else if( aFp->GetAttributes() & FP_THROUGH_HOLE )
  70. {
  71. AddSystemAttribute( comp, ODB_ATTR::COMP_MOUNT_TYPE::THT );
  72. }
  73. else
  74. {
  75. AddSystemAttribute( comp, ODB_ATTR::COMP_MOUNT_TYPE::OTHER );
  76. }
  77. return comp;
  78. }
  79. void COMPONENTS_MANAGER::Write( std::ostream& ost ) const
  80. {
  81. ost << "UNITS=" << PCB_IO_ODBPP::m_unitsStr << std::endl;
  82. WriteAttributes( ost );
  83. for( const auto& comp : m_compList )
  84. {
  85. comp.Write( ost );
  86. }
  87. }
  88. void ODB_COMPONENT::Write( std::ostream& ost ) const
  89. {
  90. ost << "# CMP " << m_index << std::endl;
  91. ost << "CMP " << m_pkg_ref << " " << m_center.first << " " << m_center.second << " " << m_rot
  92. << " " << m_mirror << " " << m_comp_name << " " << m_part_name;
  93. WriteAttributes( ost );
  94. ost << std::endl;
  95. for( const auto& [key, value] : m_prp )
  96. {
  97. ost << "PRP " << key << " " << value << std::endl;
  98. }
  99. for( const auto& toep : m_toeprints )
  100. {
  101. toep.Write( ost );
  102. }
  103. ost << "#" << std::endl;
  104. }
  105. void ODB_COMPONENT::TOEPRINT::Write( std::ostream& ost ) const
  106. {
  107. ost << "TOP " << m_pin_num << " " << m_center.first << " " << m_center.second << " " << m_rot
  108. << " " << m_mirror << " " << m_net_num << " " << m_subnet_num << " " << m_toeprint_name
  109. << std::endl;
  110. }