diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 7a2748ab62..e40aedd236 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -543,10 +543,17 @@ void DIALOG_DRC::OnDRCItemRClick( wxDataViewEvent& aEvent ) } if( rcItem->GetErrorCode() == DRCE_CLEARANCE - || rcItem->GetErrorCode() == DRCE_EDGE_CLEARANCE ) + || rcItem->GetErrorCode() == DRCE_EDGE_CLEARANCE + || rcItem->GetErrorCode() == DRCE_HOLE_CLEARANCE ) { menu.Append( 3, _( "Run clearance resolution tool..." ) ); } + else if( rcItem->GetErrorCode() == DRCE_TEXT_HEIGHT + || rcItem->GetErrorCode() == DRCE_TEXT_THICKNESS + || rcItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG ) + { + menu.Append( 3, _( "Run constraints resolution tool..." ) ); + } menu.AppendSeparator(); diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index af709fba2d..3f9d1ce0ec 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -186,15 +186,18 @@ void DRC_ENGINE::loadImplicitRules() rule = createImplicitRule( _( "board setup constraints silk" ) ); rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS ); - DRC_CONSTRAINT silkClearanceConstraint( SILK_CLEARANCE_CONSTRAINT ); silkClearanceConstraint.Value().SetMin( bds.m_SilkClearance ); rule->AddConstraint( silkClearanceConstraint ); + rule = createImplicitRule( _( "board setup constraints silk text height" ) ); + rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS ); DRC_CONSTRAINT silkTextHeightConstraint( TEXT_HEIGHT_CONSTRAINT ); silkTextHeightConstraint.Value().SetMin( bds.m_MinSilkTextHeight ); rule->AddConstraint( silkTextHeightConstraint ); + rule = createImplicitRule( _( "board setup constraints silk text thickness" ) ); + rule->m_LayerCondition = LSET( 2, F_SilkS, B_SilkS ); DRC_CONSTRAINT silkTextThicknessConstraint( TEXT_THICKNESS_CONSTRAINT ); silkTextThicknessConstraint.Value().SetMin( bds.m_MinSilkTextThickness ); rule->AddConstraint( silkTextThicknessConstraint ); @@ -920,6 +923,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO case SILK_CLEARANCE_CONSTRAINT: case HOLE_CLEARANCE_CONSTRAINT: case EDGE_CLEARANCE_CONSTRAINT: + case MECHANICAL_CLEARANCE_CONSTRAINT: + case MECHANICAL_HOLE_CLEARANCE_CONSTRAINT: { int val = c->constraint.m_Value.Min(); REPORT( wxString::Format( _( "Checking %s clearance: %s." ), @@ -928,11 +933,22 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO break; } + case DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT: + { + int val = c->constraint.m_Value.Max(); + REPORT( wxString::Format( _( "Checking %s max uncoupled length: %s." ), + EscapeHTML( c->constraint.GetName() ), + REPORT_VALUE( val ) ) ) + break; + } + + case TRACK_WIDTH_CONSTRAINT: case ANNULAR_WIDTH_CONSTRAINT: case VIA_DIAMETER_CONSTRAINT: case TEXT_HEIGHT_CONSTRAINT: case TEXT_THICKNESS_CONSTRAINT: + case DIFF_PAIR_GAP_CONSTRAINT: { if( aReporter ) { @@ -950,10 +966,11 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO case TRACK_WIDTH_CONSTRAINT: msg = _( "track width" ); break; case ANNULAR_WIDTH_CONSTRAINT: msg = _( "annular width" ); break; case VIA_DIAMETER_CONSTRAINT: msg = _( "via diameter" ); break; + case DIFF_PAIR_GAP_CONSTRAINT: msg = _( "diff pair gap" ); break; default: msg = _( "constraint" ); break; } - REPORT( wxString::Format( _( "Checking %s %s: %s." ), + REPORT( wxString::Format( _( "Checking %s %s: opt %s." ), EscapeHTML( c->constraint.GetName() ), EscapeHTML( msg ), opt ) ) diff --git a/pcbnew/tools/board_inspection_tool.cpp b/pcbnew/tools/board_inspection_tool.cpp index 327bc1bcbb..df67fd5c8b 100644 --- a/pcbnew/tools/board_inspection_tool.cpp +++ b/pcbnew/tools/board_inspection_tool.cpp @@ -194,19 +194,45 @@ void BOARD_INSPECTION_TOOL::reportHeader( const wxString& aTitle, BOARD_ITEM* a, } +wxString reportMin( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) +{ + if( aConstraint.m_Value.HasMin() ) + return StringFromValue( aUnits, aConstraint.m_Value.Min(), true ); + else + return wxT( "" ) + _( "undefined" ) + wxT( "" ); +} + + +wxString reportOpt( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) +{ + if( aConstraint.m_Value.HasOpt() ) + return StringFromValue( aUnits, aConstraint.m_Value.Opt(), true ); + else + return wxT( "" ) + _( "undefined" ) + wxT( "" ); +} + + +wxString reportMax( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) +{ + if( aConstraint.m_Value.HasMax() ) + return StringFromValue( aUnits, aConstraint.m_Value.Max(), true ); + else + return wxT( "" ) + _( "undefined" ) + wxT( "" ); +} + + void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDRCItem ) { - BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() ); - BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() ); - PCB_LAYER_ID layer = m_frame->GetActiveLayer(); - - if( !a || !b ) - return; + BOARD_ITEM* a = m_frame->GetBoard()->GetItem( aDRCItem->GetMainItemID() ); + BOARD_ITEM* b = m_frame->GetBoard()->GetItem( aDRCItem->GetAuxItemID() ); + BOARD_CONNECTED_ITEM* ac = dynamic_cast( a ); + BOARD_CONNECTED_ITEM* bc = dynamic_cast( b ); + PCB_LAYER_ID layer = m_frame->GetActiveLayer(); if( m_inspectClearanceDialog == nullptr ) { m_inspectClearanceDialog = std::make_unique( m_frame ); - m_inspectClearanceDialog->SetTitle( _( "Clearance Report" ) ); + m_inspectClearanceDialog->SetTitle( _( "Violation Report" ) ); m_inspectClearanceDialog->Connect( wxEVT_CLOSE_WINDOW, wxCommandEventHandler( BOARD_INSPECTION_TOOL::onInspectClearanceDialogClosed ), @@ -222,8 +248,108 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR switch( aDRCItem->GetErrorCode() ) { + case DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG: + { + for( KIID id : aDRCItem->GetIDs() ) + { + bc = dynamic_cast( m_frame->GetBoard()->GetItem( id ) ); + + if( ac && bc && ac->GetNetCode() != bc->GetNetCode() ) + break; + } + + r = m_inspectClearanceDialog->AddPage( _( "Uncoupled Length" ) ); + reportHeader( _( "Diff pair uncoupled length resolution for:" ), ac, bc, r ); + + if( compileError ) + reportCompileError( r ); + + constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, a, b, layer, r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ), + reportMax( r->GetUnits(), constraint ) ) ); + break; + } + + case DRCE_TEXT_HEIGHT: + r = m_inspectClearanceDialog->AddPage( _( "Text Height" ) ); + reportHeader( _( "Text height resolution for:" ), a, r ); + + if( compileError ) + reportCompileError( r ); + + constraint = drcEngine.EvalRules( TEXT_HEIGHT_CONSTRAINT, a, b, layer, r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved text height constraints: min %s; opt %s; max %s." ), + reportMin( r->GetUnits(), constraint ), + reportOpt( r->GetUnits(), constraint ), + reportMax( r->GetUnits(), constraint ) ) ); + break; + + case DRCE_TEXT_THICKNESS: + r = m_inspectClearanceDialog->AddPage( _( "Text Thickness" ) ); + reportHeader( _( "Text thickness resolution for:" ), a, r ); + + if( compileError ) + reportCompileError( r ); + + constraint = drcEngine.EvalRules( TEXT_THICKNESS_CONSTRAINT, a, b, layer, r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved text thickness constraints: min %s; opt %s; max %s." ), + reportMin( r->GetUnits(), constraint ), + reportOpt( r->GetUnits(), constraint ), + reportMax( r->GetUnits(), constraint ) ) ); + break; + + case DRCE_HOLE_CLEARANCE: + r = m_inspectClearanceDialog->AddPage( _( "Hole Clearance" ) ); + reportHeader( _( "Hole clearance resolution for:" ), a, b, r ); + + if( compileError ) + reportCompileError( r ); + + if( ac && bc && ac->GetNetCode() == bc->GetNetCode() ) + { + r->Report( "" ); + r->Report( _( "Items belong to the same net. Clearance is 0." ) ); + } + else + { + constraint = drcEngine.EvalRules( HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r ); + clearance = constraint.m_Value.Min(); + clearanceStr = StringFromValue( r->GetUnits(), clearance, true ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); + } + + r->Report( "" ); + r->Report( "" ); + r->Report( "" ); + reportHeader( _( "Mechanical hole clearance resolution for:" ), a, b, layer, r ); + + constraint = drcEngine.EvalRules( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT, a, b, layer, r ); + clearance = constraint.m_Value.Min(); + clearanceStr = StringFromValue( r->GetUnits(), clearance, true ); + + if( !drcEngine.HasRulesForConstraintType( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT ) ) + { + r->Report( "" ); + r->Report( _( "No 'mechanical_hole_clearance' constraints defined." ) ); + } + else + { + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); + } + + break; + case DRCE_EDGE_CLEARANCE: - r = m_inspectClearanceDialog->AddPage( _( "Clearance" ) ); + r = m_inspectClearanceDialog->AddPage( _( "Edge Clearance" ) ); reportHeader( _( "Edge clearance resolution for:" ), a, b, r ); if( compileError ) @@ -271,12 +397,41 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr& aDR if( compileError ) reportCompileError( r ); - constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r ); + if( ac && bc && ac->GetNetCode() == bc->GetNetCode() ) + { + r->Report( "" ); + r->Report( _( "Items belong to the same net. Clearance is 0." ) ); + } + else + { + constraint = drcEngine.EvalRules( CLEARANCE_CONSTRAINT, a, a, layer, r ); + clearance = constraint.m_Value.Min(); + clearanceStr = StringFromValue( r->GetUnits(), clearance, true ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); + } + + r->Report( "" ); + r->Report( "" ); + r->Report( "" ); + reportHeader( _( "Mechanical clearance resolution for:" ), a, b, layer, r ); + + constraint = drcEngine.EvalRules( MECHANICAL_CLEARANCE_CONSTRAINT, a, b, layer, r ); clearance = constraint.m_Value.Min(); clearanceStr = StringFromValue( r->GetUnits(), clearance, true ); - r->Report( "" ); - r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); + if( !drcEngine.HasRulesForConstraintType( MECHANICAL_CLEARANCE_CONSTRAINT ) ) + { + r->Report( "" ); + r->Report( _( "No 'mechanical_clearance' constraints defined." ) ); + } + else + { + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) ); + } + break; default: @@ -499,6 +654,49 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) r->Flush(); } + if( ac && bc ) + { + NETINFO_ITEM* refNet = ac->GetNet(); + wxString coupledNet; + wxString dummy; + + if( DRC_ENGINE::MatchDpSuffix( refNet->GetNetname(), coupledNet, dummy ) + && bc->GetNetname() == coupledNet ) + { + r = m_inspectClearanceDialog->AddPage( _( "Diff Pair" ) ); + reportHeader( _( "Diff pair gap resolution for:" ), ac, bc, active, r ); + + constraint = drcEngine.EvalRules( DIFF_PAIR_GAP_CONSTRAINT, ac, bc, active, r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved gap constraints: min %s; opt %s; max %s." ), + reportMin( r->GetUnits(), constraint ), + reportOpt( r->GetUnits(), constraint ), + reportMax( r->GetUnits(), constraint ) ) ); + + r->Report( "" ); + r->Report( "" ); + r->Report( "" ); + reportHeader( _( "Diff pair max uncoupled length resolution for:" ), ac, bc, active, r ); + + if( !drcEngine.HasRulesForConstraintType( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT ) ) + { + r->Report( "" ); + r->Report( _( "No 'diff_pair_uncoupled' constraints defined." ) ); + } + else + { + constraint = drcEngine.EvalRules( DIFF_PAIR_MAX_UNCOUPLED_CONSTRAINT, ac, bc, + active, r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Resolved max uncoupled length: %s." ), + reportMax( r->GetUnits(), constraint ) ) ); + } + r->Flush(); + } + } + for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } ) { PCB_LAYER_ID correspondingMask = IsFrontLayer( layer ) ? F_Mask : B_Mask; @@ -691,33 +889,6 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent ) } -wxString reportMin( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) -{ - if( aConstraint.m_Value.HasMin() ) - return StringFromValue( aUnits, aConstraint.m_Value.Min(), true ); - else - return wxT( "" ) + _( "undefined" ) + wxT( "" ); -} - - -wxString reportOpt( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) -{ - if( aConstraint.m_Value.HasOpt() ) - return StringFromValue( aUnits, aConstraint.m_Value.Opt(), true ); - else - return wxT( "" ) + _( "undefined" ) + wxT( "" ); -} - - -wxString reportMax( EDA_UNITS aUnits, DRC_CONSTRAINT& aConstraint ) -{ - if( aConstraint.m_Value.HasMax() ) - return StringFromValue( aUnits, aConstraint.m_Value.Max(), true ); - else - return wxT( "" ) + _( "undefined" ) + wxT( "" ); -} - - int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) { #define EVAL_RULES( constraint, a, b, layer, r ) drcEngine.EvalRules( constraint, a, b, layer, r ) @@ -830,6 +1001,43 @@ int BOARD_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent ) r->Flush(); } + if( item->Type() == PCB_TEXT_T + || item->Type() == PCB_TEXTBOX_T + || item->Type() == PCB_FP_TEXT_T ) + { + r = m_inspectConstraintsDialog->AddPage( _( "Text Size" ) ); + reportHeader( _( "Text height resolution for:" ), item, r ); + + constraint = EVAL_RULES( TEXT_HEIGHT_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r ); + + if( compileError ) + reportCompileError( r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Text height constraints: min %s; opt %s; max %s." ), + reportMin( r->GetUnits(), constraint ), + reportOpt( r->GetUnits(), constraint ), + reportMax( r->GetUnits(), constraint ) ) ); + + r->Report( "" ); + r->Report( "" ); + r->Report( "" ); + reportHeader( _( "Text thickness resolution for:" ), item, r ); + + constraint = EVAL_RULES( TEXT_THICKNESS_CONSTRAINT, item, nullptr, UNDEFINED_LAYER, r ); + + if( compileError ) + reportCompileError( r ); + + r->Report( "" ); + r->Report( wxString::Format( _( "Text thickness constraints: min %s; opt %s; max %s." ), + reportMin( r->GetUnits(), constraint ), + reportOpt( r->GetUnits(), constraint ), + reportMax( r->GetUnits(), constraint ) ) ); + + r->Flush(); + } + r = m_inspectConstraintsDialog->AddPage( _( "Keepouts" ) ); reportHeader( _( "Keepout resolution for:" ), item, r );