diff --git a/eeschema/dialogs/dialog_erc.cpp b/eeschema/dialogs/dialog_erc.cpp index 9bfc8bd1b1..200e4f29aa 100644 --- a/eeschema/dialogs/dialog_erc.cpp +++ b/eeschema/dialogs/dialog_erc.cpp @@ -495,6 +495,12 @@ void DIALOG_ERC::testErc() tester.TestLibSymbolIssues(); } + if( settings.IsTestEnabled( ERCE_ENDPOINT_OFF_GRID ) ) + { + AdvancePhase( _( "Checking for off grid pins and wires..." ) ); + tester.TestOffGridEndpoints( m_parent->GetCanvas()->GetView()->GetGAL()->GetGridSize().x ); + } + m_parent->ResolveERCExclusions(); // Display diags: diff --git a/eeschema/erc.cpp b/eeschema/erc.cpp index 33da22df0c..280156d093 100644 --- a/eeschema/erc.cpp +++ b/eeschema/erc.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -705,10 +707,7 @@ int ERC_TESTER::TestLibSymbolIssues() for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) ) { - SCH_SYMBOL* symbol = dynamic_cast( item ); - - wxCHECK2( symbol, continue ); - + SCH_SYMBOL* symbol = static_cast( item ); LIB_SYMBOL* libSymbolInSchematic = symbol->GetLibSymbolRef().get(); wxCHECK2( libSymbolInSchematic, continue ); @@ -780,3 +779,75 @@ int ERC_TESTER::TestLibSymbolIssues() return err_count; } + + +int ERC_TESTER::TestOffGridEndpoints( int aGridSize ) +{ + // The minimal grid size allowed to place a pin is 25 mils + // the best grid size is 50 mils, but 25 mils is still usable + // this is because all symbols are using a 50 mils grid to place pins, and therefore + // the wires must be on the 50 mils grid + // So raise an error if a pin is not on a 25 mil (or bigger: 50 mil or 100 mil) grid + const int min_grid_size = Mils2iu( 25 ); + const int clamped_grid_size = ( aGridSize < min_grid_size ) ? min_grid_size : aGridSize; + + SCH_SCREENS screens( m_schematic->Root() ); + int err_count = 0; + + for( SCH_SCREEN* screen = screens.GetFirst(); screen != nullptr; screen = screens.GetNext() ) + { + std::vector markers; + + for( SCH_ITEM* item : screen->Items().OfType( SCH_SYMBOL_T ) ) + { + if( item->Type() == SCH_LINE_T && item->IsConnectable() ) + { + SCH_LINE* line = static_cast( item ); + + if( ( line->GetStartPoint().x % clamped_grid_size ) != 0 + || ( line->GetStartPoint().y % clamped_grid_size) != 0 ) + { + std::shared_ptr ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID ); + ercItem->SetItems( line ); + + markers.emplace_back( new SCH_MARKER( ercItem, line->GetStartPoint() ) ); + } + else if( ( line->GetEndPoint().x % clamped_grid_size ) != 0 + || ( line->GetEndPoint().y % clamped_grid_size) != 0 ) + { + std::shared_ptr ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID ); + ercItem->SetItems( line ); + + markers.emplace_back( new SCH_MARKER( ercItem, line->GetEndPoint() ) ); + } + } + else if( item->Type() == SCH_SYMBOL_T ) + { + SCH_SYMBOL* symbol = static_cast( item ); + + for( SCH_PIN* pin : symbol->GetPins( nullptr ) ) + { + VECTOR2I pinPos = pin->GetTransformedPosition(); + + if( ( pinPos.x % clamped_grid_size ) != 0 + || ( pinPos.y % clamped_grid_size) != 0 ) + { + std::shared_ptr ercItem = ERC_ITEM::Create( ERCE_ENDPOINT_OFF_GRID ); + ercItem->SetItems( pin ); + + markers.emplace_back( new SCH_MARKER( ercItem, pinPos ) ); + break; + } + } + } + } + + for( SCH_MARKER* marker : markers ) + { + screen->Append( marker ); + err_count += 1; + } + } + + return err_count; +} \ No newline at end of file diff --git a/eeschema/erc.h b/eeschema/erc.h index da329b2740..62184c0a72 100644 --- a/eeschema/erc.h +++ b/eeschema/erc.h @@ -128,6 +128,12 @@ public: */ int TestLibSymbolIssues(); + /** + * Test pins and wire ends for being off grid. + * @return the error count + */ + int TestOffGridEndpoints( int aGridSize ); + private: SCHEMATIC* m_schematic; diff --git a/eeschema/erc_item.cpp b/eeschema/erc_item.cpp index ea5ed9145e..a6ab57bf59 100644 --- a/eeschema/erc_item.cpp +++ b/eeschema/erc_item.cpp @@ -46,6 +46,10 @@ ERC_ITEM ERC_ITEM::duplicateSheetName( ERCE_DUPLICATE_SHEET_NAME, _( "Duplicate sheet names within a given sheet" ), wxT( "duplicate_sheet_names" ) ); +ERC_ITEM ERC_ITEM::endpointOffGrid( ERCE_ENDPOINT_OFF_GRID, + _( "Symbol pin or wire end off grid" ), + wxT( "endpoint_off_grid" ) ); + ERC_ITEM ERC_ITEM::pinNotConnected( ERCE_PIN_NOT_CONNECTED, _( "Pin not connected" ), wxT( "pin_not_connected" ) ); @@ -196,6 +200,7 @@ std::shared_ptr ERC_ITEM::Create( int aErrorCode ) switch( aErrorCode ) { case ERCE_DUPLICATE_SHEET_NAME: return std::make_shared( duplicateSheetName ); + case ERCE_ENDPOINT_OFF_GRID: return std::make_shared( endpointOffGrid ); case ERCE_PIN_NOT_CONNECTED: return std::make_shared( pinNotConnected ); case ERCE_PIN_NOT_DRIVEN: return std::make_shared( pinNotDriven ); case ERCE_POWERPIN_NOT_DRIVEN: return std::make_shared( powerpinNotDriven ); diff --git a/eeschema/erc_item.h b/eeschema/erc_item.h index 6269b3aaf0..9ffcddd798 100644 --- a/eeschema/erc_item.h +++ b/eeschema/erc_item.h @@ -72,6 +72,7 @@ private: static ERC_ITEM heading_misc; static ERC_ITEM duplicateSheetName; + static ERC_ITEM endpointOffGrid; static ERC_ITEM pinNotConnected; static ERC_ITEM pinNotDriven; static ERC_ITEM powerpinNotDriven; diff --git a/eeschema/erc_settings.cpp b/eeschema/erc_settings.cpp index d70dc393ec..cb904c7c6f 100644 --- a/eeschema/erc_settings.cpp +++ b/eeschema/erc_settings.cpp @@ -94,6 +94,7 @@ ERC_SETTINGS::ERC_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) : // Error is the default setting so set non-error priorities here. m_Severities[ERCE_UNSPECIFIED] = RPT_SEVERITY_UNDEFINED; + m_Severities[ERCE_ENDPOINT_OFF_GRID] = RPT_SEVERITY_WARNING; m_Severities[ERCE_PIN_TO_PIN_WARNING] = RPT_SEVERITY_WARNING; m_Severities[ERCE_SIMILAR_LABELS] = RPT_SEVERITY_WARNING; m_Severities[ERCE_GLOBLABEL] = RPT_SEVERITY_WARNING; diff --git a/eeschema/erc_settings.h b/eeschema/erc_settings.h index 6fa25841fb..5e0ffa9aa1 100644 --- a/eeschema/erc_settings.h +++ b/eeschema/erc_settings.h @@ -38,6 +38,7 @@ enum ERCE_T ERCE_UNSPECIFIED = 0, ERCE_FIRST, ERCE_DUPLICATE_SHEET_NAME = ERCE_FIRST, ///< Duplicate sheet names within a given sheet. + ERCE_ENDPOINT_OFF_GRID, ///< Pin or wire-end off grid. ERCE_PIN_NOT_CONNECTED, ///< Pin not connected and not no connect symbol. ERCE_PIN_NOT_DRIVEN, ///< Pin connected to some others pins but no pin to drive it. ///< pins to drive it can be output, passive, 3sttae, I/O diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp index 3d8fd87894..e85ca94563 100644 --- a/eeschema/sch_symbol.cpp +++ b/eeschema/sch_symbol.cpp @@ -888,7 +888,7 @@ std::vector SCH_SYMBOL::GetPins( const SCH_SHEET_PATH* aSheet ) const int unit = GetUnitSelection( aSheet ); - for( const auto& p : m_pins ) + for( const std::unique_ptr& p : m_pins ) { if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) ) continue;