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:
Magnus Lundmark
2025-12-04 13:12:24 +00:00
committed by Jeff Young
parent dbb120597f
commit f47ec5f5d4
2 changed files with 114 additions and 4 deletions
+67 -4
View File
@@ -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)
+47
View File
@@ -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;
}