diff --git a/common/gbr_metadata.cpp b/common/gbr_metadata.cpp index 7ffc2cfb41..cde69921bd 100644 --- a/common/gbr_metadata.cpp +++ b/common/gbr_metadata.cpp @@ -269,6 +269,11 @@ std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribu attribute_string = "TA.AperFunction,ComponentDrill"; break; + case GBR_APERTURE_ATTRIB_PRESSFITDRILL: + // print info associated to a flashed component pad with pressfit option in drill files + attribute_string = "TA.AperFunction,ComponentDrill,PressFit"; + break; + // print info associated to a component oblong pad hole in drill files // Same as a round pad hole, but is a specific aperture in drill file and // a G04 comment is added to the aperture function diff --git a/common/pcb.keywords b/common/pcb.keywords index ad278590d2..b9a9b6aa0e 100644 --- a/common/pcb.keywords +++ b/common/pcb.keywords @@ -263,6 +263,7 @@ pad_prop_castellated pad_prop_testpoint pad_prop_heatsink pad_prop_mechanical +pad_prop_pressfit padstack padvia prefer_zone_connections diff --git a/include/gbr_metadata.h b/include/gbr_metadata.h index a3e90a8203..42ad7936a2 100644 --- a/include/gbr_metadata.h +++ b/include/gbr_metadata.h @@ -137,6 +137,10 @@ public: /// Aperture used for castellated pads in drill files. GBR_APERTURE_ATTRIB_CASTELLATEDDRILL, + /// Aperture used for pressfit pads in drill files. + /// this is similar to GBR_APERTURE_ATTRIB_COMPONENTPAD with optional PressFit field + GBR_APERTURE_ATTRIB_PRESSFITDRILL, + GBR_APERTURE_ATTRIB_VIADRILL, ///< Aperture used for via holes in drill files. GBR_APERTURE_ATTRIB_CMP_DRILL, ///< Aperture used for pad holes in drill files. diff --git a/pcbnew/dialogs/dialog_gendrill.cpp b/pcbnew/dialogs/dialog_gendrill.cpp index 164d8d5abe..417d77e648 100644 --- a/pcbnew/dialogs/dialog_gendrill.cpp +++ b/pcbnew/dialogs/dialog_gendrill.cpp @@ -110,6 +110,8 @@ DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, JOB_EXPORT_PCB_ bool DIALOG_GENDRILL::TransferDataToWindow() { + m_messagesBox->Clear(); + if( !m_job ) { updatePrecisionOptions(); @@ -292,6 +294,7 @@ void DIALOG_GENDRILL::genDrillAndMapFiles( bool aGenDrill, bool aGenMap, bool aG updateConfig(); // set params and Save drill options m_pcbEditFrame->ClearMsgPanel(); + m_messagesBox->Clear(); WX_TEXT_CTRL_REPORTER reporter( m_messagesBox ); const PLOT_FORMAT filefmt[] = { @@ -395,6 +398,7 @@ void DIALOG_GENDRILL::onGenReportFile( wxCommandEvent& event ) if( dlg.ShowModal() == wxID_CANCEL ) return; + m_messagesBox->Clear(); bool success; // Info is slightly different between Excellon and Gerber diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index ae459da7a7..45c082c4a8 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -805,6 +805,7 @@ void DIALOG_PAD_PROPERTIES::initValues() case PAD_PROP::HEATSINK: m_choiceFabProperty->SetSelection( 5 ); break; case PAD_PROP::CASTELLATED: m_choiceFabProperty->SetSelection( 6 ); break; case PAD_PROP::MECHANICAL: m_choiceFabProperty->SetSelection( 7 ); break; + case PAD_PROP::PRESSFIT: m_choiceFabProperty->SetSelection( 8 ); break; } // Ensure the pad property is compatible with the pad type @@ -1700,6 +1701,7 @@ PAD_PROP DIALOG_PAD_PROPERTIES::getSelectedProperty() case 5: prop = PAD_PROP::HEATSINK; break; case 6: prop = PAD_PROP::CASTELLATED; break; case 7: prop = PAD_PROP::MECHANICAL; break; + case 8: prop = PAD_PROP::PRESSFIT; break; } return prop; diff --git a/pcbnew/dialogs/dialog_pad_properties_base.cpp b/pcbnew/dialogs/dialog_pad_properties_base.cpp index 9575879c5b..2f9724dea9 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.cpp +++ b/pcbnew/dialogs/dialog_pad_properties_base.cpp @@ -613,7 +613,7 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind m_middleBoxSizer->Add( 0, 2, 0, wxEXPAND, 5 ); - wxString m_choiceFabPropertyChoices[] = { _("None"), _("BGA pad"), _("Fiducial, local to footprint"), _("Fiducial, global to board"), _("Test point pad"), _("Heatsink pad"), _("Castellated pad (through hole only)"), _("Mechanical") }; + wxString m_choiceFabPropertyChoices[] = { _("None"), _("BGA pad"), _("Fiducial, local to footprint"), _("Fiducial, global to board"), _("Test point pad"), _("Heatsink pad"), _("Castellated pad (through hole only)"), _("Mechanical"), _("Press-fit (through hole only)") }; int m_choiceFabPropertyNChoices = sizeof( m_choiceFabPropertyChoices ) / sizeof( wxString ); m_choiceFabProperty = new wxChoice( m_panelGeneral, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceFabPropertyNChoices, m_choiceFabPropertyChoices, 0 ); m_choiceFabProperty->SetSelection( 0 ); diff --git a/pcbnew/dialogs/dialog_pad_properties_base.fbp b/pcbnew/dialogs/dialog_pad_properties_base.fbp index f7158dd9df..1bffcb03bf 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.fbp +++ b/pcbnew/dialogs/dialog_pad_properties_base.fbp @@ -7477,7 +7477,7 @@ 1 0 - "None" "BGA pad" "Fiducial, local to footprint" "Fiducial, global to board" "Test point pad" "Heatsink pad" "Castellated pad (through hole only)" "Mechanical" + "None" "BGA pad" "Fiducial, local to footprint" "Fiducial, global to board" "Test point pad" "Heatsink pad" "Castellated pad (through hole only)" "Mechanical" "Press-fit (through hole only)" 1 1 diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp index 318c2c9adc..b95d8290ff 100644 --- a/pcbnew/exporters/gen_drill_report_files.cpp +++ b/pcbnew/exporters/gen_drill_report_files.cpp @@ -362,19 +362,29 @@ bool GENDRILL_WRITER_BASE::genDrillMapFile( const wxString& aFullFileName, PLOT_ diameter_in_inches( tool.m_Diameter ) ); msg = From_UTF8( line ); + const char* extra_info; + + // Add more info for holes with specific constraints (castelleted, pressfit) + // note: only PTH pads have this option + if( tool.m_HoleAttribute == HOLE_ATTRIBUTE::HOLE_PAD_CASTELLATED ) + extra_info = ", castellated"; + else if( tool.m_HoleAttribute == HOLE_ATTRIBUTE::HOLE_PAD_PRESSFIT ) + extra_info = ", press-fit"; + else + extra_info = ""; // Now list how many holes and ovals are associated with each drill. if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) ) - snprintf( line, sizeof(line), "(1 hole)" ); + snprintf( line, sizeof(line), "(1 hole%s)", extra_info ); else if( tool.m_TotalCount == 1 ) // && ( toolm_OvalCount == 1 ) - snprintf( line, sizeof(line), "(1 slot)" ); + snprintf( line, sizeof(line), "(1 slot%s)", extra_info ); else if( tool.m_OvalCount == 0 ) - snprintf( line, sizeof(line), "(%d holes)", tool.m_TotalCount ); + snprintf( line, sizeof(line), "(%d holes%s)", tool.m_TotalCount, extra_info ); else if( tool.m_OvalCount == 1 ) - snprintf( line, sizeof(line), "(%d holes + 1 slot)", tool.m_TotalCount - 1 ); + snprintf( line, sizeof(line), "(%d holes + 1 slot%s)", tool.m_TotalCount - 1, extra_info ); else // if ( toolm_OvalCount > 1 ) - snprintf( line, sizeof(line), "(%d holes + %d slots)", tool.m_TotalCount - tool.m_OvalCount, - tool.m_OvalCount ); + snprintf( line, sizeof(line), "(%d holes + %d slots%s)", tool.m_TotalCount - tool.m_OvalCount, + tool.m_OvalCount, extra_info ); msg += From_UTF8( line ); @@ -550,15 +560,23 @@ unsigned GENDRILL_WRITER_BASE::printToolSummary( OUTPUTFORMATTER& out, bool aSum // Now list how many holes and ovals are associated with each drill. if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) ) - out.Print( 0, "(1 hole)\n" ); + out.Print( 0, "(1 hole" ); else if( tool.m_TotalCount == 1 ) - out.Print( 0, "(1 hole) (with 1 slot)\n" ); + out.Print( 0, "(1 hole) (with 1 slot" ); else if( tool.m_OvalCount == 0 ) - out.Print( 0, "(%d holes)\n", tool.m_TotalCount ); + out.Print( 0, "(%d holes)", tool.m_TotalCount ); else if( tool.m_OvalCount == 1 ) - out.Print( 0, "(%d holes) (with 1 slot)\n", tool.m_TotalCount ); + out.Print( 0, "(%d holes) (with 1 slot", tool.m_TotalCount ); else // tool.m_OvalCount > 1 - out.Print( 0, "(%d holes) (with %d slots)\n", tool.m_TotalCount, tool.m_OvalCount ); + out.Print( 0, "(%d holes) (with %d slots", tool.m_TotalCount, tool.m_OvalCount ); + + if( tool.m_HoleAttribute == HOLE_ATTRIBUTE::HOLE_PAD_CASTELLATED ) + out.Print( 0, ", castellated" ); + + if( tool.m_HoleAttribute == HOLE_ATTRIBUTE::HOLE_PAD_PRESSFIT ) + out.Print( 0, ", press-fit" ); + + out.Print( 0, ")\n"); totalHoleCount += tool.m_TotalCount; } diff --git a/pcbnew/exporters/gendrill_Excellon_writer.cpp b/pcbnew/exporters/gendrill_Excellon_writer.cpp index f90261648c..dc851985e9 100644 --- a/pcbnew/exporters/gendrill_Excellon_writer.cpp +++ b/pcbnew/exporters/gendrill_Excellon_writer.cpp @@ -176,9 +176,18 @@ void EXCELLON_WRITER::writeHoleAttribute( HOLE_ATTRIBUTE aAttribute ) break; case HOLE_ATTRIBUTE::HOLE_PAD: + //case HOLE_ATTRIBUTE::HOLE_PAD_CASTELLATED: fprintf( m_file, "; #@! TA.AperFunction,Plated,PTH,ComponentDrill\n" ); break; + case HOLE_ATTRIBUTE::HOLE_PAD_CASTELLATED: + fprintf( m_file, "; #@! TA.AperFunction,Plated,PTH,CastelletedDrill\n" ); + break; + + case HOLE_ATTRIBUTE::HOLE_PAD_PRESSFIT: + fprintf( m_file, "; #@! TA.AperFunction,Plated,PTH,ComponentDrill,PressFit\n" ); + break; + case HOLE_ATTRIBUTE::HOLE_MECHANICAL: fprintf( m_file, "; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill\n" ); break; diff --git a/pcbnew/exporters/gendrill_file_writer_base.cpp b/pcbnew/exporters/gendrill_file_writer_base.cpp index 7a46369c2b..852fe1fc33 100644 --- a/pcbnew/exporters/gendrill_file_writer_base.cpp +++ b/pcbnew/exporters/gendrill_file_writer_base.cpp @@ -147,9 +147,20 @@ void GENDRILL_WRITER_BASE::buildHolesList( DRILL_LAYER_PAIR aLayerPair, bool aGe continue; new_hole.m_ItemParent = pad; - new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_ATTRIB::NPTH); - new_hole.m_HoleAttribute = new_hole.m_Hole_NotPlated ? HOLE_ATTRIBUTE::HOLE_MECHANICAL - : HOLE_ATTRIBUTE::HOLE_PAD; + new_hole.m_Hole_NotPlated = ( pad->GetAttribute() == PAD_ATTRIB::NPTH ); + + if( new_hole.m_Hole_NotPlated ) + new_hole.m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_MECHANICAL; + else + { + if( pad->GetProperty() == PAD_PROP::CASTELLATED ) + new_hole.m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_PAD_CASTELLATED; + else if( pad->GetProperty() == PAD_PROP::PRESSFIT ) + new_hole.m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_PAD_PRESSFIT; + else + new_hole.m_HoleAttribute = HOLE_ATTRIBUTE::HOLE_PAD; + } + new_hole.m_Tool_Reference = -1; // Flag is: Not initialized new_hole.m_Hole_Orient = pad->GetOrientation(); new_hole.m_Hole_Shape = 0; // hole shape: round diff --git a/pcbnew/exporters/gendrill_file_writer_base.h b/pcbnew/exporters/gendrill_file_writer_base.h index b93a095e4f..2efa5d9c83 100644 --- a/pcbnew/exporters/gendrill_file_writer_base.h +++ b/pcbnew/exporters/gendrill_file_writer_base.h @@ -43,11 +43,13 @@ class BOARD_ITEM; // in NC drill files enum class HOLE_ATTRIBUTE { - HOLE_UNKNOWN, // uninitialized type - HOLE_VIA_THROUGH, // a via hole (always plated) from top to bottom - HOLE_VIA_BURIED, // a via hole (always plated) not through hole - HOLE_PAD, // a plated or not plated pad hole - HOLE_MECHANICAL // a mechanical pad (provided, not used) + HOLE_UNKNOWN, // uninitialized type + HOLE_VIA_THROUGH, // a via hole (always plated) from top to bottom + HOLE_VIA_BURIED, // a via hole (always plated) not through hole + HOLE_PAD, // a plated or not plated pad hole + HOLE_PAD_CASTELLATED, // a plated castelleted pad hole + HOLE_PAD_PRESSFIT, // a plated press-fit pad hole + HOLE_MECHANICAL // a mechanical pad (provided, not used) }; // Via Protection features according to IPC-4761. diff --git a/pcbnew/exporters/gendrill_gerber_writer.cpp b/pcbnew/exporters/gendrill_gerber_writer.cpp index d53d5dd45d..1b78df61bb 100644 --- a/pcbnew/exporters/gendrill_gerber_writer.cpp +++ b/pcbnew/exporters/gendrill_gerber_writer.cpp @@ -390,6 +390,11 @@ int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth, gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CASTELLATEDDRILL ); } + else if( pad->GetProperty() == PAD_PROP::PRESSFIT ) + { + gbr_metadata.SetApertureAttrib( + GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_PRESSFITDRILL ); + } else { // Good practice of oblong pad holes (slots) is to use a specific aperture for diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 0d108523d6..8ff2a0a2e7 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -1400,6 +1400,7 @@ void PAD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& case PAD_PROP::HEATSINK: props += _( "Heat sink" ); break; case PAD_PROP::CASTELLATED: props += _( "Castellated" ); break; case PAD_PROP::MECHANICAL: props += _( "Mechanical" ); break; + case PAD_PROP::PRESSFIT: props += _( "Press-fit" ); break; } // TODO(JE) How to show complex padstack info in the message panel @@ -2309,6 +2310,10 @@ void PAD::CheckPad( UNITS_PROVIDER* aUnitsProvider, bool aForPadProperties, if( GetProperty() == PAD_PROP::MECHANICAL && GetAttribute() != PAD_ATTRIB::PTH ) aErrorHandler( DRCE_PADSTACK, _( "('mechanical' property is for PTH pads)" ) ); + if( GetProperty() == PAD_PROP::PRESSFIT + && ( GetAttribute() != PAD_ATTRIB::PTH || !HasDrilledHole() ) ) + aErrorHandler( DRCE_PADSTACK, _( "('press-fit' property is for PTH pads with round holes)" ) ); + switch( GetAttribute() ) { case PAD_ATTRIB::NPTH: // Not plated, but through hole, a hole is expected @@ -2745,7 +2750,8 @@ static struct PAD_DESC .Map( PAD_PROP::TESTPOINT, _HKI( "Test point pad" ) ) .Map( PAD_PROP::HEATSINK, _HKI( "Heatsink pad" ) ) .Map( PAD_PROP::CASTELLATED, _HKI( "Castellated pad" ) ) - .Map( PAD_PROP::MECHANICAL, _HKI( "Mechanical pad" ) ); + .Map( PAD_PROP::MECHANICAL, _HKI( "Mechanical pad" ) ) + .Map( PAD_PROP::PRESSFIT, _HKI( "Press-fit pad" ) ); ENUM_MAP::Instance() .Map( PAD_DRILL_SHAPE::CIRCLE, _HKI( "Round" ) ) diff --git a/pcbnew/padstack.h b/pcbnew/padstack.h index e182fa68f5..983499e183 100644 --- a/pcbnew/padstack.h +++ b/pcbnew/padstack.h @@ -104,6 +104,7 @@ enum class PAD_PROP HEATSINK, ///< a pad used as heat sink, usually in SMD footprints CASTELLATED, ///< a pad with a castellated through hole MECHANICAL, ///< a pad used for mechanical support + PRESSFIT ///< a PTH with a hole diameter with tight tolerances for press fit pin }; diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp index 243faebc6d..6f91d61c66 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.cpp @@ -1526,6 +1526,7 @@ void PCB_IO_KICAD_SEXPR::format( const PAD* aPad ) const case PAD_PROP::HEATSINK: property = "pad_prop_heatsink"; break; case PAD_PROP::CASTELLATED: property = "pad_prop_castellated"; break; case PAD_PROP::MECHANICAL: property = "pad_prop_mechanical"; break; + case PAD_PROP::PRESSFIT: property = "pad_prop_pressfit"; break; default: THROW_IO_ERROR( wxString::Format( wxT( "unknown pad property: %d" ), diff --git a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp index a8af826560..145bc0adf1 100644 --- a/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp +++ b/pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr_parser.cpp @@ -5506,6 +5506,7 @@ PAD* PCB_IO_KICAD_SEXPR_PARSER::parsePAD( FOOTPRINT* aParent ) case T_pad_prop_castellated: pad->SetProperty( PAD_PROP::CASTELLATED ); break; case T_pad_prop_heatsink: pad->SetProperty( PAD_PROP::HEATSINK ); break; case T_pad_prop_mechanical: pad->SetProperty( PAD_PROP::MECHANICAL ); break; + case T_pad_prop_pressfit: pad->SetProperty( PAD_PROP::PRESSFIT ); break; case T_none: pad->SetProperty( PAD_PROP::NONE ); break; case T_RIGHT: break; diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index ba235db9ea..6d8e96bc14 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -258,6 +258,7 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLO metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CASTELLATEDPAD ); break; + case PAD_PROP::PRESSFIT: // used only in drill files case PAD_PROP::NONE: case PAD_PROP::MECHANICAL: break;