From eae85742ccf57f43066e58412a096f12d153a874 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 15 Jun 2024 15:56:54 +0100 Subject: [PATCH] Don't report reasonable solder mask bridges in a net-tie footprint. --- pcbnew/drc/drc_test_provider_solder_mask.cpp | 63 +++++++++++++++----- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/pcbnew/drc/drc_test_provider_solder_mask.cpp b/pcbnew/drc/drc_test_provider_solder_mask.cpp index b2643517ba..adc6501df1 100644 --- a/pcbnew/drc/drc_test_provider_solder_mask.cpp +++ b/pcbnew/drc/drc_test_provider_solder_mask.cpp @@ -364,6 +364,8 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::checkMaskAperture( BOARD_ITEM* aMaskItem, BO if( aTestLayer == B_Mask && !aTestItem->IsOnLayer( B_Cu ) ) return false; + PCB_LAYER_ID maskLayer = IsFrontLayer( aTestLayer ) ? F_Mask : B_Mask; + FOOTPRINT* fp = aMaskItem->GetParentFootprint(); if( fp && ( fp->GetAttributes() & FP_ALLOW_SOLDERMASK_BRIDGES ) > 0 ) @@ -372,7 +374,7 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::checkMaskAperture( BOARD_ITEM* aMaskItem, BO return false; } - PTR_LAYER_CACHE_KEY key = { aMaskItem, aTestLayer }; + PTR_LAYER_CACHE_KEY key = { aMaskItem, maskLayer }; auto ii = m_maskApertureNetMap.find( key ); @@ -384,22 +386,48 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::checkMaskAperture( BOARD_ITEM* aMaskItem, BO return false; } - if( ii->second.second == aTestNet && aTestNet > 0 ) + auto& [cacheKey, cacheEntry] = *ii; + auto& [alreadyEncounteredItem, encounteredItemNet] = cacheEntry; + + if( encounteredItemNet == aTestNet && aTestNet >= 0 ) { // Same net; still no bridge... return false; } - if( fp && ii->second.first->Type() == PCB_PAD_T && aTestItem->Type() == PCB_PAD_T ) + if( fp && fp->IsNetTie() && aTestItem->GetParentFootprint() == fp ) { - PAD* alreadyEncounteredPad = static_cast( ii->second.first ); - PAD* thisPad = static_cast( aTestItem ); + std::map padToNetTieGroupMap = fp->MapPadNumbersToNetTieGroups(); + PAD* padA = nullptr; + PAD* padB = nullptr; - if( alreadyEncounteredPad->SharesNetTieGroup( thisPad ) ) - return false; + if( alreadyEncounteredItem->Type() == PCB_PAD_T ) + padA = static_cast( alreadyEncounteredItem ); + + if( aTestItem->Type() == PCB_PAD_T ) + padB = static_cast( aTestItem ); + + if( padA && padB ) + { + int netTieGroupA = padToNetTieGroupMap[padA->GetNumber()]; + int netTieGroupB = padToNetTieGroupMap[padB->GetNumber()]; + + if( netTieGroupA >= 0 && netTieGroupA == netTieGroupB ) + return false; + } + else if( padA && aTestItem->Type() == PCB_SHAPE_T ) + { + if( padToNetTieGroupMap.contains( padA->GetNumber() ) ) + return false; + } + else if( padB && alreadyEncounteredItem->Type() == PCB_SHAPE_T ) + { + if( padToNetTieGroupMap.contains( padB->GetNumber() ) ) + return false; + } } - *aCollidingItem = ii->second.first; + *aCollidingItem = alreadyEncounteredItem; return true; } @@ -440,8 +468,10 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con itemNet = static_cast( aItem )->GetNetCode(); BOARD_DESIGN_SETTINGS& bds = aItem->GetBoard()->GetDesignSettings(); - PAD* pad = dynamic_cast( aItem ); - PCB_VIA* via = dynamic_cast( aItem ); + PAD* pad = aItem->Type() == PCB_PAD_T ? static_cast( aItem ) + : nullptr; + PCB_VIA* via = aItem->Type() == PCB_VIA_T ? static_cast( aItem ) + : nullptr; std::shared_ptr itemShape = aItem->GetEffectiveShape( aRefLayer ); m_itemTree->QueryColliding( aItem, aRefLayer, aTargetLayer, @@ -449,7 +479,8 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con [&]( BOARD_ITEM* other ) -> bool { FOOTPRINT* itemFP = aItem->GetParentFootprint(); - PAD* otherPad = dynamic_cast( other ); + PAD* otherPad = other->Type() == PCB_PAD_T ? static_cast( other ) + : nullptr; int otherNet = -1; if( other->IsConnected() ) @@ -500,8 +531,10 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con // Visitor: [&]( BOARD_ITEM* other ) -> bool { - PAD* otherPad = dynamic_cast( other ); - PCB_VIA* otherVia = dynamic_cast( other ); + PAD* otherPad = other->Type() == PCB_PAD_T ? static_cast( other ) + : nullptr; + PCB_VIA* otherVia = other->Type() == PCB_VIA_T ? static_cast( other ) + : nullptr; auto otherShape = other->GetEffectiveShape( aTargetLayer ); int otherNet = -1; @@ -548,7 +581,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con // two distinct nets. if( isMaskAperture( aItem ) ) { - if( checkMaskAperture( aItem, other, aTargetLayer, otherNet, &colliding ) ) + if( checkMaskAperture( aItem, other, aRefLayer, otherNet, &colliding ) ) { auto drce = DRC_ITEM::Create( DRCE_SOLDERMASK_BRIDGE ); @@ -560,7 +593,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con } else if( isMaskAperture( other ) ) { - if( checkMaskAperture( other, aItem, aTargetLayer, itemNet, &colliding ) ) + if( checkMaskAperture( other, aItem, aRefLayer, itemNet, &colliding ) ) { auto drce = DRC_ITEM::Create( DRCE_SOLDERMASK_BRIDGE );