Browse Source

Add option to D356 output to suppress NC pads

Since this is a net test format, some importers do not like dealing with
NC pads
pull/18/head
Seth Hillbrand 3 months ago
parent
commit
40125c73d0
  1. 132
      pcbnew/exporters/export_d356.cpp
  2. 16
      pcbnew/exporters/export_d356.h
  3. 3
      pcbnew/pcbnew_settings.cpp
  4. 7
      pcbnew/pcbnew_settings.h

132
pcbnew/exporters/export_d356.cpp

@ -47,7 +47,10 @@
#include <math/util.h> // for KiROUND
#include <export_d356.h>
#include <tools/board_editor_control.h>
#include <wx/checkbox.h>
#include <wx/filedlg.h>
#include <wx/filedlgcustomize.h>
#include <wx/msgdlg.h>
@ -95,7 +98,7 @@ static int iu_to_d356(int iu, int clamp)
}
/* Extract the D356 record from the footprints (pads) */
static void build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecords )
void IPC356D_WRITER::build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecords )
{
VECTOR2I origin = aPcb->GetDesignSettings().GetAuxOrigin();
@ -107,46 +110,49 @@ static void build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecor
rk.access = compute_pad_access_code( aPcb, pad->GetLayerSet() );
// It could be a mask only pad, we only handle pads with copper here
if( rk.access != -1 )
{
rk.netname = pad->GetNetname();
rk.pin = pad->GetNumber();
rk.refdes = footprint->GetReference();
rk.midpoint = false; // XXX MAYBE need to be computed (how?)
const VECTOR2I& drill = pad->GetDrillSize();
rk.drill = std::min( drill.x, drill.y );
rk.hole = (rk.drill != 0);
rk.smd = pad->GetAttribute() == PAD_ATTRIB::SMD
|| pad->GetAttribute() == PAD_ATTRIB::CONN;
rk.mechanical = ( pad->GetAttribute() == PAD_ATTRIB::NPTH );
rk.x_location = pad->GetPosition().x - origin.x;
rk.y_location = origin.y - pad->GetPosition().y;
PCB_LAYER_ID accessLayer = footprint->IsFlipped() ? B_Cu : F_Cu;
rk.x_size = pad->GetSize( accessLayer ).x;
// Rule: round pads have y = 0
if( pad->GetShape( accessLayer ) == PAD_SHAPE::CIRCLE )
rk.y_size = 0;
else
rk.y_size = pad->GetSize( accessLayer ).y;
rk.rotation = - pad->GetOrientation().AsDegrees();
if( rk.rotation < 0 )
rk.rotation += 360;
// the value indicates which sides are *not* accessible
rk.soldermask = 3;
if( pad->GetLayerSet()[F_Mask] )
rk.soldermask &= ~1;
if( pad->GetLayerSet()[B_Mask] )
rk.soldermask &= ~2;
aRecords.push_back( rk );
}
if( rk.access == -1 )
continue;
if( m_doNotExportUnconnectedPads && pad->GetNetCode() == NETINFO_LIST::UNCONNECTED )
continue;
rk.netname = pad->GetNetname();
rk.pin = pad->GetNumber();
rk.refdes = footprint->GetReference();
rk.midpoint = false; // XXX MAYBE need to be computed (how?)
const VECTOR2I& drill = pad->GetDrillSize();
rk.drill = std::min( drill.x, drill.y );
rk.hole = (rk.drill != 0);
rk.smd = pad->GetAttribute() == PAD_ATTRIB::SMD
|| pad->GetAttribute() == PAD_ATTRIB::CONN;
rk.mechanical = ( pad->GetAttribute() == PAD_ATTRIB::NPTH );
rk.x_location = pad->GetPosition().x - origin.x;
rk.y_location = origin.y - pad->GetPosition().y;
PCB_LAYER_ID accessLayer = footprint->IsFlipped() ? B_Cu : F_Cu;
rk.x_size = pad->GetSize( accessLayer ).x;
// Rule: round pads have y = 0
if( pad->GetShape( accessLayer ) == PAD_SHAPE::CIRCLE )
rk.y_size = 0;
else
rk.y_size = pad->GetSize( accessLayer ).y;
rk.rotation = - pad->GetOrientation().AsDegrees();
if( rk.rotation < 0 )
rk.rotation += 360;
// the value indicates which sides are *not* accessible
rk.soldermask = 3;
if( pad->GetLayerSet()[F_Mask] )
rk.soldermask &= ~1;
if( pad->GetLayerSet()[B_Mask] )
rk.soldermask &= ~2;
aRecords.push_back( rk );
}
}
}
@ -382,6 +388,40 @@ bool IPC356D_WRITER::Write( const wxString& aFilename )
}
// Subclass for wxFileDialogCustomizeHook to add the checkbox
class D365_CUSTOMIZE_HOOK : public wxFileDialogCustomizeHook
{
public:
public:
D365_CUSTOMIZE_HOOK( bool aDoNotExportUnconnectedPads = false ) :
m_doNotExportUnconnectedPads( aDoNotExportUnconnectedPads ),
m_cb(nullptr)
{};
virtual void AddCustomControls( wxFileDialogCustomize& customizer ) override
{
m_cb = customizer.AddCheckBox( _( "Do not export unconnected pads" ) );
m_cb->SetValue( m_doNotExportUnconnectedPads );
}
virtual void TransferDataFromCustomControls() override
{
m_doNotExportUnconnectedPads = m_cb->GetValue();
}
bool GetDoNotExportUnconnectedPads() const { return m_doNotExportUnconnectedPads; }
private:
bool m_doNotExportUnconnectedPads;
wxFileDialogCheckBox* m_cb;
wxDECLARE_NO_COPY_CLASS( D365_CUSTOMIZE_HOOK );
};
int BOARD_EDITOR_CONTROL::GenD356File( const TOOL_EVENT& aEvent )
{
wxFileName fn = m_frame->GetBoard()->GetFileName();
@ -395,17 +435,21 @@ int BOARD_EDITOR_CONTROL::GenD356File( const TOOL_EVENT& aEvent )
wxFileDialog dlg( m_frame, _( "Generate IPC-D-356 netlist file" ), pro_dir, fn.GetFullName(),
wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
D365_CUSTOMIZE_HOOK customizeHook( m_frame->GetPcbNewSettings()->m_ExportD356.doNotExportUnconnectedPads );
dlg.SetCustomizeHook( customizeHook );
if( dlg.ShowModal() == wxID_CANCEL )
return 0;
IPC356D_WRITER writer( m_frame->GetBoard() );
bool doNotExportUnconnectedPads = customizeHook.GetDoNotExportUnconnectedPads();
writer.SetDoNotExportUnconnectedPads( doNotExportUnconnectedPads );
m_frame->GetPcbNewSettings()->m_ExportD356.doNotExportUnconnectedPads = doNotExportUnconnectedPads;
if( writer.Write( dlg.GetPath() ) )
{
wxMessageBox( wxString::Format( _( "IPC-D-356 netlist file created:\n'%s'." ),
dlg.GetPath() ),
_( "IPC-D-356 Netlist File" ), wxICON_INFORMATION );
DisplayInfoMessage( m_frame, wxString::Format( _( "IPC-D-356 netlist file created:\n'%s'." ),
dlg.GetPath() ) );
}
else
{

16
pcbnew/exporters/export_d356.h

@ -59,7 +59,8 @@ public:
* @param aParent will be used as the parent for any warning dialogs
*/
IPC356D_WRITER( BOARD* aPcb ) :
m_pcb( aPcb )
m_pcb( aPcb ),
m_doNotExportUnconnectedPads( false )
{}
virtual ~IPC356D_WRITER() {}
@ -71,9 +72,22 @@ public:
*/
bool Write( const wxString& aFilename );
/**
* Sets whether unconnected pads should be exported
* @param aDoNotExportUnconnectedPads if true, unconnected pads will not be exported
*/
void SetDoNotExportUnconnectedPads( bool aDoNotExportUnconnectedPads )
{
m_doNotExportUnconnectedPads = aDoNotExportUnconnectedPads;
}
private:
BOARD* m_pcb;
/// Writes a list of records to the given output stream
void write_D356_records( std::vector<D356_RECORD> &aRecords, FILE* aFile );
void build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecords );
bool m_doNotExportUnconnectedPads;
};

3
pcbnew/pcbnew_settings.cpp

@ -447,6 +447,9 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS()
m_params.emplace_back( new PARAM<int>( "export_vrml.origin_mode",
&m_ExportVrml.origin_mode, 0 ) );
m_params.emplace_back( new PARAM<bool>( "export_d356.doNotExportUnconnectedPads",
&m_ExportD356.doNotExportUnconnectedPads, false ) );
m_params.emplace_back( new PARAM<int>( "zones.net_sort_mode",
&m_Zones.net_sort_mode, -1 ) );

7
pcbnew/pcbnew_settings.h

@ -233,6 +233,11 @@ public:
int origin_mode;
};
struct DIALOG_EXPORT_D356
{
bool doNotExportUnconnectedPads;
};
struct DIALOG_FOOTPRINT_WIZARD_LIST
{
int width;
@ -396,6 +401,8 @@ public:
DIALOG_EXPORT_VRML m_ExportVrml;
DIALOG_EXPORT_D356 m_ExportD356;
DIALOG_FOOTPRINT_WIZARD_LIST m_FootprintWizardList;
DIALOG_GENERATE_DRILL m_GenDrill;

Loading…
Cancel
Save