mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
Implement Component Classes
- Adds Component Class field to SCH_DIRECTIVE_LABEL - Adds SCH_SYMBOLs to SCH_RULE_AREA item lists - SCH_SYMBOLs resolve Component Class directives - Netlist exporter / importer handles Component Class names - Adds DRC expressions and functions - Adds QA check for component class netlist export
This commit is contained in:
parent
ae96ac6d2e
commit
d64a112971
@ -745,6 +745,7 @@ set( PCB_COMMON_SRCS
|
|||||||
${CMAKE_SOURCE_DIR}/pcbnew/teardrop/teardrop_parameters.cpp #needed by board_design_settings.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/teardrop/teardrop_parameters.cpp #needed by board_design_settings.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/router/pns_meander.cpp #needed by board_design_settings.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/router/pns_meander.cpp #needed by board_design_settings.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/board.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/board.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/pcbnew/component_class_manager.cpp #needed by board.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/board_item.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/board_item.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_dimension.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_dimension.cpp
|
||||||
${CMAKE_SOURCE_DIR}/pcbnew/pcb_shape.cpp
|
${CMAKE_SOURCE_DIR}/pcbnew/pcb_shape.cpp
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
class
|
||||||
code
|
code
|
||||||
comp
|
comp
|
||||||
components
|
components
|
||||||
|
component_classes
|
||||||
datasheet
|
datasheet
|
||||||
date
|
date
|
||||||
description
|
description
|
||||||
|
@ -65,6 +65,7 @@ center
|
|||||||
chamfer
|
chamfer
|
||||||
chamfer_ratio
|
chamfer_ratio
|
||||||
circle
|
circle
|
||||||
|
class
|
||||||
clearance
|
clearance
|
||||||
clearance_min
|
clearance_min
|
||||||
color
|
color
|
||||||
@ -73,6 +74,7 @@ column_count
|
|||||||
column_widths
|
column_widths
|
||||||
comment
|
comment
|
||||||
company
|
company
|
||||||
|
component_classes
|
||||||
connect
|
connect
|
||||||
connect_pads
|
connect_pads
|
||||||
copperpour
|
copperpour
|
||||||
|
@ -414,6 +414,21 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
|
|||||||
xsheetpath->AddAttribute( wxT( "names" ), sheet.PathHumanReadable() );
|
xsheetpath->AddAttribute( wxT( "names" ), sheet.PathHumanReadable() );
|
||||||
xsheetpath->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
|
xsheetpath->AddAttribute( wxT( "tstamps" ), sheet.PathAsString() );
|
||||||
|
|
||||||
|
// Node for component class
|
||||||
|
std::vector<wxString> compClassNames =
|
||||||
|
getComponentClassNamesForAllSymbolUnits( symbol, sheet, sheetList );
|
||||||
|
|
||||||
|
if( compClassNames.size() > 0 )
|
||||||
|
{
|
||||||
|
XNODE* xcompclasslist;
|
||||||
|
xcomp->AddChild( xcompclasslist = node( wxT( "component_classes" ) ) );
|
||||||
|
|
||||||
|
for( const wxString& compClass : compClassNames )
|
||||||
|
{
|
||||||
|
xcompclasslist->AddChild( node( wxT( "class" ), UnescapeString( compClass ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XNODE* xunits; // Node for extra units
|
XNODE* xunits; // Node for extra units
|
||||||
xcomp->AddChild( xunits = node( wxT( "tstamps" ) ) );
|
xcomp->AddChild( xunits = node( wxT( "tstamps" ) ) );
|
||||||
|
|
||||||
@ -445,6 +460,49 @@ XNODE* NETLIST_EXPORTER_XML::makeSymbols( unsigned aCtl )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<wxString> NETLIST_EXPORTER_XML::getComponentClassNamesForAllSymbolUnits(
|
||||||
|
SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSymbolSheet, const SCH_SHEET_LIST& aSheetList )
|
||||||
|
{
|
||||||
|
std::unordered_set<wxString> compClassNames = aSymbol->GetComponentClassNames( &aSymbolSheet );
|
||||||
|
int primaryUnit = aSymbol->GetUnitSelection( &aSymbolSheet );
|
||||||
|
|
||||||
|
if( aSymbol->GetUnitCount() > 1 )
|
||||||
|
{
|
||||||
|
wxString ref = aSymbol->GetRef( &aSymbolSheet );
|
||||||
|
|
||||||
|
for( const SCH_SHEET_PATH& sheet : aSheetList )
|
||||||
|
{
|
||||||
|
for( SCH_ITEM* item : sheet.LastScreen()->Items().OfType( SCH_SYMBOL_T ) )
|
||||||
|
{
|
||||||
|
SCH_SYMBOL* symbol2 = static_cast<SCH_SYMBOL*>( item );
|
||||||
|
|
||||||
|
wxString ref2 = symbol2->GetRef( &sheet );
|
||||||
|
int otherUnit = symbol2->GetUnitSelection( &sheet );
|
||||||
|
|
||||||
|
if( ref2.CmpNoCase( ref ) != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( otherUnit == primaryUnit )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::unordered_set<wxString> otherClassNames =
|
||||||
|
symbol2->GetComponentClassNames( &sheet );
|
||||||
|
compClassNames.insert( otherClassNames.begin(), otherClassNames.end() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<wxString> sortedCompClassNames( compClassNames.begin(), compClassNames.end() );
|
||||||
|
std::sort( sortedCompClassNames.begin(), sortedCompClassNames.end(),
|
||||||
|
[]( const wxString& str1, const wxString& str2 )
|
||||||
|
{
|
||||||
|
return str1.Cmp( str2 ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
return sortedCompClassNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
XNODE* NETLIST_EXPORTER_XML::makeDesignHeader()
|
XNODE* NETLIST_EXPORTER_XML::makeDesignHeader()
|
||||||
{
|
{
|
||||||
SCH_SCREEN* screen;
|
SCH_SCREEN* screen;
|
||||||
|
@ -133,6 +133,14 @@ protected:
|
|||||||
void addSymbolFields( XNODE* aNode, SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSheet,
|
void addSymbolFields( XNODE* aNode, SCH_SYMBOL* aSymbol, const SCH_SHEET_PATH& aSheet,
|
||||||
const SCH_SHEET_LIST& aSheetList);
|
const SCH_SHEET_LIST& aSheetList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all component class names attached to any sub-unit of a given symbol
|
||||||
|
*/
|
||||||
|
std::vector<wxString>
|
||||||
|
getComponentClassNamesForAllSymbolUnits( SCH_SYMBOL* aSymbol,
|
||||||
|
const SCH_SHEET_PATH& aSymbolSheet,
|
||||||
|
const SCH_SHEET_LIST& aSheetList );
|
||||||
|
|
||||||
bool m_resolveTextVars; // Export textVar references resolved
|
bool m_resolveTextVars; // Export textVar references resolved
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -183,13 +183,20 @@ void SCH_FIELD::SetId( int aId )
|
|||||||
// We can't use defined IDs for labels because there can be multiple net class
|
// We can't use defined IDs for labels because there can be multiple net class
|
||||||
// assignments.
|
// assignments.
|
||||||
|
|
||||||
if( GetCanonicalName() == wxT( "Netclass" ) )
|
if( GetCanonicalName() == wxT( "Netclass" )
|
||||||
|
|| GetCanonicalName() == wxT( "Component Class" ) )
|
||||||
|
{
|
||||||
SetLayer( LAYER_NETCLASS_REFS );
|
SetLayer( LAYER_NETCLASS_REFS );
|
||||||
|
}
|
||||||
else if( GetCanonicalName() == wxT( "Intersheetrefs" ) )
|
else if( GetCanonicalName() == wxT( "Intersheetrefs" ) )
|
||||||
|
{
|
||||||
SetLayer( LAYER_INTERSHEET_REFS );
|
SetLayer( LAYER_INTERSHEET_REFS );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
SetLayer( LAYER_FIELDS );
|
SetLayer( LAYER_FIELDS );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1002,7 +1002,7 @@ const BOX2I SCH_LABEL_BASE::GetBoundingBox() const
|
|||||||
|
|
||||||
for( const SCH_FIELD& field : m_fields )
|
for( const SCH_FIELD& field : m_fields )
|
||||||
{
|
{
|
||||||
if( field.IsVisible() )
|
if( field.IsVisible() && field.GetText() != wxEmptyString )
|
||||||
{
|
{
|
||||||
BOX2I fieldBBox = field.GetBoundingBox();
|
BOX2I fieldBBox = field.GetBoundingBox();
|
||||||
|
|
||||||
@ -1734,6 +1734,9 @@ void SCH_DIRECTIVE_LABEL::AutoplaceFields( SCH_SCREEN* aScreen, bool aManual )
|
|||||||
|
|
||||||
for( SCH_FIELD& field : m_fields )
|
for( SCH_FIELD& field : m_fields )
|
||||||
{
|
{
|
||||||
|
if( field.GetText() == wxEmptyString )
|
||||||
|
continue;
|
||||||
|
|
||||||
switch( GetSpinStyle() )
|
switch( GetSpinStyle() )
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -267,6 +267,10 @@ void SCH_RULE_AREA::RefreshContainedItemsAndDirectives(
|
|||||||
addContainedItem( areaItem );
|
addContainedItem( areaItem );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if( areaItem->IsType( { SCH_SYMBOL_T } ) )
|
||||||
|
{
|
||||||
|
addContainedItem( areaItem );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +320,7 @@ const std::unordered_set<SCH_ITEM*>& SCH_RULE_AREA::GetContainedItems() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*> SCH_RULE_AREA::GetDirectives() const
|
const std::unordered_set<SCH_DIRECTIVE_LABEL*>& SCH_RULE_AREA::GetDirectives() const
|
||||||
{
|
{
|
||||||
return m_directives;
|
return m_directives;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public:
|
|||||||
const std::unordered_set<SCH_ITEM*>& GetContainedItems() const;
|
const std::unordered_set<SCH_ITEM*>& GetContainedItems() const;
|
||||||
|
|
||||||
/// @brief Returns the set of all directive labels attached to the rule area border
|
/// @brief Returns the set of all directive labels attached to the rule area border
|
||||||
const std::unordered_set<SCH_DIRECTIVE_LABEL*> GetDirectives() const;
|
const std::unordered_set<SCH_DIRECTIVE_LABEL*>& GetDirectives() const;
|
||||||
|
|
||||||
/// @brief Resolves the netclass of this rule area from connected directive labels
|
/// @brief Resolves the netclass of this rule area from connected directive labels
|
||||||
/// @returns The resolved netclass (if any), and the SCH_ITEM providing the declaration
|
/// @returns The resolved netclass (if any), and the SCH_ITEM providing the declaration
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include <settings/settings_manager.h>
|
#include <settings/settings_manager.h>
|
||||||
#include <sch_plotter.h>
|
#include <sch_plotter.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
#include <sch_rule_area.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -2872,6 +2873,38 @@ bool SCH_SYMBOL::IsNormal() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::unordered_set<wxString> SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const
|
||||||
|
{
|
||||||
|
std::unordered_set<wxString> componentClass;
|
||||||
|
|
||||||
|
auto getComponentClassFields = [&]( const auto& fields )
|
||||||
|
{
|
||||||
|
for( const SCH_FIELD& field : fields )
|
||||||
|
{
|
||||||
|
if( field.GetCanonicalName() == wxT( "Component Class" ) )
|
||||||
|
{
|
||||||
|
if( field.GetShownText( aPath, false ) != wxEmptyString )
|
||||||
|
componentClass.insert( field.GetShownText( aPath, false ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// First get component classes set on the symbol itself
|
||||||
|
getComponentClassFields( m_fields );
|
||||||
|
|
||||||
|
// Now get component classes set on any enclosing rule areas
|
||||||
|
for( const SCH_RULE_AREA* ruleArea : m_rule_areas_cache )
|
||||||
|
{
|
||||||
|
for( const SCH_DIRECTIVE_LABEL* label : ruleArea->GetDirectives() )
|
||||||
|
{
|
||||||
|
getComponentClassFields( label->GetFields() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return componentClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
|
bool SCH_SYMBOL::operator==( const SCH_ITEM& aOther ) const
|
||||||
{
|
{
|
||||||
if( Type() != aOther.Type() )
|
if( Type() != aOther.Type() )
|
||||||
|
@ -901,6 +901,9 @@ public:
|
|||||||
|
|
||||||
double Similarity( const SCH_ITEM& aOther ) const override;
|
double Similarity( const SCH_ITEM& aOther ) const override;
|
||||||
|
|
||||||
|
/// Returns the component classes this symbol belongs in
|
||||||
|
std::unordered_set<wxString> GetComponentClassNames( const SCH_SHEET_PATH* aPath ) const;
|
||||||
|
|
||||||
bool operator==( const SCH_ITEM& aOther ) const override;
|
bool operator==( const SCH_ITEM& aOther ) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -481,10 +481,11 @@ TOOL_ACTION EE_ACTIONS::placeLabel( TOOL_ACTION_ARGS()
|
|||||||
.Icon( BITMAPS::add_label )
|
.Icon( BITMAPS::add_label )
|
||||||
.Flags( AF_ACTIVATE ) );
|
.Flags( AF_ACTIVATE ) );
|
||||||
|
|
||||||
TOOL_ACTION EE_ACTIONS::placeClassLabel( TOOL_ACTION_ARGS()
|
TOOL_ACTION
|
||||||
|
EE_ACTIONS::placeClassLabel( TOOL_ACTION_ARGS()
|
||||||
.Name( "eeschema.InteractiveDrawing.placeClassLabel" )
|
.Name( "eeschema.InteractiveDrawing.placeClassLabel" )
|
||||||
.Scope( AS_GLOBAL )
|
.Scope( AS_GLOBAL )
|
||||||
.FriendlyName( _( "Place Net Class Directives" ) )
|
.FriendlyName( _( "Place Directive Labels" ) )
|
||||||
.Icon( BITMAPS::add_class_flag )
|
.Icon( BITMAPS::add_class_flag )
|
||||||
.Flags( AF_ACTIVATE ) );
|
.Flags( AF_ACTIVATE ) );
|
||||||
|
|
||||||
|
@ -1546,6 +1546,8 @@ SCH_TEXT* SCH_DRAWING_TOOLS::createNewText( const VECTOR2I& aPosition, int aType
|
|||||||
labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
|
labelItem = new SCH_DIRECTIVE_LABEL( aPosition );
|
||||||
labelItem->SetShape( m_lastNetClassFlagShape );
|
labelItem->SetShape( m_lastNetClassFlagShape );
|
||||||
labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
|
labelItem->GetFields().emplace_back( SCH_FIELD( {0,0}, 0, labelItem, wxT( "Netclass" ) ) );
|
||||||
|
labelItem->GetFields().emplace_back(
|
||||||
|
SCH_FIELD( { 0, 0 }, 0, labelItem, wxT( "Component Class" ) ) );
|
||||||
labelItem->GetFields().back().SetItalic( true );
|
labelItem->GetFields().back().SetItalic( true );
|
||||||
labelItem->GetFields().back().SetVisible( true );
|
labelItem->GetFields().back().SetVisible( true );
|
||||||
textItem = labelItem;
|
textItem = labelItem;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
class BOARD;
|
class BOARD;
|
||||||
class BOARD_DESIGN_SETTINGS;
|
class BOARD_DESIGN_SETTINGS;
|
||||||
class BOARD_ITEM_CONTAINER;
|
class BOARD_ITEM_CONTAINER;
|
||||||
|
class COMPONENT_CLASS;
|
||||||
class SHAPE_POLY_SET;
|
class SHAPE_POLY_SET;
|
||||||
class SHAPE_SEGMENT;
|
class SHAPE_SEGMENT;
|
||||||
class PCB_BASE_FRAME;
|
class PCB_BASE_FRAME;
|
||||||
@ -79,11 +80,8 @@ class BOARD_ITEM : public EDA_ITEM
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype, PCB_LAYER_ID aLayer = F_Cu ) :
|
BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype, PCB_LAYER_ID aLayer = F_Cu ) :
|
||||||
EDA_ITEM( aParent, idtype, false, true ),
|
EDA_ITEM( aParent, idtype, false, true ), m_layer( aLayer ), m_isKnockout( false ),
|
||||||
m_layer( aLayer ),
|
m_isLocked( false ), m_group( nullptr ), m_componentClass( nullptr )
|
||||||
m_isKnockout( false ),
|
|
||||||
m_isLocked( false ),
|
|
||||||
m_group( nullptr )
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +417,12 @@ public:
|
|||||||
bool operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const;
|
bool operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetComponentClass( const COMPONENT_CLASS* aClass ) { m_componentClass = aClass; }
|
||||||
|
|
||||||
|
const COMPONENT_CLASS* GetComponentClass() const { return m_componentClass; }
|
||||||
|
|
||||||
|
wxString GetComponentClassAsString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Return a string (to be shown to the user) describing a layer mask.
|
* Return a string (to be shown to the user) describing a layer mask.
|
||||||
@ -434,6 +438,8 @@ protected:
|
|||||||
bool m_isLocked;
|
bool m_isLocked;
|
||||||
|
|
||||||
PCB_GROUP* m_group;
|
PCB_GROUP* m_group;
|
||||||
|
|
||||||
|
const COMPONENT_CLASS* m_componentClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SWIG
|
#ifndef SWIG
|
||||||
|
@ -316,6 +316,7 @@ set( PCBNEW_CLASS_SRCS
|
|||||||
array_pad_number_provider.cpp
|
array_pad_number_provider.cpp
|
||||||
build_BOM_from_board.cpp
|
build_BOM_from_board.cpp
|
||||||
cleanup_item.cpp
|
cleanup_item.cpp
|
||||||
|
component_class_manager.cpp
|
||||||
convert_shape_list_to_polygon.cpp
|
convert_shape_list_to_polygon.cpp
|
||||||
cross-probing.cpp
|
cross-probing.cpp
|
||||||
edit.cpp
|
edit.cpp
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <board_item_container.h>
|
#include <board_item_container.h>
|
||||||
#include <board_stackup_manager/board_stackup.h>
|
#include <board_stackup_manager/board_stackup.h>
|
||||||
|
#include <component_class_manager.h>
|
||||||
#include <embedded_files.h>
|
#include <embedded_files.h>
|
||||||
#include <common.h> // Needed for stl hash extensions
|
#include <common.h> // Needed for stl hash extensions
|
||||||
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
|
#include <convert_shape_list_to_polygon.h> // for OUTLINE_ERROR_HANDLER
|
||||||
@ -1262,6 +1263,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void EmbedFonts() override;
|
void EmbedFonts() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the component class manager
|
||||||
|
*/
|
||||||
|
COMPONENT_CLASS_MANAGER& GetComponentClassManager() { return m_componentClassManager; }
|
||||||
|
|
||||||
// --------- Item order comparators ---------
|
// --------- Item order comparators ---------
|
||||||
|
|
||||||
struct cmp_items
|
struct cmp_items
|
||||||
@ -1377,6 +1383,8 @@ private:
|
|||||||
std::vector<BOARD_LISTENER*> m_listeners;
|
std::vector<BOARD_LISTENER*> m_listeners;
|
||||||
|
|
||||||
bool m_embedFonts;
|
bool m_embedFonts;
|
||||||
|
|
||||||
|
COMPONENT_CLASS_MANAGER m_componentClassManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -374,6 +374,17 @@ wxString BOARD_ITEM::GetParentAsString() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString BOARD_ITEM::GetComponentClassAsString() const
|
||||||
|
{
|
||||||
|
if( m_componentClass )
|
||||||
|
{
|
||||||
|
return m_componentClass->GetFullName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct BOARD_ITEM_DESC
|
static struct BOARD_ITEM_DESC
|
||||||
{
|
{
|
||||||
BOARD_ITEM_DESC()
|
BOARD_ITEM_DESC()
|
||||||
@ -413,6 +424,13 @@ static struct BOARD_ITEM_DESC
|
|||||||
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem );
|
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem );
|
||||||
return item && item->GetBoard() && !item->GetBoard()->IsFootprintHolder();
|
return item && item->GetBoard() && !item->GetBoard()->IsFootprintHolder();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// Used only in DRC engine
|
||||||
|
propMgr.AddProperty( new PROPERTY<BOARD_ITEM, wxString>(
|
||||||
|
_HKI( "ComponentClass" ), NO_SETTER( BOARD_ITEM, wxString ),
|
||||||
|
&BOARD_ITEM::GetComponentClassAsString ) )
|
||||||
|
.SetIsHiddenFromLibraryEditors()
|
||||||
|
.SetIsHiddenFromPropertiesManager();
|
||||||
}
|
}
|
||||||
} _BOARD_ITEM_DESC;
|
} _BOARD_ITEM_DESC;
|
||||||
|
|
||||||
|
145
pcbnew/component_class_manager.cpp
Normal file
145
pcbnew/component_class_manager.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <component_class_manager.h>
|
||||||
|
|
||||||
|
|
||||||
|
void COMPONENT_CLASS::AddConstituentClass( COMPONENT_CLASS* componentClass )
|
||||||
|
{
|
||||||
|
m_constituentClasses.push_back( componentClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool COMPONENT_CLASS::ContainsClassName( const wxString& className ) const
|
||||||
|
{
|
||||||
|
if( m_constituentClasses.size() == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( m_constituentClasses.size() == 1 )
|
||||||
|
return m_name == className;
|
||||||
|
|
||||||
|
return std::any_of( m_constituentClasses.begin(), m_constituentClasses.end(),
|
||||||
|
[&className]( const COMPONENT_CLASS* testClass )
|
||||||
|
{
|
||||||
|
return testClass->GetFullName() == className;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString COMPONENT_CLASS::GetName() const
|
||||||
|
{
|
||||||
|
if( m_constituentClasses.size() == 0 )
|
||||||
|
return wxT( "<None>" );
|
||||||
|
|
||||||
|
if( m_constituentClasses.size() == 1 )
|
||||||
|
return m_name;
|
||||||
|
|
||||||
|
wxASSERT( m_constituentClasses.size() >= 2 );
|
||||||
|
|
||||||
|
wxString name;
|
||||||
|
|
||||||
|
if( m_constituentClasses.size() == 2 )
|
||||||
|
{
|
||||||
|
name.Printf( _( "%s and %s" ), m_constituentClasses[0]->GetName(),
|
||||||
|
m_constituentClasses[1]->GetName() );
|
||||||
|
}
|
||||||
|
else if( m_constituentClasses.size() == 3 )
|
||||||
|
{
|
||||||
|
name.Printf( _( "%s, %s and %s" ), m_constituentClasses[0]->GetName(),
|
||||||
|
m_constituentClasses[1]->GetName(), m_constituentClasses[2]->GetName() );
|
||||||
|
}
|
||||||
|
else if( m_constituentClasses.size() > 3 )
|
||||||
|
{
|
||||||
|
name.Printf( _( "%s, %s and %d more" ), m_constituentClasses[0]->GetName(),
|
||||||
|
m_constituentClasses[1]->GetName(),
|
||||||
|
static_cast<int>( m_constituentClasses.size() - 2 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool COMPONENT_CLASS::IsEmpty() const
|
||||||
|
{
|
||||||
|
return m_constituentClasses.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
COMPONENT_CLASS_MANAGER::COMPONENT_CLASS_MANAGER()
|
||||||
|
{
|
||||||
|
m_noneClass = std::make_unique<COMPONENT_CLASS>( wxEmptyString );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
COMPONENT_CLASS*
|
||||||
|
COMPONENT_CLASS_MANAGER::GetEffectiveComponentClass( std::unordered_set<wxString>& classNames )
|
||||||
|
{
|
||||||
|
if( classNames.size() == 0 )
|
||||||
|
return m_noneClass.get();
|
||||||
|
|
||||||
|
auto getOrCreateClass = [this]( const wxString& className )
|
||||||
|
{
|
||||||
|
if( !m_classes.count( className ) )
|
||||||
|
{
|
||||||
|
std::unique_ptr<COMPONENT_CLASS> newClass =
|
||||||
|
std::make_unique<COMPONENT_CLASS>( className );
|
||||||
|
newClass->AddConstituentClass( newClass.get() );
|
||||||
|
m_classes[className] = std::move( newClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_classes[className].get();
|
||||||
|
};
|
||||||
|
|
||||||
|
if( classNames.size() == 1 )
|
||||||
|
{
|
||||||
|
return getOrCreateClass( *classNames.begin() );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<wxString> sortedClassNames( classNames.begin(), classNames.end() );
|
||||||
|
|
||||||
|
std::sort( sortedClassNames.begin(), sortedClassNames.end(),
|
||||||
|
[]( const wxString& str1, const wxString& str2 )
|
||||||
|
{
|
||||||
|
return str1.Cmp( str2 ) < 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
wxString fullName = sortedClassNames[0];
|
||||||
|
|
||||||
|
for( std::size_t i = 1; i < sortedClassNames.size(); ++i )
|
||||||
|
{
|
||||||
|
fullName += ",";
|
||||||
|
fullName += sortedClassNames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_effectiveClasses.count( fullName ) )
|
||||||
|
{
|
||||||
|
std::unique_ptr<COMPONENT_CLASS> effClass = std::make_unique<COMPONENT_CLASS>( fullName );
|
||||||
|
|
||||||
|
for( const wxString& className : sortedClassNames )
|
||||||
|
{
|
||||||
|
effClass->AddConstituentClass( getOrCreateClass( className ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_effectiveClasses[fullName] = std::move( effClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_effectiveClasses[fullName].get();
|
||||||
|
}
|
100
pcbnew/component_class_manager.h
Normal file
100
pcbnew/component_class_manager.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||||
|
#define PCBNEW_COMPONENT_CLASS_MANAGER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include <board_item.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A lightweight representation of a component class. The membership within
|
||||||
|
* m_consituentClasses allows determination of the type of class this is:
|
||||||
|
*
|
||||||
|
* m_constituentClasses.size() == 0: This is a null class (no assigment).
|
||||||
|
* m_name is empty.
|
||||||
|
* m_constituentClasses.size() == 1: This is an atomic class. The constituent class
|
||||||
|
* pointer refers to itself. m_name contains the name of the atomic class
|
||||||
|
* m_constituentClasses.size() > 1: This is a composite class. The constituent class
|
||||||
|
* pointers refer to all atomic members. m_name contains a comma-delimited list of
|
||||||
|
* all atomic member class names.
|
||||||
|
*/
|
||||||
|
class COMPONENT_CLASS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
COMPONENT_CLASS( const wxString& name ) : m_name( name ) {}
|
||||||
|
|
||||||
|
/// Fetches the display name of this component class
|
||||||
|
wxString GetName() const;
|
||||||
|
|
||||||
|
/// Fetches the full name of this component class
|
||||||
|
const wxString& GetFullName() const { return m_name; }
|
||||||
|
|
||||||
|
/// Adds a constituent component class to an effective component class
|
||||||
|
void AddConstituentClass( COMPONENT_CLASS* componentClass );
|
||||||
|
|
||||||
|
/// Determines if this (effective) component class contains a specific sub-class
|
||||||
|
bool ContainsClassName( const wxString& className ) const;
|
||||||
|
|
||||||
|
/// Determines if this (effective) component class is empty (i.e. no classes defined)
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
/// Fetches a vector of the constituent classes for this (effective) class
|
||||||
|
const std::vector<COMPONENT_CLASS*>& GetConstituentClasses() const
|
||||||
|
{
|
||||||
|
return m_constituentClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// The full name of the component class
|
||||||
|
wxString m_name;
|
||||||
|
|
||||||
|
/// The COMPONENT_CLASS objects contributing to this complete component class
|
||||||
|
std::vector<COMPONENT_CLASS*> m_constituentClasses;
|
||||||
|
};
|
||||||
|
|
||||||
|
class COMPONENT_CLASS_MANAGER
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
COMPONENT_CLASS_MANAGER();
|
||||||
|
|
||||||
|
/// @brief Gets an effective component class for the given constituent class names
|
||||||
|
/// @param classes The names of the constituent component classes
|
||||||
|
/// @return Effective COMPONENT_CLASS object
|
||||||
|
COMPONENT_CLASS* GetEffectiveComponentClass( std::unordered_set<wxString>& classNames );
|
||||||
|
|
||||||
|
/// Returns the unassigned component class
|
||||||
|
const COMPONENT_CLASS* GetNoneComponentClass() const { return m_noneClass.get(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// All individual component classes
|
||||||
|
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_classes;
|
||||||
|
|
||||||
|
/// Generated effective component classes
|
||||||
|
std::unordered_map<wxString, std::unique_ptr<COMPONENT_CLASS>> m_effectiveClasses;
|
||||||
|
|
||||||
|
/// The class to represent an unassigned component class
|
||||||
|
std::unique_ptr<COMPONENT_CLASS> m_noneClass;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1584,6 +1584,11 @@ void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
|
|||||||
aList.emplace_back( _( "Rotation" ), wxString::Format( wxT( "%.4g" ),
|
aList.emplace_back( _( "Rotation" ), wxString::Format( wxT( "%.4g" ),
|
||||||
GetOrientation().AsDegrees() ) );
|
GetOrientation().AsDegrees() ) );
|
||||||
|
|
||||||
|
if( m_componentClass )
|
||||||
|
{
|
||||||
|
aList.emplace_back( _( "Component Class" ), m_componentClass->GetName() );
|
||||||
|
}
|
||||||
|
|
||||||
msg.Printf( _( "Footprint: %s" ), m_fpid.GetUniStringLibId() );
|
msg.Printf( _( "Footprint: %s" ), m_fpid.GetUniStringLibId() );
|
||||||
msg2.Printf( _( "3D-Shape: %s" ), m_3D_Drawings.empty() ? _( "<none>" )
|
msg2.Printf( _( "3D-Shape: %s" ), m_3D_Drawings.empty() ? _( "<none>" )
|
||||||
: m_3D_Drawings.front().m_Filename );
|
: m_3D_Drawings.front().m_Filename );
|
||||||
|
@ -147,6 +147,7 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
|||||||
}
|
}
|
||||||
|
|
||||||
FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
|
FOOTPRINT* footprint = m_frame->LoadFootprint( aComponent->GetFPID() );
|
||||||
|
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||||
|
|
||||||
if( footprint == nullptr )
|
if( footprint == nullptr )
|
||||||
{
|
{
|
||||||
@ -201,6 +202,40 @@ FOOTPRINT* BOARD_NETLIST_UPDATER::addNewFootprint( COMPONENT* aComponent )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BOARD_NETLIST_UPDATER::updateComponentClass( FOOTPRINT* aFootprint, COMPONENT* aNewComponent )
|
||||||
|
{
|
||||||
|
// Get the existing component class
|
||||||
|
wxString curClassName;
|
||||||
|
|
||||||
|
if( const COMPONENT_CLASS* curClass = aFootprint->GetComponentClass() )
|
||||||
|
curClassName = curClass->GetFullName();
|
||||||
|
|
||||||
|
// Calculate the new component class
|
||||||
|
COMPONENT_CLASS* newClass = m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||||
|
aNewComponent->GetComponentClassNames() );
|
||||||
|
wxString newClassName = newClass->GetFullName();
|
||||||
|
|
||||||
|
if( curClassName == newClassName )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString msg;
|
||||||
|
|
||||||
|
if( m_isDryRun )
|
||||||
|
{
|
||||||
|
msg.Printf( _( "Change %s component class from %s to %s." ), aFootprint->GetReference(),
|
||||||
|
curClassName, newClassName );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFootprint->SetComponentClass( newClass );
|
||||||
|
msg.Printf( _( "Changed %s component class from %s to %s." ), aFootprint->GetReference(),
|
||||||
|
curClassName, newClassName );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_reporter->Report( msg, RPT_SEVERITY_ACTION );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FOOTPRINT* BOARD_NETLIST_UPDATER::replaceFootprint( NETLIST& aNetlist, FOOTPRINT* aFootprint,
|
FOOTPRINT* BOARD_NETLIST_UPDATER::replaceFootprint( NETLIST& aNetlist, FOOTPRINT* aFootprint,
|
||||||
COMPONENT* aNewComponent )
|
COMPONENT* aNewComponent )
|
||||||
{
|
{
|
||||||
@ -395,8 +430,11 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
|
|||||||
for( PCB_FIELD* field : aPcbFootprint->GetFields() )
|
for( PCB_FIELD* field : aPcbFootprint->GetFields() )
|
||||||
{
|
{
|
||||||
// These fields are individually checked above
|
// These fields are individually checked above
|
||||||
if( field->IsReference() || field->IsValue() || field->IsFootprint() )
|
if( field->IsReference() || field->IsValue() || field->IsFootprint()
|
||||||
|
|| field->IsComponentClass() )
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
fpFieldsAsMap[field->GetName()] = field->GetText();
|
fpFieldsAsMap[field->GetName()] = field->GetText();
|
||||||
}
|
}
|
||||||
@ -407,6 +445,9 @@ bool BOARD_NETLIST_UPDATER::updateFootprintParameters( FOOTPRINT* aPcbFootprint,
|
|||||||
compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
|
compFields.erase( GetCanonicalFieldName( VALUE_FIELD ) );
|
||||||
compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
|
compFields.erase( GetCanonicalFieldName( FOOTPRINT_FIELD ) );
|
||||||
|
|
||||||
|
// Remove any component class fields - these are not editable in the pcb editor
|
||||||
|
compFields.erase( wxT( "Component Class" ) );
|
||||||
|
|
||||||
// Fields are stored as an ordered map, but we don't (yet) support reordering
|
// Fields are stored as an ordered map, but we don't (yet) support reordering
|
||||||
// the footprint fields to match the symbol, so we manually check the fields
|
// the footprint fields to match the symbol, so we manually check the fields
|
||||||
// in the order they are stored in the symbol.
|
// in the order they are stored in the symbol.
|
||||||
@ -1214,6 +1255,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
|||||||
|
|
||||||
updateFootprintParameters( tmp, component );
|
updateFootprintParameters( tmp, component );
|
||||||
updateComponentPadConnections( tmp, component );
|
updateComponentPadConnections( tmp, component );
|
||||||
|
updateComponentClass( tmp, component );
|
||||||
}
|
}
|
||||||
|
|
||||||
matchCount++;
|
matchCount++;
|
||||||
@ -1236,6 +1278,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
|||||||
|
|
||||||
updateFootprintParameters( footprint, component );
|
updateFootprintParameters( footprint, component );
|
||||||
updateComponentPadConnections( footprint, component );
|
updateComponentPadConnections( footprint, component );
|
||||||
|
updateComponentClass( footprint, component );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( matchCount > 1 )
|
else if( matchCount > 1 )
|
||||||
|
@ -111,6 +111,8 @@ private:
|
|||||||
|
|
||||||
bool updateComponentPadConnections( FOOTPRINT* aFootprint, COMPONENT* aNewComponent );
|
bool updateComponentPadConnections( FOOTPRINT* aFootprint, COMPONENT* aNewComponent );
|
||||||
|
|
||||||
|
void updateComponentClass( FOOTPRINT* aFootprint, COMPONENT* aNewComponent );
|
||||||
|
|
||||||
void cacheCopperZoneConnections();
|
void cacheCopperZoneConnections();
|
||||||
|
|
||||||
bool updateCopperZoneNets( NETLIST& aNetlist );
|
bool updateCopperZoneNets( NETLIST& aNetlist );
|
||||||
|
@ -287,6 +287,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
|||||||
* (libsource (lib conn) (part DB25))
|
* (libsource (lib conn) (part DB25))
|
||||||
* (property (name PINCOUNT) (value 25))
|
* (property (name PINCOUNT) (value 25))
|
||||||
* (sheetpath (names /) (tstamps /))
|
* (sheetpath (names /) (tstamps /))
|
||||||
|
* (component_classes (class (name "CLASS")))
|
||||||
* (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647))
|
* (tstamp 68183921-93a5-49ac-91b0-49d05a0e1647))
|
||||||
*
|
*
|
||||||
* other fields (unused) are skipped
|
* other fields (unused) are skipped
|
||||||
@ -305,6 +306,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
|||||||
std::vector<KIID> uuids;
|
std::vector<KIID> uuids;
|
||||||
std::map<wxString, wxString> properties;
|
std::map<wxString, wxString> properties;
|
||||||
nlohmann::ordered_map<wxString, wxString> fields;
|
nlohmann::ordered_map<wxString, wxString> fields;
|
||||||
|
std::unordered_set<wxString> componentClasses;
|
||||||
|
|
||||||
// The token comp was read, so the next data is (ref P1)
|
// The token comp was read, so the next data is (ref P1)
|
||||||
while( (token = NextTok() ) != T_RIGHT )
|
while( (token = NextTok() ) != T_RIGHT )
|
||||||
@ -469,6 +471,24 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_component_classes:
|
||||||
|
{
|
||||||
|
while( ( token = NextTok() ) != T_RIGHT )
|
||||||
|
{
|
||||||
|
if( token != T_LEFT )
|
||||||
|
Expecting( T_LEFT );
|
||||||
|
|
||||||
|
if( ( token = NextTok() ) != T_class )
|
||||||
|
Expecting( T_class );
|
||||||
|
|
||||||
|
NeedSYMBOLorNUMBER();
|
||||||
|
componentClasses.insert( From_UTF8( CurText() ) );
|
||||||
|
NeedRIGHT();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Skip not used data (i.e all other tokens)
|
// Skip not used data (i.e all other tokens)
|
||||||
skipCurrent();
|
skipCurrent();
|
||||||
@ -491,6 +511,7 @@ void KICAD_NETLIST_PARSER::parseComponent()
|
|||||||
component->SetProperties( properties );
|
component->SetProperties( properties );
|
||||||
component->SetFields( fields );
|
component->SetFields( fields );
|
||||||
component->SetHumanReadablePath( humanSheetPath );
|
component->SetHumanReadablePath( humanSheetPath );
|
||||||
|
component->SetComponentClassNames( componentClasses );
|
||||||
m_netlist->AddComponent( component );
|
m_netlist->AddComponent( component );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
#include <wx/arrstr.h>
|
#include <wx/arrstr.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <lib_id.h>
|
#include <lib_id.h>
|
||||||
#include <footprint.h>
|
#include <footprint.h>
|
||||||
@ -175,6 +176,13 @@ public:
|
|||||||
void SetHumanReadablePath( const wxString& aPath ) { m_humanReadablePath = aPath; }
|
void SetHumanReadablePath( const wxString& aPath ) { m_humanReadablePath = aPath; }
|
||||||
const wxString& GetHumanReadablePath() const { return m_humanReadablePath; }
|
const wxString& GetHumanReadablePath() const { return m_humanReadablePath; }
|
||||||
|
|
||||||
|
void SetComponentClassNames( const std::unordered_set<wxString>& aClassNames )
|
||||||
|
{
|
||||||
|
m_componentClassNames = aClassNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<wxString>& GetComponentClassNames() { return m_componentClassNames; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<COMPONENT_NET> m_nets; ///< list of nets shared by the component pins
|
std::vector<COMPONENT_NET> m_nets; ///< list of nets shared by the component pins
|
||||||
|
|
||||||
@ -215,6 +223,9 @@ private:
|
|||||||
/// Component-specific user fields found in the netlist.
|
/// Component-specific user fields found in the netlist.
|
||||||
nlohmann::ordered_map<wxString, wxString> m_fields;
|
nlohmann::ordered_map<wxString, wxString> m_fields;
|
||||||
|
|
||||||
|
/// Component classes for this footprint
|
||||||
|
std::unordered_set<wxString> m_componentClassNames;
|
||||||
|
|
||||||
static COMPONENT_NET m_emptyNet;
|
static COMPONENT_NET m_emptyNet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2484,6 +2484,7 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
|
|||||||
aNew->SetSheetfile( aExisting->GetSheetfile() );
|
aNew->SetSheetfile( aExisting->GetSheetfile() );
|
||||||
aNew->SetSheetname( aExisting->GetSheetname() );
|
aNew->SetSheetname( aExisting->GetSheetname() );
|
||||||
aNew->SetFilters( aExisting->GetFilters() );
|
aNew->SetFilters( aExisting->GetFilters() );
|
||||||
|
aNew->SetComponentClass( aExisting->GetComponentClass() );
|
||||||
|
|
||||||
aCommit.Remove( aExisting );
|
aCommit.Remove( aExisting );
|
||||||
aCommit.Add( aNew );
|
aCommit.Add( aNew );
|
||||||
|
@ -71,6 +71,7 @@ public:
|
|||||||
bool IsValue() const { return m_id == VALUE_FIELD; }
|
bool IsValue() const { return m_id == VALUE_FIELD; }
|
||||||
bool IsFootprint() const { return m_id == FOOTPRINT_FIELD; }
|
bool IsFootprint() const { return m_id == FOOTPRINT_FIELD; }
|
||||||
bool IsDatasheet() const { return m_id == DATASHEET_FIELD; }
|
bool IsDatasheet() const { return m_id == DATASHEET_FIELD; }
|
||||||
|
bool IsComponentClass() const { return GetName() == wxT( "Component Class" ); }
|
||||||
|
|
||||||
bool IsMandatoryField() const { return m_id < MANDATORY_FIELDS; }
|
bool IsMandatoryField() const { return m_id < MANDATORY_FIELDS; }
|
||||||
|
|
||||||
|
@ -1214,6 +1214,22 @@ void PCB_IO_KICAD_SEXPR::format( const FOOTPRINT* aFootprint, int aNestLevel ) c
|
|||||||
m_out->Print( aNestLevel + 1, ")\n" );
|
m_out->Print( aNestLevel + 1, ")\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( const COMPONENT_CLASS* compClass = aFootprint->GetComponentClass() )
|
||||||
|
{
|
||||||
|
if( !compClass->IsEmpty() )
|
||||||
|
{
|
||||||
|
m_out->Print( aNestLevel + 1, "(component_classes\n" );
|
||||||
|
|
||||||
|
for( const COMPONENT_CLASS* constituent : compClass->GetConstituentClasses() )
|
||||||
|
{
|
||||||
|
m_out->Print( aNestLevel + 2, "(class %s)\n",
|
||||||
|
m_out->Quotew( constituent->GetFullName() ).c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_out->Print( aNestLevel + 1, ")\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( !aFootprint->GetFilters().empty() )
|
if( !aFootprint->GetFilters().empty() )
|
||||||
{
|
{
|
||||||
m_out->Print( aNestLevel + 1, "(property ki_fp_filters %s)\n",
|
m_out->Print( aNestLevel + 1, "(property ki_fp_filters %s)\n",
|
||||||
|
@ -161,7 +161,8 @@ class PCB_IO_KICAD_SEXPR; // forward decl
|
|||||||
//#define SEXPR_BOARD_FILE_VERSION 20240617 // Table angles
|
//#define SEXPR_BOARD_FILE_VERSION 20240617 // Table angles
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20240703 // User layer types
|
//#define SEXPR_BOARD_FILE_VERSION 20240703 // User layer types
|
||||||
//#define SEXPR_BOARD_FILE_VERSION 20240706 // Embedded Files
|
//#define SEXPR_BOARD_FILE_VERSION 20240706 // Embedded Files
|
||||||
#define SEXPR_BOARD_FILE_VERSION 20240819 // Embedded Files - Update hash algorithm to Murmur3
|
//#define SEXPR_BOARD_FILE_VERSION 20240819 // Embedded Files - Update hash algorithm to Murmur3
|
||||||
|
#define SEXPR_BOARD_FILE_VERSION 20240928 // Component classes
|
||||||
|
|
||||||
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
|
||||||
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
|
||||||
|
@ -4281,6 +4281,11 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
|||||||
|
|
||||||
footprint->SetInitialComments( aInitialComments );
|
footprint->SetInitialComments( aInitialComments );
|
||||||
|
|
||||||
|
if( m_board )
|
||||||
|
{
|
||||||
|
footprint->SetComponentClass( m_board->GetComponentClassManager().GetNoneComponentClass() );
|
||||||
|
}
|
||||||
|
|
||||||
token = NextTok();
|
token = NextTok();
|
||||||
|
|
||||||
if( !IsSymbol( token ) && token != T_NUMBER )
|
if( !IsSymbol( token ) && token != T_NUMBER )
|
||||||
@ -4773,13 +4778,41 @@ FOOTPRINT* PCB_IO_KICAD_SEXPR_PARSER::parseFOOTPRINT_unchecked( wxArrayString* a
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case T_component_classes:
|
||||||
|
{
|
||||||
|
std::unordered_set<wxString> componentClassNames;
|
||||||
|
|
||||||
|
while( ( token = NextTok() ) != T_RIGHT )
|
||||||
|
{
|
||||||
|
if( token != T_LEFT )
|
||||||
|
Expecting( T_LEFT );
|
||||||
|
|
||||||
|
if( ( token = NextTok() ) != T_class )
|
||||||
|
Expecting( T_class );
|
||||||
|
|
||||||
|
NeedSYMBOLorNUMBER();
|
||||||
|
componentClassNames.insert( From_UTF8( CurText() ) );
|
||||||
|
NeedRIGHT();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_board )
|
||||||
|
{
|
||||||
|
const COMPONENT_CLASS* componentClass =
|
||||||
|
m_board->GetComponentClassManager().GetEffectiveComponentClass(
|
||||||
|
componentClassNames );
|
||||||
|
footprint->SetComponentClass( componentClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Expecting( "at, descr, locked, placed, tedit, tstamp, uuid, "
|
Expecting( "at, descr, locked, placed, tedit, tstamp, uuid, "
|
||||||
"autoplace_cost90, autoplace_cost180, attr, clearance, "
|
"autoplace_cost90, autoplace_cost180, attr, clearance, "
|
||||||
"embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
|
"embedded_files, fp_arc, fp_circle, fp_curve, fp_line, fp_poly, "
|
||||||
"fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
|
"fp_rect, fp_text, pad, group, generator, model, path, solder_mask_margin, "
|
||||||
"solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
|
"solder_paste_margin, solder_paste_margin_ratio, tags, thermal_gap, "
|
||||||
"version, zone, or zone_connect" );
|
"version, zone, zone_connect, or component_classes" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +165,65 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PCBEXPR_COMPONENT_CLASS_VALUE : public LIBEVAL::VALUE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PCBEXPR_COMPONENT_CLASS_VALUE( BOARD_ITEM* aItem ) :
|
||||||
|
LIBEVAL::VALUE( wxEmptyString ), m_item( aItem ){};
|
||||||
|
|
||||||
|
const wxString& AsString() const override
|
||||||
|
{
|
||||||
|
const COMPONENT_CLASS* compClass = m_item->GetComponentClass();
|
||||||
|
|
||||||
|
if( compClass )
|
||||||
|
{
|
||||||
|
const_cast<PCBEXPR_COMPONENT_CLASS_VALUE*>( this )->Set( compClass->GetFullName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBEVAL::VALUE::AsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EqualTo( LIBEVAL::CONTEXT* aCtx, const VALUE* b ) const override
|
||||||
|
{
|
||||||
|
if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue =
|
||||||
|
dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
|
||||||
|
{
|
||||||
|
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||||
|
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||||
|
|
||||||
|
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||||
|
// of all unique component class objects
|
||||||
|
return aClass == bClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return LIBEVAL::VALUE::EqualTo( aCtx, b );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NotEqualTo( LIBEVAL::CONTEXT* aCtx, const LIBEVAL::VALUE* b ) const override
|
||||||
|
{
|
||||||
|
if( const PCBEXPR_COMPONENT_CLASS_VALUE* bValue =
|
||||||
|
dynamic_cast<const PCBEXPR_COMPONENT_CLASS_VALUE*>( b ) )
|
||||||
|
{
|
||||||
|
const COMPONENT_CLASS* aClass = m_item->GetComponentClass();
|
||||||
|
const COMPONENT_CLASS* bClass = bValue->m_item->GetComponentClass();
|
||||||
|
|
||||||
|
// Note this depends on COMPONENT_CLASS_MANAGER maintaining ownership
|
||||||
|
// of all unique component class objects
|
||||||
|
return aClass != bClass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return LIBEVAL::VALUE::NotEqualTo( aCtx, b );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BOARD_ITEM* m_item;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class PCBEXPR_NET_VALUE : public LIBEVAL::VALUE
|
class PCBEXPR_NET_VALUE : public LIBEVAL::VALUE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -279,6 +338,17 @@ LIBEVAL::VALUE* PCBEXPR_NETCLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LIBEVAL::VALUE* PCBEXPR_COMPONENT_CLASS_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( GetObject( aCtx ) );
|
||||||
|
|
||||||
|
if( !item || item->Type() != PCB_FOOTPRINT_T )
|
||||||
|
return new LIBEVAL::VALUE();
|
||||||
|
|
||||||
|
return new PCBEXPR_COMPONENT_CLASS_VALUE( item );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LIBEVAL::VALUE* PCBEXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
LIBEVAL::VALUE* PCBEXPR_NETNAME_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
|
||||||
{
|
{
|
||||||
BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
|
BOARD_CONNECTED_ITEM* item = dynamic_cast<BOARD_CONNECTED_ITEM*>( GetObject( aCtx ) );
|
||||||
@ -326,6 +396,15 @@ std::unique_ptr<LIBEVAL::VAR_REF> PCBEXPR_UCODE::CreateVarRef( const wxString& a
|
|||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
else if( aField.CmpNoCase( wxT( "ComponentClass" ) ) == 0 )
|
||||||
|
{
|
||||||
|
if( aVar == wxT( "A" ) )
|
||||||
|
return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 0 );
|
||||||
|
else if( aVar == wxT( "B" ) )
|
||||||
|
return std::make_unique<PCBEXPR_COMPONENT_CLASS_REF>( 1 );
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
else if( aField.CmpNoCase( wxT( "NetName" ) ) == 0 )
|
else if( aField.CmpNoCase( wxT( "NetName" ) ) == 0 )
|
||||||
{
|
{
|
||||||
if( aVar == wxT( "A" ) )
|
if( aVar == wxT( "A" ) )
|
||||||
|
@ -127,6 +127,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// "Object code" version of a component class reference (for performance).
|
||||||
|
class PCBEXPR_COMPONENT_CLASS_REF : public PCBEXPR_VAR_REF
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PCBEXPR_COMPONENT_CLASS_REF( int aItemIndex ) : PCBEXPR_VAR_REF( aItemIndex )
|
||||||
|
{
|
||||||
|
SetType( LIBEVAL::VT_STRING );
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBEVAL::VALUE* GetValue( LIBEVAL::CONTEXT* aCtx ) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// "Object code" version of a netname reference (for performance).
|
// "Object code" version of a netname reference (for performance).
|
||||||
class PCBEXPR_NETNAME_REF : public PCBEXPR_VAR_REF
|
class PCBEXPR_NETNAME_REF : public PCBEXPR_VAR_REF
|
||||||
{
|
{
|
||||||
|
@ -1208,6 +1208,42 @@ static void hasNetclassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hasComponentClassFunc( LIBEVAL::CONTEXT* aCtx, void* self )
|
||||||
|
{
|
||||||
|
LIBEVAL::VALUE* arg = aCtx->Pop();
|
||||||
|
LIBEVAL::VALUE* result = aCtx->AllocValue();
|
||||||
|
|
||||||
|
result->Set( 0.0 );
|
||||||
|
aCtx->Push( result );
|
||||||
|
|
||||||
|
if( !arg || arg->AsString().IsEmpty() )
|
||||||
|
{
|
||||||
|
if( aCtx->HasErrorCallback() )
|
||||||
|
aCtx->ReportError(
|
||||||
|
_( "Missing component class name argument to hasComponentClass()" ) );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCBEXPR_VAR_REF* vref = static_cast<PCBEXPR_VAR_REF*>( self );
|
||||||
|
BOARD_ITEM* item = vref ? vref->GetObject( aCtx ) : nullptr;
|
||||||
|
|
||||||
|
if( !item )
|
||||||
|
return;
|
||||||
|
|
||||||
|
result->SetDeferredEval(
|
||||||
|
[item, arg]() -> double
|
||||||
|
{
|
||||||
|
BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( item );
|
||||||
|
const COMPONENT_CLASS* compClass = boardItem->GetComponentClass();
|
||||||
|
|
||||||
|
if( compClass && compClass->ContainsClassName( arg->AsString() ) )
|
||||||
|
return 1.0;
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PCBEXPR_BUILTIN_FUNCTIONS::PCBEXPR_BUILTIN_FUNCTIONS()
|
PCBEXPR_BUILTIN_FUNCTIONS::PCBEXPR_BUILTIN_FUNCTIONS()
|
||||||
{
|
{
|
||||||
@ -1249,4 +1285,5 @@ void PCBEXPR_BUILTIN_FUNCTIONS::RegisterAllFunctions()
|
|||||||
RegisterFunc( wxT( "getField('x')" ), getFieldFunc );
|
RegisterFunc( wxT( "getField('x')" ), getFieldFunc );
|
||||||
|
|
||||||
RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc );
|
RegisterFunc( wxT( "hasNetclass('x')" ), hasNetclassFunc );
|
||||||
|
RegisterFunc( wxT( "hasComponentClass('x')" ), hasComponentClassFunc );
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
(kicad_pcb (version 20240928) (generator "pcbnew") (generator_version "8.99")
|
||||||
|
)
|
@ -0,0 +1,428 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"3dviewports": [],
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {},
|
||||||
|
"diff_pair_dimensions": [],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"rules": {},
|
||||||
|
"track_widths": [],
|
||||||
|
"via_dimensions": []
|
||||||
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
|
"layer_presets": [],
|
||||||
|
"viewports": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"pin_map": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rule_severities": {
|
||||||
|
"bus_definition_conflict": "error",
|
||||||
|
"bus_entry_needed": "error",
|
||||||
|
"bus_to_bus_conflict": "error",
|
||||||
|
"bus_to_net_conflict": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"endpoint_off_grid": "warning",
|
||||||
|
"extra_units": "error",
|
||||||
|
"footprint_filter": "ignore",
|
||||||
|
"footprint_link_issues": "warning",
|
||||||
|
"four_way_junction": "ignore",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_multiple_wires": "warning",
|
||||||
|
"lib_symbol_issues": "warning",
|
||||||
|
"lib_symbol_mismatch": "warning",
|
||||||
|
"missing_bidi_pin": "warning",
|
||||||
|
"missing_input_pin": "warning",
|
||||||
|
"missing_power_pin": "error",
|
||||||
|
"missing_unit": "warning",
|
||||||
|
"multiple_net_names": "warning",
|
||||||
|
"net_not_bus_member": "warning",
|
||||||
|
"no_connect_connected": "warning",
|
||||||
|
"no_connect_dangling": "warning",
|
||||||
|
"pin_not_connected": "error",
|
||||||
|
"pin_not_driven": "error",
|
||||||
|
"pin_to_pin": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"same_local_global_label": "warning",
|
||||||
|
"similar_label_and_power": "warning",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"similar_power": "warning",
|
||||||
|
"simulation_model_issue": "ignore",
|
||||||
|
"single_global_label": "ignore",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unconnected_wire_endpoint": "warning",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "component_classes.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": -1,
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.2,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.3,
|
||||||
|
"wire_width": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 4
|
||||||
|
},
|
||||||
|
"net_colors": null,
|
||||||
|
"netclass_assignments": null,
|
||||||
|
"netclass_patterns": []
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"plot": "",
|
||||||
|
"pos_files": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"svg": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||||
|
"bom_fmt_presets": [],
|
||||||
|
"bom_fmt_settings": {
|
||||||
|
"field_delimiter": ",",
|
||||||
|
"keep_line_breaks": false,
|
||||||
|
"keep_tabs": false,
|
||||||
|
"name": "CSV",
|
||||||
|
"ref_delimiter": ",",
|
||||||
|
"ref_range_delimiter": "",
|
||||||
|
"string_delimiter": "\""
|
||||||
|
},
|
||||||
|
"bom_presets": [],
|
||||||
|
"bom_settings": {
|
||||||
|
"exclude_dnp": false,
|
||||||
|
"fields_ordered": [
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Reference",
|
||||||
|
"name": "Reference",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Qty",
|
||||||
|
"name": "${QUANTITY}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Value",
|
||||||
|
"name": "Value",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "DNP",
|
||||||
|
"name": "${DNP}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from BOM",
|
||||||
|
"name": "${EXCLUDE_FROM_BOM}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from Board",
|
||||||
|
"name": "${EXCLUDE_FROM_BOARD}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Footprint",
|
||||||
|
"name": "Footprint",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Datasheet",
|
||||||
|
"name": "Datasheet",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Description",
|
||||||
|
"name": "Description",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "#",
|
||||||
|
"name": "${ITEM_NUMBER}",
|
||||||
|
"show": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filter_string": "",
|
||||||
|
"group_symbols": true,
|
||||||
|
"include_excluded_from_bom": true,
|
||||||
|
"name": "",
|
||||||
|
"sort_asc": true,
|
||||||
|
"sort_field": "Reference"
|
||||||
|
},
|
||||||
|
"connection_grid_size": 50.0,
|
||||||
|
"drawing": {
|
||||||
|
"dashed_lines_dash_length_ratio": 12.0,
|
||||||
|
"dashed_lines_gap_length_ratio": 3.0,
|
||||||
|
"default_line_thickness": 6.0,
|
||||||
|
"default_text_size": 50.0,
|
||||||
|
"field_names": [],
|
||||||
|
"intersheets_ref_own_page": false,
|
||||||
|
"intersheets_ref_prefix": "",
|
||||||
|
"intersheets_ref_short": false,
|
||||||
|
"intersheets_ref_show": false,
|
||||||
|
"intersheets_ref_suffix": "",
|
||||||
|
"junction_size_choice": 3,
|
||||||
|
"label_size_ratio": 0.375,
|
||||||
|
"operating_point_overlay_i_precision": 3,
|
||||||
|
"operating_point_overlay_i_range": "~A",
|
||||||
|
"operating_point_overlay_v_precision": 3,
|
||||||
|
"operating_point_overlay_v_range": "~V",
|
||||||
|
"overbar_offset_ratio": 1.23,
|
||||||
|
"pin_symbol_size": 25.0,
|
||||||
|
"text_offset_ratio": 0.15
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "KiCad",
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"space_save_all_events": true,
|
||||||
|
"spice_current_sheet_as_root": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"spice_model_current_sheet_as_root": true,
|
||||||
|
"spice_save_all_currents": false,
|
||||||
|
"spice_save_all_dissipations": false,
|
||||||
|
"spice_save_all_voltages": false,
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
@ -0,0 +1,610 @@
|
|||||||
|
(kicad_sch
|
||||||
|
(version 20240819)
|
||||||
|
(generator "eeschema")
|
||||||
|
(generator_version "8.99")
|
||||||
|
(uuid "bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd")
|
||||||
|
(paper "A4")
|
||||||
|
(lib_symbols
|
||||||
|
(symbol "Amplifier_Operational:TL072"
|
||||||
|
(pin_names
|
||||||
|
(offset 0.127)
|
||||||
|
)
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "U"
|
||||||
|
(at 0 5.08 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(justify left)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "TL072"
|
||||||
|
(at 0 -5.08 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(justify left)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "ki_locked" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "ki_keywords" "dual opamp"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "ki_fp_filters" "SOIC*3.9x4.9mm*P1.27mm* DIP*W7.62mm* TO*99* OnSemi*Micro8* TSSOP*3x3mm*P0.65mm* TSSOP*4.4x3mm*P0.65mm* MSOP*3x3mm*P0.65mm* SSOP*3.9x4.9mm*P0.635mm* LFCSP*2x2mm*P0.5mm* *SIP* SOIC*5.3x6.2mm*P1.27mm*"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "TL072_1_1"
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -5.08 5.08) (xy 5.08 0) (xy -5.08 -5.08) (xy -5.08 5.08)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -7.62 2.54 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "+"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -7.62 -2.54 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "-"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 0 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "~"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "TL072_2_1"
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -5.08 5.08) (xy 5.08 0) (xy -5.08 -5.08) (xy -5.08 5.08)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -7.62 2.54 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "+"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "5"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -7.62 -2.54 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "-"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "6"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 0 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "~"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "7"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "TL072_3_1"
|
||||||
|
(pin power_in line
|
||||||
|
(at -2.54 7.62 270)
|
||||||
|
(length 3.81)
|
||||||
|
(name "V+"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "8"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at -2.54 -7.62 90)
|
||||||
|
(length 3.81)
|
||||||
|
(name "V-"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "4"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(text "U1A: Has a \"Component Class\" field\nU2A: Assigned a Component Class from the SCH_RULE_AREA\nU3A: No class assigned\n\nResult in netlist: U1 has two Component Class names: Class1 and Class2"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(at 107.442 98.298 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(uuid "bfaf99ba-b9bc-483a-9a28-c01a662202e4")
|
||||||
|
)
|
||||||
|
(rule_area
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 104.14 45.72) (xy 139.7 45.72) (xy 139.7 80.01) (xy 104.14 80.01)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type dash)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
(uuid 25809b47-e826-4371-9b19-1a716050ff88)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(netclass_flag ""
|
||||||
|
(length 2.54)
|
||||||
|
(shape round)
|
||||||
|
(at 115.57 45.72 0)
|
||||||
|
(fields_autoplaced yes)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
(uuid "dec4e873-7ff9-4632-8b58-f929fe6629ca")
|
||||||
|
(property "Netclass" ""
|
||||||
|
(at -199.39 -15.24 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Component Class" "Class2"
|
||||||
|
(at 116.2685 43.18 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
(italic yes)
|
||||||
|
)
|
||||||
|
(justify left)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol
|
||||||
|
(lib_id "Amplifier_Operational:TL072")
|
||||||
|
(at 74.93 62.23 0)
|
||||||
|
(unit 1)
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(dnp no)
|
||||||
|
(fields_autoplaced yes)
|
||||||
|
(uuid "521c74f6-a90a-4165-ba5b-74e4986fbfb5")
|
||||||
|
(property "Reference" "U1"
|
||||||
|
(at 74.93 52.07 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "TL072"
|
||||||
|
(at 74.93 54.61 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||||
|
(at 74.93 62.23 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||||
|
(at 74.93 62.23 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||||
|
(at 74.93 62.23 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Component Class" "Class1"
|
||||||
|
(at 74.93 62.23 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin "3"
|
||||||
|
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||||
|
)
|
||||||
|
(pin "2"
|
||||||
|
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||||
|
)
|
||||||
|
(pin "1"
|
||||||
|
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||||
|
)
|
||||||
|
(pin "5"
|
||||||
|
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||||
|
)
|
||||||
|
(pin "6"
|
||||||
|
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||||
|
)
|
||||||
|
(pin "7"
|
||||||
|
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||||
|
)
|
||||||
|
(pin "8"
|
||||||
|
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||||
|
)
|
||||||
|
(pin "4"
|
||||||
|
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||||
|
)
|
||||||
|
(instances
|
||||||
|
(project ""
|
||||||
|
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||||
|
(reference "U1")
|
||||||
|
(unit 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol
|
||||||
|
(lib_id "Amplifier_Operational:TL072")
|
||||||
|
(at 121.92 63.5 0)
|
||||||
|
(unit 2)
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(dnp no)
|
||||||
|
(fields_autoplaced yes)
|
||||||
|
(uuid "da40a256-1fbb-4db4-9c2c-275f5c1d0f3c")
|
||||||
|
(property "Reference" "U1"
|
||||||
|
(at 121.92 53.34 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "TL072"
|
||||||
|
(at 121.92 55.88 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||||
|
(at 121.92 63.5 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||||
|
(at 121.92 63.5 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||||
|
(at 121.92 63.5 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Component Class" "Class1"
|
||||||
|
(at 121.92 63.5 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin "3"
|
||||||
|
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||||
|
)
|
||||||
|
(pin "2"
|
||||||
|
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||||
|
)
|
||||||
|
(pin "1"
|
||||||
|
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||||
|
)
|
||||||
|
(pin "5"
|
||||||
|
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||||
|
)
|
||||||
|
(pin "6"
|
||||||
|
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||||
|
)
|
||||||
|
(pin "7"
|
||||||
|
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||||
|
)
|
||||||
|
(pin "8"
|
||||||
|
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||||
|
)
|
||||||
|
(pin "4"
|
||||||
|
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||||
|
)
|
||||||
|
(instances
|
||||||
|
(project ""
|
||||||
|
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||||
|
(reference "U1")
|
||||||
|
(unit 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol
|
||||||
|
(lib_id "Amplifier_Operational:TL072")
|
||||||
|
(at 176.53 66.04 0)
|
||||||
|
(unit 3)
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(dnp no)
|
||||||
|
(fields_autoplaced yes)
|
||||||
|
(uuid "ec280545-6554-44ce-b281-8b6027100352")
|
||||||
|
(property "Reference" "U1"
|
||||||
|
(at 175.26 64.77 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(justify left)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "TL072"
|
||||||
|
(at 175.26 67.31 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(justify left)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" "Package_SO:SO-8_5.3x6.2mm_P1.27mm"
|
||||||
|
(at 176.53 66.04 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
|
||||||
|
(at 176.53 66.04 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
|
||||||
|
(at 176.53 66.04 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Component Class" "Class1"
|
||||||
|
(at 176.53 66.04 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin "3"
|
||||||
|
(uuid "0a60a206-2dc8-4b92-a7be-126df13c85da")
|
||||||
|
)
|
||||||
|
(pin "2"
|
||||||
|
(uuid "b8ab93b0-0173-432e-85ed-64d6e0b531e0")
|
||||||
|
)
|
||||||
|
(pin "1"
|
||||||
|
(uuid "31022ebe-9ec7-4f79-9dd6-a320ec2cdc46")
|
||||||
|
)
|
||||||
|
(pin "5"
|
||||||
|
(uuid "6e87584c-ea7d-4388-9198-d4f8e33418db")
|
||||||
|
)
|
||||||
|
(pin "6"
|
||||||
|
(uuid "683f1791-0e09-4b93-863a-50f522c42231")
|
||||||
|
)
|
||||||
|
(pin "7"
|
||||||
|
(uuid "3abeb01e-4937-4584-a986-3b6827ccb17b")
|
||||||
|
)
|
||||||
|
(pin "8"
|
||||||
|
(uuid "153c2aa2-4642-461a-b93e-2375ef54c4f0")
|
||||||
|
)
|
||||||
|
(pin "4"
|
||||||
|
(uuid "e09162f6-ff12-43f4-bcac-fffde8eda559")
|
||||||
|
)
|
||||||
|
(instances
|
||||||
|
(project ""
|
||||||
|
(path "/bfc9b4d1-186d-4d8a-9f35-9d071f1d54fd"
|
||||||
|
(reference "U1")
|
||||||
|
(unit 3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(sheet_instances
|
||||||
|
(path "/"
|
||||||
|
(page "1")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
@ -0,0 +1,94 @@
|
|||||||
|
(export (version "E")
|
||||||
|
(design
|
||||||
|
(source "/component_classes/component_classes.kicad_sch")
|
||||||
|
(date "2024-09-29T22:57:25+0100")
|
||||||
|
(tool "Eeschema 8.99.0-2480-g2270f03d8e-dirty")
|
||||||
|
(sheet (number "1") (name "/") (tstamps "/")
|
||||||
|
(title_block
|
||||||
|
(title)
|
||||||
|
(company)
|
||||||
|
(rev)
|
||||||
|
(date)
|
||||||
|
(source "component_classes.kicad_sch")
|
||||||
|
(comment (number "1") (value ""))
|
||||||
|
(comment (number "2") (value ""))
|
||||||
|
(comment (number "3") (value ""))
|
||||||
|
(comment (number "4") (value ""))
|
||||||
|
(comment (number "5") (value ""))
|
||||||
|
(comment (number "6") (value ""))
|
||||||
|
(comment (number "7") (value ""))
|
||||||
|
(comment (number "8") (value ""))
|
||||||
|
(comment (number "9") (value "")))))
|
||||||
|
(components
|
||||||
|
(comp (ref "U1")
|
||||||
|
(value "TL072")
|
||||||
|
(footprint "Package_SO:SO-8_5.3x6.2mm_P1.27mm")
|
||||||
|
(datasheet "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||||
|
(description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8")
|
||||||
|
(fields
|
||||||
|
(field (name "Component Class") "Class1")
|
||||||
|
(field (name "Footprint") "Package_SO:SO-8_5.3x6.2mm_P1.27mm")
|
||||||
|
(field (name "Datasheet") "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||||
|
(field (name "Description") "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||||
|
(libsource (lib "Amplifier_Operational") (part "TL072") (description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||||
|
(property (name "Component Class") (value "Class1"))
|
||||||
|
(property (name "Sheetname") (value "Root"))
|
||||||
|
(property (name "Sheetfile") (value "component_classes.kicad_sch"))
|
||||||
|
(property (name "ki_keywords") (value "dual opamp"))
|
||||||
|
(property (name "ki_fp_filters") (value "SOIC*3.9x4.9mm*P1.27mm* DIP*W7.62mm* TO*99* OnSemi*Micro8* TSSOP*3x3mm*P0.65mm* TSSOP*4.4x3mm*P0.65mm* MSOP*3x3mm*P0.65mm* SSOP*3.9x4.9mm*P0.635mm* LFCSP*2x2mm*P0.5mm* *SIP* SOIC*5.3x6.2mm*P1.27mm*"))
|
||||||
|
(sheetpath (names "/") (tstamps "/"))
|
||||||
|
(component_classes
|
||||||
|
(class "Class1")
|
||||||
|
(class "Class2"))
|
||||||
|
(tstamps "ec280545-6554-44ce-b281-8b6027100352" "da40a256-1fbb-4db4-9c2c-275f5c1d0f3c" "521c74f6-a90a-4165-ba5b-74e4986fbfb5")))
|
||||||
|
(libparts
|
||||||
|
(libpart (lib "Amplifier_Operational") (part "TL072")
|
||||||
|
(description "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8")
|
||||||
|
(docs "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||||
|
(footprints
|
||||||
|
(fp "SOIC*3.9x4.9mm*P1.27mm*")
|
||||||
|
(fp "DIP*W7.62mm*")
|
||||||
|
(fp "TO*99*")
|
||||||
|
(fp "OnSemi*Micro8*")
|
||||||
|
(fp "TSSOP*3x3mm*P0.65mm*")
|
||||||
|
(fp "TSSOP*4.4x3mm*P0.65mm*")
|
||||||
|
(fp "MSOP*3x3mm*P0.65mm*")
|
||||||
|
(fp "SSOP*3.9x4.9mm*P0.635mm*")
|
||||||
|
(fp "LFCSP*2x2mm*P0.5mm*")
|
||||||
|
(fp "*SIP*")
|
||||||
|
(fp "SOIC*5.3x6.2mm*P1.27mm*"))
|
||||||
|
(fields
|
||||||
|
(field (name "Reference") "U")
|
||||||
|
(field (name "Value") "TL072")
|
||||||
|
(field (name "Footprint"))
|
||||||
|
(field (name "Datasheet") "http://www.ti.com/lit/ds/symlink/tl071.pdf")
|
||||||
|
(field (name "Description") "Dual Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"))
|
||||||
|
(pins
|
||||||
|
(pin (num "1") (name "") (type "output"))
|
||||||
|
(pin (num "2") (name "-") (type "input"))
|
||||||
|
(pin (num "3") (name "+") (type "input"))
|
||||||
|
(pin (num "4") (name "V-") (type "power_in"))
|
||||||
|
(pin (num "5") (name "+") (type "input"))
|
||||||
|
(pin (num "6") (name "-") (type "input"))
|
||||||
|
(pin (num "7") (name "") (type "output"))
|
||||||
|
(pin (num "8") (name "V+") (type "power_in")))))
|
||||||
|
(libraries
|
||||||
|
(library (logical "Amplifier_Operational")
|
||||||
|
(uri "/kicad/KiCad.app/Contents/SharedSupport/symbols//Amplifier_Operational.kicad_sym")))
|
||||||
|
(nets
|
||||||
|
(net (code "1") (name "unconnected-(U1-Pad1)")
|
||||||
|
(node (ref "U1") (pin "1") (pintype "output")))
|
||||||
|
(net (code "2") (name "unconnected-(U1-Pad7)")
|
||||||
|
(node (ref "U1") (pin "7") (pintype "output")))
|
||||||
|
(net (code "3") (name "unconnected-(U1A-+-Pad3)")
|
||||||
|
(node (ref "U1") (pin "3") (pinfunction "+") (pintype "input")))
|
||||||
|
(net (code "4") (name "unconnected-(U1A---Pad2)")
|
||||||
|
(node (ref "U1") (pin "2") (pinfunction "-") (pintype "input")))
|
||||||
|
(net (code "5") (name "unconnected-(U1B-+-Pad5)")
|
||||||
|
(node (ref "U1") (pin "5") (pinfunction "+") (pintype "input")))
|
||||||
|
(net (code "6") (name "unconnected-(U1B---Pad6)")
|
||||||
|
(node (ref "U1") (pin "6") (pinfunction "-") (pintype "input")))
|
||||||
|
(net (code "7") (name "unconnected-(U1C-V+-Pad8)")
|
||||||
|
(node (ref "U1") (pin "8") (pinfunction "V+") (pintype "power_in")))
|
||||||
|
(net (code "8") (name "unconnected-(U1C-V--Pad4)")
|
||||||
|
(node (ref "U1") (pin "4") (pinfunction "V-") (pintype "power_in")))))
|
@ -87,6 +87,10 @@ public:
|
|||||||
BOOST_REQUIRE_EQUAL( goldenNet.GetPinName(), testNet.GetPinName() );
|
BOOST_REQUIRE_EQUAL( goldenNet.GetPinName(), testNet.GetPinName() );
|
||||||
BOOST_REQUIRE_EQUAL( goldenNet.GetPinType(), testNet.GetPinType() );
|
BOOST_REQUIRE_EQUAL( goldenNet.GetPinType(), testNet.GetPinType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// And the the resolved component class is the same
|
||||||
|
BOOST_REQUIRE( goldenComp->GetComponentClassNames()
|
||||||
|
== refComp->GetComponentClassNames() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -209,5 +213,10 @@ BOOST_AUTO_TEST_CASE( Issue16439 )
|
|||||||
TestNetlist( "issue16439" );
|
TestNetlist( "issue16439" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( ComponentClasses )
|
||||||
|
{
|
||||||
|
TestNetlist( "component_classes" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user