From c1dec964be83a36100e54548e2bbb6013236e9ee Mon Sep 17 00:00:00 2001 From: Roberto Fernandez Bautista Date: Tue, 8 Sep 2020 14:01:32 +0100 Subject: [PATCH] CADSTAR PCB Archive Importer: Fix Parsing errors Change error displayed when a Library .cpa file is opened (instead of a Layout file) Add warning if variants exist in original design. Parse LAYERHEIGHT in LAYER (same thing a MAKE but without the MATERIAL_ID) Parse PADEXCEPTION in COMPONENT Add DESIGN as one of the valid UNITS --- .../cadstar/cadstar_pcb_archive_loader.cpp | 9 +- .../cadstar/cadstar_pcb_archive_parser.cpp | 86 ++++++++++++++++--- .../cadstar/cadstar_pcb_archive_parser.h | 34 ++++++-- 3 files changed, 106 insertions(+), 23 deletions(-) diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp index 3eef6690a8..3194dbd1dd 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp @@ -90,7 +90,10 @@ void CADSTAR_PCB_ARCHIVE_LOADER::Load( ::BOARD* aBoard ) loadCoppers(); loadNets(); - //TODO: process all other items + if( Layout.VariantHierarchy.size() > 0 ) + wxLogWarning( + _( "The CADSTAR design contains variants which has no KiCad equivalent. All " + "components have been loaded on top of each other. " ) ); wxLogMessage( _( "The CADSTAR design has been imported successfully.\n" @@ -870,7 +873,9 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadComponents() } loadComponentAttributes( comp, m ); - m->SetDescription( getPart( comp.PartID ).Definition.Name ); + + if( !comp.PartID.IsEmpty() && comp.PartID != wxT( "NO_PART" ) ) + m->SetDescription( getPart( comp.PartID ).Definition.Name ); mComponentMap.insert( { comp.ID, m } ); } diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.cpp index 4f48e50787..25322cfd0d 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.cpp +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.cpp @@ -455,10 +455,15 @@ void CADSTAR_PCB_ARCHIVE_PARSER::LAYER::Parse( XNODE* aNode ) { wxString tempNodeName = tempNode->GetName(); - if( tempNodeName == wxT( "MAKE" ) ) + if( tempNodeName == wxT( "MAKE" ) || tempNodeName == wxT( "LAYERHEIGHT" ) ) { - MaterialId = GetXmlAttributeIDString( tempNode, 0 ); - Thickness = GetXmlAttributeIDLong( tempNode, 1 ); + if( tempNodeName == wxT( "LAYERHEIGHT" ) ) + Thickness = GetXmlAttributeIDLong( tempNode, 0 ); + else + { + MaterialId = GetXmlAttributeIDString( tempNode, 0 ); + Thickness = GetXmlAttributeIDLong( tempNode, 1 ); + } XNODE* childOfTempNode = tempNode->GetChildren(); @@ -671,7 +676,15 @@ void CADSTAR_PCB_ARCHIVE_PARSER::HEADER::Parse( XNODE* aNode ) Format.Parse( cNode ); if( Format.Type != wxT( "LAYOUT" ) ) - THROW_IO_ERROR( "Not a CADSTAR PCB Layout file!" ); + if( Format.Type == wxT( "LIBRARY" ) ) + THROW_IO_ERROR( + "The selected file is a CADSTAR Library file (as opposed to a Layout " + "file). CADSTAR libraries cannot yet be imported into KiCad." ); + else + THROW_IO_ERROR( + "The selected file is an unknown CADSTAR format so cannot be " + "imported into KiCad." ); + } else if( nodeName == wxT( "JOBFILE" ) ) JobFile = GetXmlAttributeIDString( cNode, 0 ); @@ -1358,6 +1371,8 @@ CADSTAR_PCB_ARCHIVE_PARSER::UNITS CADSTAR_PCB_ARCHIVE_PARSER::ParseUnits( XNODE* return UNITS::MM; else if( unit == wxT( "THOU" ) ) return UNITS::THOU; + else if( unit == wxT( "DESIGN" ) ) + return UNITS::DESIGN; else THROW_UNKNOWN_PARAMETER_IO_ERROR( unit, wxT( "UNITS" ) ); @@ -1563,6 +1578,19 @@ CADSTAR_PCB_ARCHIVE_PARSER::SWAP_RULE CADSTAR_PCB_ARCHIVE_PARSER::ParseSwapRule( return retval; } +CADSTAR_PCB_ARCHIVE_PARSER::PAD_SIDE CADSTAR_PCB_ARCHIVE_PARSER::GetPadSide( + const wxString& aPadSideString ) +{ + if( aPadSideString == wxT( "THRU" ) ) + return PAD_SIDE::THROUGH_HOLE; + else if( aPadSideString == wxT( "BOTTOM" ) ) + return PAD_SIDE::MAXIMUM; + else if( aPadSideString == wxT( "TOP" ) ) + return PAD_SIDE::MINIMUM; + else + return PAD_SIDE::THROUGH_HOLE; // Assume through hole as default +} + void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT_COPPER::Parse( XNODE* aNode ) { @@ -1712,15 +1740,7 @@ void CADSTAR_PCB_ARCHIVE_PARSER::PAD::Parse( XNODE* aNode ) ID = GetXmlAttributeIDLong( aNode, 0 ); PadCodeID = GetXmlAttributeIDString( aNode, 2 ); - - wxString padSideStr = GetXmlAttributeIDString( aNode, 3 ); - - if( padSideStr == wxT( "THRU" ) ) - Side = PAD_SIDE::THROUGH_HOLE; - else if( padSideStr == wxT( "BOTTOM" ) ) - Side = PAD_SIDE::MAXIMUM; - else if( padSideStr == wxT( "TOP" ) ) - Side = PAD_SIDE::MINIMUM; + Side = GetPadSide( GetXmlAttributeIDString( aNode, 3 ) ); XNODE* cNode = aNode->GetChildren(); wxString location = wxString::Format( "PAD %d", ID ); @@ -2740,6 +2760,40 @@ void CADSTAR_PCB_ARCHIVE_PARSER::PIN_ATTRIBUTE::Parse( XNODE* aNode ) } +void CADSTAR_PCB_ARCHIVE_PARSER::PADEXCEPTION::Parse( XNODE* aNode ) +{ + wxASSERT( aNode->GetName() == wxT( "PADEXCEPTION" ) ); + + ID = GetXmlAttributeIDLong( aNode, 0 ); + + XNODE* cNode = aNode->GetChildren(); + + for( ; cNode; cNode = cNode->GetNext() ) + { + wxString cNodeName = cNode->GetName(); + + if( cNodeName == wxT( "PADCODEREF" ) ) + { + PadCode = GetXmlAttributeIDString( cNode, 0 ); + } + else if( cNodeName == wxT( "SIDE" ) ) + { + OverrideSide = true; + Side = GetPadSide( GetXmlAttributeIDString( cNode, 0 ) ); + } + else if( cNodeName == wxT( "ORIENT" ) ) + { + OverrideOrientation = true; + OrientAngle = GetXmlAttributeIDLong( cNode, 0 ); + } + else + { + THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() ); + } + } +} + + void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT::Parse( XNODE* aNode ) { wxASSERT( aNode->GetName() == wxT( "COMP" ) ); @@ -2808,6 +2862,12 @@ void CADSTAR_PCB_ARCHIVE_PARSER::COMPONENT::Parse( XNODE* aNode ) wxString pinLabel = GetXmlAttributeIDString( cNode, 1 ); PinLabels.insert( std::make_pair( pinID, pinLabel ) ); } + else if( cNodeName == wxT( "PADEXCEPTION" ) ) + { + PADEXCEPTION padExcept; + padExcept.Parse( cNode ); + PadExceptions.insert( std::make_pair( padExcept.ID, padExcept ) ); + } else { THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() ); diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.h b/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.h index 3eb1c821b2..dfeda30aea 100644 --- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.h +++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_parser.h @@ -246,14 +246,14 @@ public: LAYER_TYPE Type = LAYER_TYPE::UNDEFINED; LAYER_SUBTYPE SubType = LAYER_SUBTYPE::LAYERSUBTYPE_NONE; PHYSICAL_LAYER_ID PhysicalLayer = - UNDEFINED_PHYSICAL_LAYER; ///< If UNDEFINED, no physical layer is - ///< assigned (e.g. documentation and - ///< construction layers) - LAYER_ID SwapLayerID = UNDEFINED_LAYER_ID; ///< If UNDEFINED_LAYER_ID, no swap layer - ROUTING_BIAS RoutingBias = ROUTING_BIAS::UNBIASED; - long Thickness = 0; ///< Note: Units of length are defined in file header - MATERIAL_ID MaterialId; - EMBEDDING Embedding = EMBEDDING::NONE; + UNDEFINED_PHYSICAL_LAYER; ///< If UNDEFINED, no physical layer is + ///< assigned (e.g. documentation and + ///< construction layers) + LAYER_ID SwapLayerID = UNDEFINED_LAYER_ID; ///< If UNDEFINED_LAYER_ID, no swap layer + ROUTING_BIAS RoutingBias = ROUTING_BIAS::UNBIASED; + long Thickness = 0; ///< Note: Units of length are defined in file header + MATERIAL_ID MaterialId = UNDEFINED_MATERIAL_ID; + EMBEDDING Embedding = EMBEDDING::NONE; bool ReferencePlane = false; bool VariantLayer = false; @@ -800,6 +800,7 @@ public: enum class UNITS { + DESIGN, ///< Inherits from design units (assumed Assignments->Technology->Units) THOU, INCH, MICROMETRE, @@ -1039,6 +1040,9 @@ public: THROUGH_HOLE ///< All physical layers currently defined }; + + static PAD_SIDE GetPadSide( const wxString& aPadSideString ); + /** * @brief From CADSTAR help: "For specifying the directions in which routes can enter or exit the * pad. There are eight pre-defined directions to choose from, North, South, East, West, @@ -1683,6 +1687,19 @@ public: }; + struct PADEXCEPTION + { + PAD_ID ID; + PADCODE_ID PadCode = wxEmptyString; ///< If not empty, override padcode + bool OverrideSide = false; + PAD_SIDE Side; + bool OverrideOrientation = false; + long OrientAngle = 0; + + void Parse( XNODE* aNode ); + }; + + struct COMPONENT { COMPONENT_ID ID; @@ -1712,6 +1729,7 @@ public: ///< to be out of sync. ///< See PART::DEFINITION::PIN::Label std::map PinAttributes; + std::map PadExceptions; void Parse( XNODE* aNode ); };