From b9edfe4fe4fcf6de3ceb50d428ffefebcf56133a Mon Sep 17 00:00:00 2001 From: Russell Oliver Date: Fri, 30 Jun 2017 11:52:05 +1000 Subject: [PATCH] WIP: Refactor symbol importation to account for multiple gates and device connect pin maps. --- common/eagle_parser.cpp | 15 ++- eeschema/libarch.cpp | 9 ++ eeschema/sch_eagle_plugin.cpp | 210 ++++++++++++++++++++++------------ eeschema/sch_eagle_plugin.h | 16 ++- include/eagle_parser.h | 7 +- 5 files changed, 168 insertions(+), 89 deletions(-) diff --git a/common/eagle_parser.cpp b/common/eagle_parser.cpp index 95374473ff..ea79657672 100644 --- a/common/eagle_parser.cpp +++ b/common/eagle_parser.cpp @@ -742,8 +742,9 @@ EPART::EPART( wxXmlNode* aPart ) library = parseRequiredAttribute( aPart, "library" ); deviceset = parseRequiredAttribute( aPart, "deviceset" ); device = parseRequiredAttribute( aPart, "device" ); - technology = parseRequiredAttribute( aPart, "technology" ); + technology = parseOptionalAttribute( aPart, "technology" ); value = parseOptionalAttribute( aPart, "value" ); + rot = parseOptionalAttribute( aPart, "rot" ); } @@ -786,8 +787,10 @@ EGATE::EGATE( wxXmlNode* aGate ) * > */ + std::cout << aGate->GetName().ToStdString() << '\n'; name = parseRequiredAttribute( aGate, "name" ); - symbol = parseRequiredAttribute( aGate, "library" ); + std::cout << name << '\n'; + symbol = parseRequiredAttribute( aGate, "symbol" ); x = parseRequiredAttribute( aGate, "x" ); y = parseRequiredAttribute( aGate, "y" ); @@ -848,6 +851,7 @@ EDEVICE::EDEVICE( wxXmlNode* aDevice ) while(connectNode){ connects.push_back(ECONNECT(connectNode)); + connectNode = connectNode->GetNext(); } }; @@ -868,8 +872,8 @@ EDEVICESET::EDEVICESET( wxXmlNode* aDeviceSet ) prefix = parseOptionalAttribute( aDeviceSet, "prefix" ); uservalue = parseOptionalAttribute( aDeviceSet, "uservalue" ); - - + /* Russell: Parsing of devices and gates moved to sch_eagle_plugin.cpp + * //TODO: description NODE_MAP aDeviceSetChildren = MapChildren(aDeviceSet); @@ -886,7 +890,6 @@ EDEVICESET::EDEVICESET( wxXmlNode* aDeviceSet ) gates.push_back(EGATE(gateNode)); gateNode->GetNext(); } + */ } - - diff --git a/eeschema/libarch.cpp b/eeschema/libarch.cpp index 2ceefb2331..268191ef40 100644 --- a/eeschema/libarch.cpp +++ b/eeschema/libarch.cpp @@ -102,6 +102,15 @@ bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName ) // AddPart() does first clone the part before adding. archLib->AddPart( part ); } + // Russell: This is a hack to get a part to save into the cache file the components PART_REF when imported with the eagle plugin. + // Don't think it is kosher, but it works for now. + else + { + PART_REF partref = component->GetPartRef(); + if( !partref.expired()){ + cacheLib->AddPart( partref.lock().get() ); + } + } } catch( ... /* IO_ERROR ioe */ ) { diff --git a/eeschema/sch_eagle_plugin.cpp b/eeschema/sch_eagle_plugin.cpp index 634fc394e6..1b9367d262 100644 --- a/eeschema/sch_eagle_plugin.cpp +++ b/eeschema/sch_eagle_plugin.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,8 @@ #include +using std::string; + // Eagle schematic internal units are millimeters // Kicad schematic units are thousandths of an inch constexpr double EUNIT_TO_MIL = 1000.0 / 25.4; @@ -170,7 +173,7 @@ SCH_SHEET* SCH_EAGLE_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway, // Load the document wxXmlDocument xmlDocument; - wxFileName fn = aFileName; + m_filename = aFileName; m_kiway = aKiway; if( !xmlDocument.Load( fn.GetFullPath() ) ) @@ -275,8 +278,13 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode ) // TODO : handle modules nodes // wxXmlNode* modules = schematicChildren["modules"]; - // TODO : handle parts nodes - // wxXmlNode* parts = schematicChildren["parts"]; + wxXmlNode* partNode = schematicChildren["parts"]->GetChildren(); + while( partNode ) + { + std::unique_ptr epart( new EPART(partNode) ); + m_partlist[epart.get()->name] = epart.release(); + partNode = partNode->GetNext(); + } // TODO : handle variantdefs nodes // wxXmlNode* variantdefs = schematicChildren["variantdefs"]; @@ -290,7 +298,9 @@ void SCH_EAGLE_PLUGIN::loadSchematic( wxXmlNode* aSchematicNode ) while( libraryNode ) { - loadLibrary( libraryNode ); + + auto elib = loadLibrary( libraryNode ); + m_eaglelibraries[elib->name] = elib; libraryNode = libraryNode->GetNext(); } @@ -581,15 +591,32 @@ void SCH_EAGLE_PLUGIN::loadInstance( wxXmlNode* aInstanceNode ) // Find the device from the part entry, and its LIB_PART. + std::cout << "Instance> part: " << einstance.part << " Gate: " << einstance.gate << '\n'; + EPART* epart = m_partlist[einstance.part]; + std::cout << "Part> name: " << epart->name << " library: " << epart->library << " deviceset: " << epart->deviceset << epart->device << '\n'; + + std::string gatename = epart->deviceset + epart->device + einstance.gate; + std::string symbolname = epart->deviceset + epart->device; + std::cout << gatename << '\n'; + std::cout << "Gate to unit number " << m_eaglelibraries[epart->library]->gate_unit[gatename] << '\n'; + int unit = m_eaglelibraries[epart->library]->gate_unit[gatename]; + LIB_PART* part = m_eaglelibraries[epart->library]->kicadsymbols[symbolname]; - std::unique_ptr< SCH_COMPONENT > component( new SCH_COMPONENT() ); - - - component->SetPosition( wxPoint(einstance.x*EUNIT_TO_MIL, -einstance.y*EUNIT_TO_MIL) ); + //SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* sheet, int unit, int convert, const wxPoint& pos, bool setNewItemFlag ) + std::unique_ptr< SCH_COMPONENT > component( new SCH_COMPONENT( *part, NULL, unit, 0, wxPoint(einstance.x*EUNIT_TO_MIL, -einstance.y*EUNIT_TO_MIL), true ) ); + if(epart->rot){ + if(epart->rot->mirror){ + component->MirrorY(0); + } + } component->GetField(0)->SetText(einstance.part); + component->SetModified(); + + + @@ -607,13 +634,17 @@ void SCH_EAGLE_PLUGIN::loadModuleinst( wxXmlNode* aModuleinstNode ) } -void SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode ) +EAGLE_LIBRARY* SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode ) { - EAGLE_LIBRARY elib; + unique_ptr elib(new EAGLE_LIBRARY); + + std::map gate; + // Read the library name wxString libName = aLibraryNode->GetAttribute( "name" ); + elib.get()->name = libName.ToStdString(); std::cout << "Importing Eagle Library "<< libName.ToStdString() << std::endl; @@ -623,15 +654,6 @@ void SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode ) // TODO: Do something with the description // wxXmlNode* libraryChildren["description"]; - // Loop through the devicesets and load each of them - wxXmlNode* devicesetNode = libraryChildren["devicesets"]->GetChildren(); - while( devicesetNode ) - { - auto edeviceset = EDEVICESET(devicesetNode ); - - elib.devicesets[edeviceset.name] = &edeviceset; - devicesetNode = devicesetNode->GetNext(); - } // Loop through the packages and load each of them // wxXmlNode* packageNode = libraryChildren["packages"]->GetChildren(); @@ -647,68 +669,86 @@ void SCH_EAGLE_PLUGIN::loadLibrary( wxXmlNode* aLibraryNode ) while( symbolNode ) { wxString symbolName = symbolNode->GetAttribute( "name" ); - elib.symbolnodes[symbolName.ToStdString()] = symbolNode; + elib->symbolnodes[symbolName.ToStdString()] = symbolNode; symbolNode = symbolNode->GetNext(); } - // For each devicesets. - for(auto deviceset = elib.devicesets.begin(); deviceset != elib.devicesets.end(); deviceset++) + // Loop through the devicesets and load each of them + wxXmlNode* devicesetNode = libraryChildren["devicesets"]->GetChildren(); + while( devicesetNode ) { - std::cout << "Importing Eagle device set "<< deviceset->first << std::endl; + // Get Device set information + EDEVICESET edeviceset = EDEVICESET(devicesetNode); - std::map gate_items; + std::cout << "Importing Eagle device set "<< edeviceset.name << std::endl; - int gates_count = 0; - // create a set of lib items for each gate. - for(auto gate = deviceset->second->gates.begin(); gate != deviceset->second->gates.end(); gate++) - { - std::cout << "Creating item list for gate: "<< gate->name << std::endl; - wxXmlNode* sn = elib.symbolnodes[gate->name]; - gate_items[gate->name] = loadSymbol(sn); - gates_count++; - } + NODE_MAP aDeviceSetChildren = MapChildren(devicesetNode); + wxXmlNode* deviceNode = getChildrenNodes(aDeviceSetChildren, "devices"); + // For each device in the device set: + while(deviceNode){ + // Get device information + EDEVICE edevice = EDEVICE(deviceNode); - for(auto device = deviceset->second->devices.begin(); device != deviceset->second->devices.end(); device++) - { - wxString symbolName = wxString(deviceset->first + device->name); + // Create symbol name from deviceset and device names. + wxString symbolName = wxString( edeviceset.name+ edevice.name); + std::cout << "Creating Kicad Symbol: " << symbolName.ToStdString() << '\n'; - std::cout << symbolName.ToStdString() << '\n'; - - unique_ptr part; - - part->SetName(symbolName); - part->SetUnitCount(gates_count); - for(const auto libItems : gate_items ){ - for(const auto libitem : libItems) - { - std::cout << libitem; - } + // Create kicad symbol. + unique_ptr kpart ( new LIB_PART(symbolName)); + // Process each gate in the deviceset for this device. + wxXmlNode* gateNode = getChildrenNodes(aDeviceSetChildren, "gates"); + int gates_count = countChildren(deviceNode, "gates"); + if(gates_count>1){ + gates_count=1; } + else + { + gates_count = 0; + } + while(gateNode){ + + EGATE egate = EGATE(gateNode); + + elib.get()->gate_unit[edeviceset.name+edevice.name+egate.name] = gates_count; + + loadSymbol(elib->symbolnodes[egate.symbol], (LIB_PART*)kpart.get(), &edevice, (int)gates_count, egate.name); + + gates_count++; + gateNode = gateNode->GetNext(); + } // gateNode + + kpart->SetUnitCount(gates_count); + + elib->kicadsymbols[kpart->GetName().ToStdString()] = kpart.release(); + + deviceNode = deviceNode->GetNext(); + } // devicenode + + devicesetNode = devicesetNode->GetNext(); + } // devicesetNode - - } - } - - + return elib.release(); } -LIB_ITEMS* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode ) +void SCH_EAGLE_PLUGIN::loadSymbol(wxXmlNode *aSymbolNode, LIB_PART* aPart, EDEVICE* aDevice, int gateNumber, string gateName) { + //std::cout << "loadsymbol" << '\n'; // Create a new part with the symbol name wxString symbolName = aSymbolNode->GetAttribute( "name" ); - unique_ptr items; + std::vector items; wxXmlNode* currentNode = aSymbolNode->GetChildren(); while( currentNode ) { - wxString nodeName = currentNode->GetName(); + wxString nodeName = currentNode->GetName(); + //std::cout << "symbolnode " << nodeName.ToStdString() <<'\n'; if( nodeName == "description" ) { // TODO @@ -724,25 +764,41 @@ LIB_ITEMS* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode ) } else if( nodeName == "circle" ) { - items->push_back(loadSymbolCircle( NULL, currentNode ) ); + LIB_CIRCLE* circle = loadSymbolCircle( aPart, currentNode ); + circle->SetUnit(gateNumber); + aPart->AddDrawItem( circle ); } else if( nodeName == "pin" ) { - items->push_back( loadPin( NULL, currentNode ) ); + LIB_PIN* pin = loadPin( aPart, currentNode ); + + for(auto connect : aDevice->connects) + { + //std::cout << connect.gate << " " << connect.pin << " " << connect.pad << std::endl; + if(connect.gate == gateName and pin->GetName().ToStdString() == connect.pin){ + wxString padname(connect.pad); + pin->SetPinNumFromString(padname); + } + } + pin->SetUnit(gateNumber); + aPart->AddDrawItem(pin); } else if( nodeName == "polygon" ) { - //items.push_back( loadPolygon( NULL, currentNode ) ); + //loadPolygon( aPart, currentNode ); + //aPart->AddDrawItem(); } else if( nodeName == "rectangle" ) { - items->push_back( loadSymbolRectangle( NULL, currentNode ) ); + LIB_RECTANGLE* rectangle = loadSymbolRectangle( aPart, currentNode ); + rectangle->SetUnit(gateNumber); + aPart->AddDrawItem( rectangle ); } else if( nodeName == "text" ) { - LIB_TEXT* libtext = loadSymboltext( NULL, currentNode ); - - items->push_back( libtext); + LIB_TEXT* libtext = loadSymboltext( aPart, currentNode ); + libtext->SetUnit(gateNumber); + aPart->AddDrawItem( libtext); // TODO: Reimplement mandatory field positioning. /* if( libtext->GetText() ==">NAME" ) @@ -761,17 +817,19 @@ LIB_ITEMS* SCH_EAGLE_PLUGIN::loadSymbol( wxXmlNode* aSymbolNode ) } */ //else - // items.push_back( loadlibtext( NULL, currentNode ) ); + // aPart->AddDrawItem(loadlibtext( NULL, currentNode ) ); } else if( nodeName == "wire" ) { - items->push_back( loadSymbolWire( NULL, currentNode ) ); + LIB_POLYLINE* pline = loadSymbolWire( aPart, currentNode ); + pline->SetUnit(gateNumber); + aPart->AddDrawItem(pline); } currentNode = currentNode->GetNext(); } - return items.release(); + } @@ -782,7 +840,7 @@ LIB_CIRCLE* SCH_EAGLE_PLUGIN::loadSymbolCircle( LIB_PART* aPart, wxXmlNode* aCir unique_ptr circle( new LIB_CIRCLE( aPart ) ); - circle->SetPosition( wxPoint( c.x*EUNIT_TO_MIL, -c.y*EUNIT_TO_MIL ) ); + circle->SetPosition( wxPoint( c.x*EUNIT_TO_MIL, c.y*EUNIT_TO_MIL ) ); circle->SetRadius( c.radius*EUNIT_TO_MIL ); circle->SetWidth( c.width*EUNIT_TO_MIL ); @@ -796,8 +854,8 @@ LIB_RECTANGLE* SCH_EAGLE_PLUGIN::loadSymbolRectangle( LIB_PART* aPart, wxXmlNode unique_ptr rectangle( new LIB_RECTANGLE( aPart ) ); - rectangle->SetPosition( wxPoint( rect.x1*EUNIT_TO_MIL, -rect.y1*EUNIT_TO_MIL ) ); - rectangle->SetEnd( wxPoint( rect.x2*EUNIT_TO_MIL, -rect.y2*EUNIT_TO_MIL ) ); + rectangle->SetPosition( wxPoint( rect.x1*EUNIT_TO_MIL, rect.y1*EUNIT_TO_MIL ) ); + rectangle->SetEnd( wxPoint( rect.x2*EUNIT_TO_MIL, rect.y2*EUNIT_TO_MIL ) ); // TODO: Manage rotation @@ -814,9 +872,9 @@ LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadSymbolWire( LIB_PART* aPart, wxXmlNode* aWir wxPoint begin, end; begin.x = ewire.x1*EUNIT_TO_MIL; - begin.y = -ewire.y1*EUNIT_TO_MIL; + begin.y = ewire.y1*EUNIT_TO_MIL; end.x = ewire.x2*EUNIT_TO_MIL; - end.y = -ewire.y2*EUNIT_TO_MIL; + end.y = ewire.y2*EUNIT_TO_MIL; polyLine->AddPoint( begin ); polyLine->AddPoint( end ); @@ -836,7 +894,7 @@ LIB_POLYLINE* SCH_EAGLE_PLUGIN::loadSymbolPolyLine( LIB_PART* aPart, wxXmlNode* while( vertex ) { auto evertex = EVERTEX( vertex ); - auto v = wxPoint( evertex.x*EUNIT_TO_MIL, -evertex.y*EUNIT_TO_MIL ); + auto v = wxPoint( evertex.x*EUNIT_TO_MIL, evertex.y*EUNIT_TO_MIL ); polyLine->AddPoint( v ); vertex->GetNext(); @@ -852,7 +910,7 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( LIB_PART* aPart, wxXmlNode* aPin ) auto epin = EPIN( aPin ); - pin->SetPosition( wxPoint( epin.x * EUNIT_TO_MIL, -epin.y * EUNIT_TO_MIL ) ); + pin->SetPosition( wxPoint( epin.x * EUNIT_TO_MIL, epin.y * EUNIT_TO_MIL ) ); pin->SetName( epin.name ); int roti = 0; @@ -869,7 +927,7 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( LIB_PART* aPart, wxXmlNode* aPin ) break; case 90: - pin->SetOrientation( 'D' ); + pin->SetOrientation( 'U' ); break; case 180: @@ -877,7 +935,7 @@ LIB_PIN* SCH_EAGLE_PLUGIN::loadPin( LIB_PART* aPart, wxXmlNode* aPin ) break; case 270: - pin->SetOrientation( 'U' ); + pin->SetOrientation( 'D' ); break; } @@ -913,7 +971,7 @@ LIB_TEXT* SCH_EAGLE_PLUGIN::loadSymboltext( LIB_PART* aPart, wxXmlNode* aLibText auto etext = ETEXT( aLibText ); - libtext->SetPosition( wxPoint( etext.x * EUNIT_TO_MIL, -etext.y * EUNIT_TO_MIL ) ); + libtext->SetPosition( wxPoint( etext.x * EUNIT_TO_MIL, etext.y * EUNIT_TO_MIL ) ); libtext->SetText( aLibText->GetNodeContent() ); libtext->SetTextSize( wxSize( int( etext.size * EUNIT_TO_MIL ), int( etext.size * EUNIT_TO_MIL ) ) ); @@ -940,6 +998,7 @@ bool SCH_EAGLE_PLUGIN::CheckHeader( const wxString& aFileName ) void SCH_EAGLE_PLUGIN::Save( const wxString& aFileName, SCH_SCREEN* aSchematic, KIWAY* aKiway, const PROPERTIES* aProperties ) { + std::cout << "SCH_EAGLE_PLUGIN::Save" << '\n'; } @@ -967,6 +1026,7 @@ LIB_ALIAS* SCH_EAGLE_PLUGIN::LoadSymbol( const wxString& aLibraryPath, const wxS void SCH_EAGLE_PLUGIN::SaveSymbol( const wxString& aLibraryPath, const LIB_PART* aSymbol, const PROPERTIES* aProperties ) { + std::cout << "SCH_EAGLE_PLUGIN::SaveSymbol" << '\n'; } diff --git a/eeschema/sch_eagle_plugin.h b/eeschema/sch_eagle_plugin.h index 450770942f..0dcd01315e 100644 --- a/eeschema/sch_eagle_plugin.h +++ b/eeschema/sch_eagle_plugin.h @@ -65,12 +65,14 @@ class LIB_TEXT; typedef struct EAGLE_LIBRARY { - wxString name; + std::string name; std::unordered_map kicadsymbols; - std::unordered_map devicesets; std::unordered_map symbolnodes; + std::unordered_map gate_unit; -}EAGLE_LIBRARY; +} EAGLE_LIBRARY; + +typedef std::map EPART_LIST; class SCH_EAGLE_PLUGIN : public SCH_PLUGIN { @@ -129,7 +131,7 @@ private: void loadSheet( wxXmlNode* aSheetNode ); void loadInstance( wxXmlNode* aInstanceNode ); void loadModuleinst( wxXmlNode* aModuleinstNode ); - void loadLibrary( wxXmlNode* aLibraryNode ); + EAGLE_LIBRARY* loadLibrary( wxXmlNode* aLibraryNode ); void loadSegments( wxXmlNode* aSegmentsNode, const wxString& aNetName, const wxString& aNetClass ); @@ -137,7 +139,7 @@ private: SCH_GLOBALLABEL* loadLabel( wxXmlNode* aLabelNode, const wxString& aNetName ); SCH_JUNCTION* loadJunction( wxXmlNode* aJunction ); - LIB_ITEMS* loadSymbol( wxXmlNode* aSymbolNode ); + void loadSymbol(wxXmlNode *aSymbolNode, LIB_PART* aPart, EDEVICE* aDevice, int gateNumber, string gateName); LIB_CIRCLE* loadSymbolCircle( LIB_PART* aPart, wxXmlNode* aCircleNode ); LIB_RECTANGLE* loadSymbolRectangle( LIB_PART* aPart, wxXmlNode* aRectNode ); LIB_POLYLINE* loadSymbolPolyLine( LIB_PART* aPart, wxXmlNode* aRectNode ); @@ -149,8 +151,12 @@ private: SCH_SHEET* m_rootSheet; ///< The root sheet of the schematic being loaded.. SCH_SHEET* m_currentSheet; ///< The current sheet of the schematic being loaded.. wxString m_version; ///< Eagle file version. + wxFileName m_filename; //PART_LIB* m_partlib; ///< symbol library for imported file. + EPART_LIST m_partlist; + std::map m_eaglelibraries; + diff --git a/include/eagle_parser.h b/include/eagle_parser.h index 063a6ef8e3..811cd2e2ad 100644 --- a/include/eagle_parser.h +++ b/include/eagle_parser.h @@ -831,8 +831,9 @@ struct EPART string library; string deviceset; string device; - string technology; + opt_string technology; opt_string value; + opt_erot rot; EPART( wxXmlNode* aPart ); }; @@ -949,8 +950,8 @@ struct EDEVICESET std::string name; opt_string prefix; opt_bool uservalue; - std::vector devices; - std::vector gates; + //std::vector devices; + //std::vector gates; EDEVICESET( wxXmlNode* aDeviceSet );