From f34ee00a8b1761ababbef0bf1a53b50b1aeb423f Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Sat, 24 Oct 2020 18:40:16 +0200 Subject: [PATCH] altium: import power port in all their different shapes --- .../sch_plugins/altium/altium_parser_sch.cpp | 20 ++ .../sch_plugins/altium/altium_parser_sch.h | 33 ++ .../sch_plugins/altium/sch_altium_plugin.cpp | 300 ++++++++++++++++++ .../sch_plugins/altium/sch_altium_plugin.h | 3 + 4 files changed, 356 insertions(+) diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.cpp b/eeschema/sch_plugins/altium/altium_parser_sch.cpp index 7aaa131462..33245e2e4b 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.cpp +++ b/eeschema/sch_plugins/altium/altium_parser_sch.cpp @@ -368,6 +368,26 @@ ASCH_RECTANGLE::ASCH_RECTANGLE( const std::map& aProperties } +ASCH_POWER_PORT::ASCH_POWER_PORT( const std::map& aProperties ) +{ + wxASSERT( PropertiesReadRecord( aProperties ) == ALTIUM_SCH_RECORD::POWER_PORT ); + + ownerpartid = + ALTIUM_PARSER::PropertiesReadInt( aProperties, "OWNERPARTID", ALTIUM_COMPONENT_NONE ); + + location = wxPoint( PropertiesReadKiCadUnitFrac( aProperties, "LOCATION.X" ), + -PropertiesReadKiCadUnitFrac( aProperties, "LOCATION.Y" ) ); + orientation = PropertiesReadEnum( + aProperties, "ORIENTATION", 0, 3, ASCH_RECORD_ORIENTATION::RIGHTWARDS ); + + text = ALTIUM_PARSER::PropertiesReadString( aProperties, "TEXT", "" ); + showNetName = ALTIUM_PARSER::PropertiesReadBool( aProperties, "SHOWNETNAME", true ); + + style = PropertiesReadEnum( + aProperties, "STYLE", 0, 10, ASCH_POWER_PORT_STYLE::CIRCLE ); +} + + ASCH_NO_ERC::ASCH_NO_ERC( const std::map& aProperties ) { wxASSERT( PropertiesReadRecord( aProperties ) == ALTIUM_SCH_RECORD::NO_ERC ); diff --git a/eeschema/sch_plugins/altium/altium_parser_sch.h b/eeschema/sch_plugins/altium/altium_parser_sch.h index 761c31dd24..a65e30115d 100644 --- a/eeschema/sch_plugins/altium/altium_parser_sch.h +++ b/eeschema/sch_plugins/altium/altium_parser_sch.h @@ -373,6 +373,39 @@ struct ASCH_RECTANGLE }; +enum class ASCH_POWER_PORT_STYLE +{ + UNKNOWN = -1, + + CIRCLE = 0, + ARROW = 1, + BAR = 2, + WAVE = 3, + POWER_GROUND = 4, + SIGNAL_GROUND = 5, + EARTH = 6, + GOST_ARROW = 7, + GOST_POWER_GROUND = 8, + GOST_EARTH = 9, + GOST_BAR = 10 +}; + + +struct ASCH_POWER_PORT +{ + int ownerpartid; + + wxString text; + bool showNetName; + + wxPoint location; + ASCH_RECORD_ORIENTATION orientation; + ASCH_POWER_PORT_STYLE style; + + explicit ASCH_POWER_PORT( const std::map& aProperties ); +}; + + struct ASCH_NO_ERC { wxPoint location; diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp index 9a778e38d4..18fc263ef0 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -341,6 +342,7 @@ void SCH_ALTIUM_PLUGIN::Parse( const CFB::CompoundFileReader& aReader ) case ALTIUM_SCH_RECORD::SHEET_ENTRY: break; case ALTIUM_SCH_RECORD::POWER_PORT: + ParsePowerPort( properties ); break; case ALTIUM_SCH_RECORD::PORT: break; @@ -1227,6 +1229,304 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map& aPro } +wxPoint HelperGeneratePowerPortGraphics( LIB_PART* aKPart, ASCH_POWER_PORT_STYLE aStyle ) +{ + if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE || aStyle == ASCH_POWER_PORT_STYLE::ARROW ) + { + LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line1 ); + line1->SetWidth( Mils2iu( 10 ) ); + line1->AddPoint( { 0, 0 } ); + line1->AddPoint( { 0, Mils2iu( -50 ) } ); + + if( aStyle == ASCH_POWER_PORT_STYLE::CIRCLE ) + { + LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart ); + aKPart->AddDrawItem( circle ); + circle->SetWidth( Mils2iu( 5 ) ); + circle->SetRadius( Mils2iu( 25 ) ); + circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } ); + } + else + { + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); + line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } ); + line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); + } + + return { 0, Mils2iu( 150 ) }; + } + else if( aStyle == ASCH_POWER_PORT_STYLE::WAVE ) + { + LIB_POLYLINE* line = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line ); + line->SetWidth( Mils2iu( 10 ) ); + line->AddPoint( { 0, 0 } ); + line->AddPoint( { 0, Mils2iu( -72 ) } ); + + LIB_BEZIER* bezier = new LIB_BEZIER( aKPart ); + aKPart->AddDrawItem( bezier ); + bezier->SetWidth( Mils2iu( 5 ) ); + bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } ); + bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } ); + bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } ); + bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -100 ) } ); + + return { 0, Mils2iu( 150 ) }; + } + else if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND + || aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND + || aStyle == ASCH_POWER_PORT_STYLE::EARTH + || aStyle == ASCH_POWER_PORT_STYLE::GOST_ARROW ) + { + LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line1 ); + line1->SetWidth( Mils2iu( 10 ) ); + line1->AddPoint( { 0, 0 } ); + line1->AddPoint( { 0, Mils2iu( -100 ) } ); + + if( aStyle == ASCH_POWER_PORT_STYLE::POWER_GROUND ) + { + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); + + LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line3 ); + line3->SetWidth( Mils2iu( 10 ) ); + line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } ); + line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } ); + + LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line4 ); + line4->SetWidth( Mils2iu( 10 ) ); + line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } ); + line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } ); + + LIB_POLYLINE* line5 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line5 ); + line5->SetWidth( Mils2iu( 10 ) ); + line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } ); + line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } ); + } + else if( aStyle == ASCH_POWER_PORT_STYLE::SIGNAL_GROUND ) + { + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); + } + else if( aStyle == ASCH_POWER_PORT_STYLE::EARTH ) + { + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -200 ) } ); + + LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line3 ); + line3->SetWidth( Mils2iu( 10 ) ); + line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); + line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } ); + } + else // ASCH_POWER_PORT_STYLE::GOST_ARROW + { + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } ); + line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } ); + + return { 0, Mils2iu( 150 ) }; // special case + } + + return { 0, Mils2iu( 250 ) }; + } + else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND + || aStyle == ASCH_POWER_PORT_STYLE::GOST_EARTH ) + { + LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line1 ); + line1->SetWidth( Mils2iu( 10 ) ); + line1->AddPoint( { 0, 0 } ); + line1->AddPoint( { 0, Mils2iu( -160 ) } ); + + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } ); + line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } ); + + LIB_POLYLINE* line3 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line3 ); + line3->SetWidth( Mils2iu( 10 ) ); + line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } ); + line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } ); + + LIB_POLYLINE* line4 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line4 ); + line4->SetWidth( Mils2iu( 10 ) ); + line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } ); + line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } ); + + if( aStyle == ASCH_POWER_PORT_STYLE::GOST_POWER_GROUND ) + return { 0, Mils2iu( 300 ) }; + + LIB_CIRCLE* circle = new LIB_CIRCLE( aKPart ); + aKPart->AddDrawItem( circle ); + circle->SetWidth( Mils2iu( 10 ) ); + circle->SetRadius( Mils2iu( 120 ) ); + circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } ); + + return { 0, Mils2iu( 350 ) }; + } + else if( aStyle == ASCH_POWER_PORT_STYLE::GOST_BAR ) + { + LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line1 ); + line1->SetWidth( Mils2iu( 10 ) ); + line1->AddPoint( { 0, 0 } ); + line1->AddPoint( { 0, Mils2iu( -200 ) } ); + + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } ); + line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } ); + + return { 0, Mils2iu( 250 ) }; + } + else + { + if( aStyle != ASCH_POWER_PORT_STYLE::BAR ) + wxLogWarning( "Power Port has unknown style, use bar instead. " ); + + LIB_POLYLINE* line1 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line1 ); + line1->SetWidth( Mils2iu( 10 ) ); + line1->AddPoint( { 0, 0 } ); + line1->AddPoint( { 0, Mils2iu( -100 ) } ); + + LIB_POLYLINE* line2 = new LIB_POLYLINE( aKPart ); + aKPart->AddDrawItem( line2 ); + line2->SetWidth( Mils2iu( 10 ) ); + line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } ); + line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } ); + + return { 0, Mils2iu( 150 ) }; + } +} + + +void SCH_ALTIUM_PLUGIN::ParsePowerPort( const std::map& aProperties ) +{ + ASCH_POWER_PORT elem( aProperties ); + + LIB_ID libId = AltiumToKiCadLibID( LIB_ID::ID_SCH, getLibName(), elem.text ); + + LIB_PART* kpart = nullptr; + + const auto& symbol = m_powerSymbols.find( elem.text ); + if( symbol != m_powerSymbols.end() ) + { + kpart = symbol->second; // cache hit + } + else + { + kpart = new LIB_PART( wxEmptyString ); + kpart->SetPower(); + kpart->SetName( elem.text ); + kpart->GetReferenceField().SetText( "#PWR" ); + kpart->GetValueField().SetText( elem.text ); + kpart->GetValueField().SetVisible( true ); // TODO: why does this not work? + kpart->SetDescription( wxString::Format( + "Power symbol creates a global label with name \"%s\"", elem.text ) ); + kpart->SetKeyWords( "power-flag" ); + kpart->SetLibId( libId ); + + // generate graphic + LIB_PIN* pin = new LIB_PIN( kpart ); + kpart->AddDrawItem( pin ); + + pin->SetName( elem.text ); + pin->SetPosition( { 0, 0 } ); + pin->SetLength( 0 ); + + // marks the pin as a global label + pin->SetType( ELECTRICAL_PINTYPE::PT_POWER_IN ); + pin->SetVisible( false ); + + wxPoint valueFieldPos = HelperGeneratePowerPortGraphics( kpart, elem.style ); + + kpart->GetValueField().SetPosition( valueFieldPos ); + + // this has to be done after parsing the LIB_PART! + m_pi->SaveSymbol( getLibFileName().GetFullPath(), kpart, m_properties.get() ); + m_powerSymbols.insert( { elem.text, kpart } ); + } + + SCH_SHEET_PATH sheetpath; + m_rootSheet->LocatePathOfScreen( m_currentSheet->GetScreen(), &sheetpath ); + + // each component has its own symbol for now + SCH_COMPONENT* component = new SCH_COMPONENT(); + component->SetRef( &sheetpath, "#PWR?" ); + component->SetValue( elem.text ); + component->SetLibId( libId ); + component->SetLibSymbol( new LIB_PART( *kpart ) ); + + SCH_FIELD* valueField = component->GetField( VALUE ); + + // TODO: Why do I need to set those a second time? + valueField->SetVisible( true ); + valueField->SetPosition( kpart->GetValueField().GetPosition() ); + + component->SetPosition( elem.location + m_sheetOffset ); + + switch( elem.orientation ) + { + case ASCH_RECORD_ORIENTATION::RIGHTWARDS: + component->SetOrientation( COMPONENT_ORIENTATION_T::CMP_ORIENT_90 ); + valueField->SetTextAngle( -900. ); + valueField->SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_LEFT ); + break; + case ASCH_RECORD_ORIENTATION::UPWARDS: + component->SetOrientation( COMPONENT_ORIENTATION_T::CMP_ORIENT_180 ); + valueField->SetTextAngle( -1800. ); + valueField->SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_CENTER ); + break; + case ASCH_RECORD_ORIENTATION::LEFTWARDS: + component->SetOrientation( COMPONENT_ORIENTATION_T::CMP_ORIENT_270 ); + valueField->SetTextAngle( -2700. ); + valueField->SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_RIGHT ); + break; + case ASCH_RECORD_ORIENTATION::DOWNWARDS: + component->SetOrientation( COMPONENT_ORIENTATION_T::CMP_ORIENT_0 ); + valueField->SetTextAngle( 0. ); + valueField->SetHorizJustify( EDA_TEXT_HJUSTIFY_T::GR_TEXT_HJUSTIFY_CENTER ); + break; + default: + wxLogWarning( "Pin has unexpected orientation" ); + break; + } + + m_currentSheet->GetScreen()->Append( component ); +} + + void SCH_ALTIUM_PLUGIN::ParseNoERC( const std::map& aProperties ) { ASCH_NO_ERC elem( aProperties ); diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.h b/eeschema/sch_plugins/altium/sch_altium_plugin.h index 6974c725ef..b67c0ef987 100644 --- a/eeschema/sch_plugins/altium/sch_altium_plugin.h +++ b/eeschema/sch_plugins/altium/sch_altium_plugin.h @@ -114,6 +114,7 @@ private: void ParseArc( const std::map& aProperties ); void ParseLine( const std::map& aProperties ); void ParseRectangle( const std::map& aProperties ); + void ParsePowerPort( const std::map& aProperties ); void ParseNoERC( const std::map& aProperties ); void ParseNetLabel( const std::map& aProperties ); void ParseBus( const std::map& aProperties ); @@ -138,6 +139,8 @@ private: std::map m_components; std::map m_symbols; // for the start, every component has its unique symbol + std::map m_powerSymbols; + std::map m_altiumComponents; };