Eeschema: Add multi-unit symbol support for text variables
Add enhancements to make working with multi-unit symbols easier,
particularly for connector pinout tables.
New features:
1. UNIT(<pin_number>) function
Returns the full unit reference for a given pin number.
Example: ${J601:UNIT(1)} returns "J601A" if pin 1 is in unit A.
2. Parent reference support in cross-references
Enables using parent reference (J601) instead of full unit reference
(J601A) in text variable expressions.
Example: ${J601:PIN_NAME(1)} now works (previously required ${J601A:PIN_NAME(1)})
3. Auto-resolution across units
PIN_NAME, NET_NAME, NET_CLASS, and SHORT_NET_NAME functions now
automatically search all units if a pin is not found in the current unit.
4. NC display for unconnected pins
SHORT_NET_NAME now displays "NC" instead of "unconnected-(Ref-Pin_X)",
making tables cleaner. NET_NAME still shows the full technical name.
Implementation:
- Enhanced SCHEMATIC::ResolveCrossReference() to add reference-based
lookup as a fallback after UUID resolution
- Added UNIT() function to SCH_SYMBOL::ResolveTextVar()
- Modified SHORT_NET_NAME handling to detect and format unconnected nets
This commit is contained in:
committed by
Jeff Young
parent
dbb120597f
commit
f47ec5f5d4
+67
-4
@@ -1535,6 +1535,7 @@ void SCH_SYMBOL::GetContextualTextVars( wxArrayString* aVars ) const
|
||||
aVars->push_back( wxT( "NET_NAME(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "NET_CLASS(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "PIN_NAME(<pin_number>)" ) );
|
||||
aVars->push_back( wxT( "UNIT(<pin_number>)" ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -1774,16 +1775,33 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
|
||||
else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) )
|
||||
|| token->StartsWith( wxT( "NET_NAME(" ) )
|
||||
|| token->StartsWith( wxT( "NET_CLASS(" ) )
|
||||
|| token->StartsWith( wxT( "PIN_NAME(" ) ) )
|
||||
|| token->StartsWith( wxT( "PIN_NAME(" ) )
|
||||
|| token->StartsWith( wxT( "UNIT(" ) ) )
|
||||
{
|
||||
wxString pinNumber = token->AfterFirst( '(' );
|
||||
pinNumber = pinNumber.BeforeLast( ')' );
|
||||
|
||||
for( SCH_PIN* pin : GetPins( aPath ) )
|
||||
// First, try to find the pin in the current unit (for backward compatibility)
|
||||
// For UNIT(), always search all pins to find which unit the pin belongs to
|
||||
std::vector<SCH_PIN*> pinsToSearch = token->StartsWith( wxT( "UNIT(" ) )
|
||||
? GetAllLibPins()
|
||||
: GetPins( aPath );
|
||||
|
||||
for( SCH_PIN* pin : pinsToSearch )
|
||||
{
|
||||
if( pin->GetNumber() == pinNumber )
|
||||
{
|
||||
if( token->StartsWith( wxT( "PIN_NAME" ) ) )
|
||||
if( token->StartsWith( wxT( "UNIT(" ) ) )
|
||||
{
|
||||
// Return the full unit reference (e.g., "J601A")
|
||||
int pinUnit = pin->GetUnit();
|
||||
if( pinUnit > 0 )
|
||||
*token = GetRef( aPath, false ) + SubReference( pinUnit, false );
|
||||
else
|
||||
*token = GetRef( aPath, false );
|
||||
return true;
|
||||
}
|
||||
else if( token->StartsWith( wxT( "PIN_NAME" ) ) )
|
||||
{
|
||||
*token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
|
||||
return true;
|
||||
@@ -1794,7 +1812,13 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
|
||||
if( !conn )
|
||||
*token = wxEmptyString;
|
||||
else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
|
||||
*token = conn->LocalName();
|
||||
{
|
||||
wxString netName = conn->LocalName();
|
||||
if( netName.Lower().StartsWith( wxT( "unconnected" ) ) )
|
||||
*token = wxT( "NC" );
|
||||
else
|
||||
*token = netName;
|
||||
}
|
||||
else if( token->StartsWith( wxT( "NET_NAME" ) ) )
|
||||
*token = conn->Name();
|
||||
else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
|
||||
@@ -1803,6 +1827,45 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If pin not found in current unit, search all units (auto-resolution)
|
||||
if( !token->StartsWith( wxT( "UNIT(" ) ) )
|
||||
{
|
||||
for( SCH_PIN* pin : GetAllLibPins() )
|
||||
{
|
||||
if( pin->GetNumber() == pinNumber )
|
||||
{
|
||||
if( token->StartsWith( wxT( "PIN_NAME" ) ) )
|
||||
{
|
||||
*token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt();
|
||||
return true;
|
||||
}
|
||||
|
||||
// For net-related functions, we need to find the correct sheet path
|
||||
// that has this pin's unit selected
|
||||
// Note: This is a simplification - in practice we may need to search
|
||||
// for the actual instance with this unit
|
||||
SCH_CONNECTION* conn = pin->Connection( aPath );
|
||||
|
||||
if( !conn )
|
||||
*token = wxEmptyString;
|
||||
else if( token->StartsWith( wxT( "SHORT_NET_NAME" ) ) )
|
||||
{
|
||||
wxString netName = conn->LocalName();
|
||||
if( netName.Lower().StartsWith( wxT( "unconnected" ) ) )
|
||||
*token = wxT( "NC" );
|
||||
else
|
||||
*token = netName;
|
||||
}
|
||||
else if( token->StartsWith( wxT( "NET_NAME" ) ) )
|
||||
*token = conn->Name();
|
||||
else if( token->StartsWith( wxT( "NET_CLASS" ) ) )
|
||||
*token = pin->GetEffectiveNetClass( aPath )->GetName();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if parent can resolve it (this will recurse to ancestors)
|
||||
|
||||
@@ -749,6 +749,53 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const
|
||||
return true; // Cross-reference is resolved whether or not the actual textvar was
|
||||
}
|
||||
|
||||
// If UUID resolution failed, try to resolve by reference designator
|
||||
// This handles both exact matches (J601A) and parent references for multi-unit symbols (J601)
|
||||
if( !refItem )
|
||||
{
|
||||
SCH_REFERENCE_LIST refs;
|
||||
Hierarchy().GetSymbols( refs );
|
||||
|
||||
SCH_SYMBOL* foundSymbol = nullptr;
|
||||
SCH_SHEET_PATH foundPath;
|
||||
|
||||
for( int ii = 0; ii < (int) refs.GetCount(); ii++ )
|
||||
{
|
||||
SCH_REFERENCE& reference = refs[ii];
|
||||
wxString symbolRef = reference.GetSymbol()->GetRef( &reference.GetSheetPath(), false );
|
||||
|
||||
// Try exact match first
|
||||
if( symbolRef == ref )
|
||||
{
|
||||
foundSymbol = reference.GetSymbol();
|
||||
foundPath = reference.GetSheetPath();
|
||||
break;
|
||||
}
|
||||
|
||||
// For multi-unit symbols, try matching parent reference (e.g., J601 matches J601A)
|
||||
if( symbolRef.StartsWith( ref ) && symbolRef.Length() == ref.Length() + 1 )
|
||||
{
|
||||
wxChar lastChar = symbolRef.Last();
|
||||
if( lastChar >= 'A' && lastChar <= 'Z' )
|
||||
{
|
||||
foundSymbol = reference.GetSymbol();
|
||||
foundPath = reference.GetSheetPath();
|
||||
// Don't break - continue looking for exact match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( foundSymbol )
|
||||
{
|
||||
if( foundSymbol->ResolveTextVar( &foundPath, &remainder, aDepth + 1 ) )
|
||||
*token = std::move( remainder );
|
||||
else
|
||||
*token = foundSymbol->GetRef( &foundPath, true ) + wxS( ":" ) + remainder;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user