void MODULE::CopyNetlistSettings( MODULE* aModule ) { // Don't do anything foolish like trying to copy to yourself. wxCHECK_RET( aModule != NULL && aModule != this, wxT( "Cannot copy to NULL or yourself." ) ); // Not sure what to do with the value field. Use netlist for now. aModule->SetPosition( GetPosition() ); if( aModule->GetLayer() != GetLayer() ) aModule->Flip( aModule->GetPosition() ); if( aModule->GetOrientation() != GetOrientation() ) aModule->Rotate( aModule->GetPosition(), GetOrientation() ); aModule->SetLocalSolderMaskMargin( GetLocalSolderMaskMargin() ); aModule->SetLocalClearance( GetLocalClearance() ); aModule->SetLocalSolderPasteMargin( GetLocalSolderPasteMargin() ); aModule->SetLocalSolderPasteMarginRatio( GetLocalSolderPasteMarginRatio() ); aModule->SetZoneConnection( GetZoneConnection() ); aModule->SetThermalWidth( GetThermalWidth() ); aModule->SetThermalGap( GetThermalGap() ); for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { D_PAD* newPad = aModule->FindPadByName( pad->GetPadName() ); if( newPad ) pad->CopyNetlistSettings( newPad ); } // Not sure about copying description, keywords, 3D models or any other // local user changes to footprint. Stick with the new footprint settings // called out in the footprint loaded in the netlist. aModule->CalculateBoundingBox(); }
unsigned MODULE::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const { std::set<wxUint32> usedNames; // Create a set of used pad numbers for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { // Skip pads not on copper layers (used to build complex // solder paste shapes for instance) if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() ) continue; // Skip pads with no name, because they are usually "mechanical" // pads, not "electrical" pads if( pad->GetPadName().IsEmpty() ) continue; if( !aIncludeNPTH ) { // skip NPTH if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) { continue; } } usedNames.insert( pad->GetPackedPadName() ); } return usedNames.size(); }
/** * Send a remote command to Eeschema via a socket, * @param objectToSync = item to be located on schematic (module, pin or text) * Commands are * $PART: "reference" put cursor on component anchor * $PART: "reference" $PAD: "pad number" put cursor on the component pin * $PART: "reference" $REF: "reference" put cursor on the component ref * $PART: "reference" $VAL: "value" put cursor on the component value */ void PCB_EDIT_FRAME::SendMessageToEESCHEMA( BOARD_ITEM* objectToSync ) { char cmd[1024]; const char* text_key; MODULE* module = NULL; D_PAD* pad; TEXTE_MODULE* text_mod; wxString msg; if( objectToSync == NULL ) return; switch( objectToSync->Type() ) { case PCB_MODULE_T: module = (MODULE*) objectToSync; sprintf( cmd, "$PART: \"%s\"", TO_UTF8( module->GetReference() ) ); break; case PCB_PAD_T: module = (MODULE*) objectToSync->GetParent(); pad = (D_PAD*) objectToSync; msg = pad->GetPadName(); sprintf( cmd, "$PART: \"%s\" $PAD: \"%s\"", TO_UTF8( module->GetReference() ), TO_UTF8( msg ) ); break; case PCB_MODULE_TEXT_T: module = (MODULE*) objectToSync->GetParent(); text_mod = (TEXTE_MODULE*) objectToSync; if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE ) text_key = "$REF:"; else if( text_mod->GetType() == TEXTE_MODULE::TEXT_is_VALUE ) text_key = "$VAL:"; else break; sprintf( cmd, "$PART: \"%s\" %s \"%s\"", TO_UTF8( module->GetReference() ), text_key, TO_UTF8( text_mod->GetText() ) ); break; default: break; } if( module ) { SendCommand( MSG_TO_SCH, cmd ); } }
/* * Function SetPadNetName * Update a pad netname using the current footprint * Line format: ( <pad number> = <net name> ) * Param aText = current line read from netlist */ bool NETLIST_READER::SetPadNetName( char* aText ) { char* p; char line[256]; if( m_currModule == NULL ) return false; strncpy( line, aText, sizeof(line) ); if( ( p = strtok( line, " ()\t\n" ) ) == NULL ) return false; wxString pinName = FROM_UTF8( p ); if( ( p = strtok( NULL, " ()\t\n" ) ) == NULL ) return false; wxString netName = FROM_UTF8( p ); bool found = false; for( D_PAD* pad = m_currModule->m_Pads; pad; pad = pad->Next() ) { wxString padName = pad->GetPadName(); if( padName == pinName ) { found = true; if( (char) netName[0] != '?' ) pad->SetNetname( netName ); else pad->SetNetname( wxEmptyString ); } } if( !found ) { if( m_messageWindow ) { wxString msg; msg.Printf( _( "Module [%s]: Pad [%s] not found" ), GetChars( m_currModule->m_Reference->m_Text ), GetChars( pinName ) ); m_messageWindow->AppendText( msg + wxT( "\n" ) ); } } return found; }
wxString MODULE::GetNextPadName( bool aFillSequenceGaps ) const { std::set<int> usedNumbers; // Create a set of used pad numbers for( D_PAD* pad = Pads(); pad; pad = pad->Next() ) { int padNumber = getTrailingInt( pad->GetPadName() ); usedNumbers.insert( padNumber ); } const int nextNum = getNextNumberInSequence( usedNumbers, aFillSequenceGaps ); return wxString::Format( wxT( "%i" ), nextNum ); }
void MODULE::CopyNetlistSettings( MODULE* aModule, bool aCopyLocalSettings ) { // Don't do anything foolish like trying to copy to yourself. wxCHECK_RET( aModule != NULL && aModule != this, wxT( "Cannot copy to NULL or yourself." ) ); // Not sure what to do with the value field. Use netlist for now. aModule->SetPosition( GetPosition() ); if( aModule->GetLayer() != GetLayer() ) aModule->Flip( aModule->GetPosition() ); if( aModule->GetOrientation() != GetOrientation() ) aModule->Rotate( aModule->GetPosition(), GetOrientation() ); aModule->SetLocked( IsLocked() ); if( aCopyLocalSettings ) { aModule->SetLocalSolderMaskMargin( GetLocalSolderMaskMargin() ); aModule->SetLocalClearance( GetLocalClearance() ); aModule->SetLocalSolderPasteMargin( GetLocalSolderPasteMargin() ); aModule->SetLocalSolderPasteMarginRatio( GetLocalSolderPasteMarginRatio() ); aModule->SetZoneConnection( GetZoneConnection() ); aModule->SetThermalWidth( GetThermalWidth() ); aModule->SetThermalGap( GetThermalGap() ); } for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() ) { // Fix me: if aCopyLocalSettings == true, for "multiple" pads // (set of pads having the same name/number) this is broken // because we copy settings from the first pad found. // When old and new footprints have very few differences, a better // algo can be used. D_PAD* oldPad = FindPadByName( pad->GetPadName() ); if( oldPad ) oldPad->CopyNetlistSettings( pad, aCopyLocalSettings ); } // Not sure about copying description, keywords, 3D models or any other // local user changes to footprint. Stick with the new footprint settings // called out in the footprint loaded in the netlist. aModule->CalculateBoundingBox(); }
/** * Function idf_export_module * retrieves information from all board modules, adds drill holes to * the DRILLED_HOLES or BOARD_OUTLINE section as appropriate, * compiles data for the PLACEMENT section and compiles data for * the library ELECTRICAL section. */ static void idf_export_module( BOARD* aPcb, MODULE* aModule, IDF3_BOARD& aIDFBoard ) { // Reference Designator std::string crefdes = TO_UTF8( aModule->GetReference() ); if( crefdes.empty() || !crefdes.compare( "~" ) ) { std::string cvalue = TO_UTF8( aModule->GetValue() ); // if both the RefDes and Value are empty or set to '~' the board owns the part, // otherwise associated parts of the module must be marked NOREFDES. if( cvalue.empty() || !cvalue.compare( "~" ) ) crefdes = "BOARD"; else crefdes = "NOREFDES"; } // TODO: If module cutouts are supported we must add code here // for( EDA_ITEM* item = aModule->GraphicalItems(); item != NULL; item = item->Next() ) // { // if( ( item->Type() != PCB_MODULE_EDGE_T ) // || (item->GetLayer() != Edge_Cuts ) ) continue; // code to export cutouts // } // Export pads double drill, x, y; double scale = aIDFBoard.GetUserScale(); IDF3::KEY_PLATING kplate; std::string pintype; std::string tstr; double dx, dy; aIDFBoard.GetUserOffset( dx, dy ); for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() ) { drill = (double) pad->GetDrillSize().x * scale; x = pad->GetPosition().x * scale + dx; y = -pad->GetPosition().y * scale + dy; // Export the hole on the edge layer if( drill > 0.0 ) { // plating if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) kplate = IDF3::NPTH; else kplate = IDF3::PTH; // hole type tstr = TO_UTF8( pad->GetPadName() ); if( tstr.empty() || !tstr.compare( "0" ) || !tstr.compare( "~" ) || ( kplate == IDF3::NPTH ) ||( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) ) pintype = "MTG"; else pintype = "PIN"; // fields: // 1. hole dia. : float // 2. X coord : float // 3. Y coord : float // 4. plating : PTH | NPTH // 5. Assoc. part : BOARD | NOREFDES | PANEL | {"refdes"} // 6. type : PIN | VIA | MTG | TOOL | { "other" } // 7. owner : MCAD | ECAD | UNOWNED if( ( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) && ( pad->GetDrillSize().x != pad->GetDrillSize().y ) ) { // NOTE: IDF does not have direct support for slots; // slots are implemented as a board cutout and we // cannot represent plating or reference designators double dlength = pad->GetDrillSize().y * scale; // NOTE: The orientation of modules and pads have // the opposite sense due to KiCad drawing on a // screen with a LH coordinate system double angle = pad->GetOrientation() / 10.0; // NOTE: Since this code assumes the scenario where // GetDrillSize().y is the length but idf_parser.cpp // assumes a length along the X axis, the orientation // must be shifted +90 deg when GetDrillSize().y is // the major axis. if( dlength < drill ) { std::swap( drill, dlength ); } else { angle += 90.0; } // NOTE: KiCad measures a slot's length from end to end // rather than between the centers of the arcs dlength -= drill; aIDFBoard.AddSlot( drill, dlength, angle, x, y ); } else { IDF_DRILL_DATA *dp = new IDF_DRILL_DATA( drill, x, y, kplate, crefdes, pintype, IDF3::ECAD ); if( !aIDFBoard.AddDrill( dp ) ) { delete dp; std::ostringstream ostr; ostr << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__; ostr << "(): could not add drill"; throw std::runtime_error( ostr.str() ); } } } } // add any valid models to the library item list std::string refdes; IDF3_COMPONENT* comp = NULL; for( S3D_MASTER* modfile = aModule->Models(); modfile != 0; modfile = modfile->Next() ) { if( !modfile->Is3DType( S3D_MASTER::FILE3D_IDF ) || modfile->GetShape3DFullFilename().empty() ) continue; if( refdes.empty() ) { refdes = TO_UTF8( aModule->GetReference() ); // NOREFDES cannot be used or else the software gets confused // when writing out the placement data due to conflicting // placement and layer specifications; to work around this we // create a (hopefully) unique refdes for our exported part. if( refdes.empty() || !refdes.compare( "~" ) ) refdes = aIDFBoard.GetNewRefDes(); } IDF3_COMP_OUTLINE* outline; outline = aIDFBoard.GetComponentOutline( modfile->GetShape3DFullFilename() ); if( !outline ) throw( std::runtime_error( aIDFBoard.GetError() ) ); double rotz = aModule->GetOrientation()/10.0; double locx = modfile->m_MatPosition.x * 25.4; // part offsets are in inches double locy = modfile->m_MatPosition.y * 25.4; double locz = modfile->m_MatPosition.z * 25.4; double lrot = modfile->m_MatRotation.z; bool top = ( aModule->GetLayer() == B_Cu ) ? false : true; if( top ) { locy = -locy; RotatePoint( &locx, &locy, aModule->GetOrientation() ); locy = -locy; } if( !top ) { lrot = -lrot; RotatePoint( &locx, &locy, aModule->GetOrientation() ); locy = -locy; rotz = 180.0 - rotz; if( rotz >= 360.0 ) while( rotz >= 360.0 ) rotz -= 360.0; if( rotz <= -360.0 ) while( rotz <= -360.0 ) rotz += 360.0; } if( comp == NULL ) comp = aIDFBoard.FindComponent( refdes ); if( comp == NULL ) { comp = new IDF3_COMPONENT( &aIDFBoard ); if( comp == NULL ) throw( std::runtime_error( aIDFBoard.GetError() ) ); comp->SetRefDes( refdes ); if( top ) comp->SetPosition( aModule->GetPosition().x * scale + dx, -aModule->GetPosition().y * scale + dy, rotz, IDF3::LYR_TOP ); else comp->SetPosition( aModule->GetPosition().x * scale + dx, -aModule->GetPosition().y * scale + dy, rotz, IDF3::LYR_BOTTOM ); comp->SetPlacement( IDF3::PS_ECAD ); aIDFBoard.AddComponent( comp ); } else { double refX, refY, refA; IDF3::IDF_LAYER side; if( ! comp->GetPosition( refX, refY, refA, side ) ) { // place the item if( top ) comp->SetPosition( aModule->GetPosition().x * scale + dx, -aModule->GetPosition().y * scale + dy, rotz, IDF3::LYR_TOP ); else comp->SetPosition( aModule->GetPosition().x * scale + dx, -aModule->GetPosition().y * scale + dy, rotz, IDF3::LYR_BOTTOM ); comp->SetPlacement( IDF3::PS_ECAD ); } else { // check that the retrieved component matches this one refX = refX - ( aModule->GetPosition().x * scale + dx ); refY = refY - ( -aModule->GetPosition().y * scale + dy ); refA = refA - rotz; refA *= refA; refX *= refX; refY *= refY; refX += refY; // conditions: same side, X,Y coordinates within 10 microns, // angle within 0.01 degree if( ( top && side == IDF3::LYR_BOTTOM ) || ( !top && side == IDF3::LYR_TOP ) || ( refA > 0.0001 ) || ( refX > 0.0001 ) ) { comp->GetPosition( refX, refY, refA, side ); std::ostringstream ostr; ostr << "* " << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__ << "():\n"; ostr << "* conflicting Reference Designator '" << refdes << "'\n"; ostr << "* X loc: " << (aModule->GetPosition().x * scale + dx); ostr << " vs. " << refX << "\n"; ostr << "* Y loc: " << (-aModule->GetPosition().y * scale + dy); ostr << " vs. " << refY << "\n"; ostr << "* angle: " << rotz; ostr << " vs. " << refA << "\n"; if( top ) ostr << "* TOP vs. "; else ostr << "* BOTTOM vs. "; if( side == IDF3::LYR_TOP ) ostr << "TOP"; else ostr << "BOTTOM"; throw( std::runtime_error( ostr.str() ) ); } } } // create the local data ... IDF3_COMP_OUTLINE_DATA* data = new IDF3_COMP_OUTLINE_DATA( comp, outline ); data->SetOffsets( locx, locy, locz, lrot ); comp->AddOutlineData( data ); } return; }
void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event ) { if( !padValuesOK() ) return; bool rastnestIsChanged = false; int isign = m_isFlipped ? -1 : 1; transferDataToPad( m_padMaster ); // m_padMaster is a pattern: ensure there is no net for this pad: m_padMaster->SetNetCode( NETINFO_LIST::UNCONNECTED ); if( m_currentPad ) // Set current Pad parameters { wxSize size; MODULE* module = m_currentPad->GetParent(); m_parent->SaveCopyInUndoList( module, UR_CHANGED ); module->SetLastEditTime(); // redraw the area where the pad was, without pad (delete pad on screen) m_currentPad->SetFlags( DO_NOT_DRAW ); m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() ); m_currentPad->ClearFlags( DO_NOT_DRAW ); // Update values m_currentPad->SetShape( m_padMaster->GetShape() ); m_currentPad->SetAttribute( m_padMaster->GetAttribute() ); if( m_currentPad->GetPosition() != m_padMaster->GetPosition() ) { m_currentPad->SetPosition( m_padMaster->GetPosition() ); rastnestIsChanged = true; } // compute the pos 0 value, i.e. pad position for module with orientation = 0 // i.e. relative to module origin (module position) wxPoint pt = m_currentPad->GetPosition() - module->GetPosition(); RotatePoint( &pt, -module->GetOrientation() ); m_currentPad->SetPos0( pt ); m_currentPad->SetOrientation( m_padMaster->GetOrientation() * isign + module->GetOrientation() ); m_currentPad->SetSize( m_padMaster->GetSize() ); size = m_padMaster->GetDelta(); size.y *= isign; m_currentPad->SetDelta( size ); m_currentPad->SetDrillSize( m_padMaster->GetDrillSize() ); m_currentPad->SetDrillShape( m_padMaster->GetDrillShape() ); wxPoint offset = m_padMaster->GetOffset(); offset.y *= isign; m_currentPad->SetOffset( offset ); m_currentPad->SetPadToDieLength( m_padMaster->GetPadToDieLength() ); if( m_currentPad->GetLayerSet() != m_padMaster->GetLayerSet() ) { rastnestIsChanged = true; m_currentPad->SetLayerSet( m_padMaster->GetLayerSet() ); } if( m_isFlipped ) m_currentPad->SetLayerSet( FlipLayerMask( m_currentPad->GetLayerSet() ) ); m_currentPad->SetPadName( m_padMaster->GetPadName() ); wxString padNetname; // For PAD_HOLE_NOT_PLATED, ensure there is no net name selected if( m_padMaster->GetAttribute() != PAD_HOLE_NOT_PLATED ) padNetname = m_PadNetNameCtrl->GetValue(); if( m_currentPad->GetNetname() != padNetname ) { const NETINFO_ITEM* netinfo = m_board->FindNet( padNetname ); if( !padNetname.IsEmpty() && netinfo == NULL ) { DisplayError( NULL, _( "Unknown netname, netname not changed" ) ); } else { rastnestIsChanged = true; m_currentPad->SetNetCode( netinfo->GetNet() ); } } m_currentPad->SetLocalClearance( m_padMaster->GetLocalClearance() ); m_currentPad->SetLocalSolderMaskMargin( m_padMaster->GetLocalSolderMaskMargin() ); m_currentPad->SetLocalSolderPasteMargin( m_padMaster->GetLocalSolderPasteMargin() ); m_currentPad->SetLocalSolderPasteMarginRatio( m_padMaster->GetLocalSolderPasteMarginRatio() ); m_currentPad->SetZoneConnection( m_padMaster->GetZoneConnection() ); m_currentPad->SetThermalWidth( m_padMaster->GetThermalWidth() ); m_currentPad->SetThermalGap( m_padMaster->GetThermalGap() ); module->CalculateBoundingBox(); m_parent->SetMsgPanel( m_currentPad ); // redraw the area where the pad was m_parent->GetCanvas()->RefreshDrawingRect( m_currentPad->GetBoundingBox() ); m_parent->OnModify(); } EndModal( wxID_OK ); if( rastnestIsChanged ) // The net ratsnest must be recalculated m_board->m_Status_Pcb = 0; }
void DIALOG_PAD_PROPERTIES::initValues() { wxString msg; double angle; // Disable pad net name wxTextCtrl if the caller is the footprint editor // because nets are living only in the board managed by the board editor m_canEditNetName = m_parent->IsType( FRAME_PCB ); // Setup layers names from board // Should be made first, before calling m_rbCopperLayersSel->SetSelection() m_rbCopperLayersSel->SetString( 0, m_board->GetLayerName( F_Cu ) ); m_rbCopperLayersSel->SetString( 1, m_board->GetLayerName( B_Cu ) ); m_PadLayerAdhCmp->SetLabel( m_board->GetLayerName( F_Adhes ) ); m_PadLayerAdhCu->SetLabel( m_board->GetLayerName( B_Adhes ) ); m_PadLayerPateCmp->SetLabel( m_board->GetLayerName( F_Paste ) ); m_PadLayerPateCu->SetLabel( m_board->GetLayerName( B_Paste ) ); m_PadLayerSilkCmp->SetLabel( m_board->GetLayerName( F_SilkS ) ); m_PadLayerSilkCu->SetLabel( m_board->GetLayerName( B_SilkS ) ); m_PadLayerMaskCmp->SetLabel( m_board->GetLayerName( F_Mask ) ); m_PadLayerMaskCu->SetLabel( m_board->GetLayerName( B_Mask ) ); m_PadLayerECO1->SetLabel( m_board->GetLayerName( Eco1_User ) ); m_PadLayerECO2->SetLabel( m_board->GetLayerName( Eco2_User ) ); m_PadLayerDraft->SetLabel( m_board->GetLayerName( Dwgs_User ) ); m_isFlipped = false; if( m_currentPad ) { MODULE* module = m_currentPad->GetParent(); if( module->GetLayer() == B_Cu ) { m_isFlipped = true; m_staticModuleSideValue->SetLabel( _( "Back side (footprint is mirrored)" ) ); } msg.Printf( wxT( "%.1f" ), module->GetOrientation() / 10.0 ); m_staticModuleRotValue->SetLabel( msg ); } if( m_isFlipped ) { wxPoint pt = m_dummyPad->GetOffset(); NEGATE( pt.y ); m_dummyPad->SetOffset( pt ); wxSize sz = m_dummyPad->GetDelta(); NEGATE( sz.y ); m_dummyPad->SetDelta( sz ); // flip pad's layers m_dummyPad->SetLayerSet( FlipLayerMask( m_dummyPad->GetLayerSet() ) ); } m_staticTextWarningPadFlipped->Show(m_isFlipped); m_PadNumCtrl->SetValue( m_dummyPad->GetPadName() ); m_PadNetNameCtrl->SetValue( m_dummyPad->GetNetname() ); // Display current unit name in dialog: m_PadPosX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadPosY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadDrill_X_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadDrill_Y_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeSizeX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeSizeY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeOffsetX_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeOffsetY_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadShapeDelta_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_PadLengthDie_Unit->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); // Display current pad masks clearances units m_NetClearanceUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_SolderMaskMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_SolderPasteMarginUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_ThermalWidthUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); m_ThermalGapUnits->SetLabel( GetAbbreviatedUnitsLabel( g_UserUnit ) ); // Display current pad parameters units: PutValueInLocalUnits( *m_PadPosition_X_Ctrl, m_dummyPad->GetPosition().x ); PutValueInLocalUnits( *m_PadPosition_Y_Ctrl, m_dummyPad->GetPosition().y ); PutValueInLocalUnits( *m_PadDrill_X_Ctrl, m_dummyPad->GetDrillSize().x ); PutValueInLocalUnits( *m_PadDrill_Y_Ctrl, m_dummyPad->GetDrillSize().y ); PutValueInLocalUnits( *m_ShapeSize_X_Ctrl, m_dummyPad->GetSize().x ); PutValueInLocalUnits( *m_ShapeSize_Y_Ctrl, m_dummyPad->GetSize().y ); PutValueInLocalUnits( *m_ShapeOffset_X_Ctrl, m_dummyPad->GetOffset().x ); PutValueInLocalUnits( *m_ShapeOffset_Y_Ctrl, m_dummyPad->GetOffset().y ); if( m_dummyPad->GetDelta().x ) { PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().x ); m_trapDeltaDirChoice->SetSelection( 0 ); } else { PutValueInLocalUnits( *m_ShapeDelta_Ctrl, m_dummyPad->GetDelta().y ); m_trapDeltaDirChoice->SetSelection( 1 ); } PutValueInLocalUnits( *m_LengthPadToDieCtrl, m_dummyPad->GetPadToDieLength() ); PutValueInLocalUnits( *m_NetClearanceValueCtrl, m_dummyPad->GetLocalClearance() ); PutValueInLocalUnits( *m_SolderMaskMarginCtrl, m_dummyPad->GetLocalSolderMaskMargin() ); PutValueInLocalUnits( *m_ThermalWidthCtrl, m_dummyPad->GetThermalWidth() ); PutValueInLocalUnits( *m_ThermalGapCtrl, m_dummyPad->GetThermalGap() ); // These 2 parameters are usually < 0, so prepare entering a negative value, if current is 0 PutValueInLocalUnits( *m_SolderPasteMarginCtrl, m_dummyPad->GetLocalSolderPasteMargin() ); if( m_dummyPad->GetLocalSolderPasteMargin() == 0 ) m_SolderPasteMarginCtrl->SetValue( wxT( "-" ) + m_SolderPasteMarginCtrl->GetValue() ); msg.Printf( wxT( "%f" ), m_dummyPad->GetLocalSolderPasteMarginRatio() * 100.0 ); if( m_dummyPad->GetLocalSolderPasteMarginRatio() == 0.0 && msg[0] == '0' ) // Sometimes Printf adds a sign if the value is small m_SolderPasteMarginRatioCtrl->SetValue( wxT( "-" ) + msg ); else m_SolderPasteMarginRatioCtrl->SetValue( msg ); switch( m_dummyPad->GetZoneConnection() ) { default: case UNDEFINED_CONNECTION: m_ZoneConnectionChoice->SetSelection( 0 ); break; case PAD_IN_ZONE: m_ZoneConnectionChoice->SetSelection( 1 ); break; case THERMAL_PAD: m_ZoneConnectionChoice->SetSelection( 2 ); break; case PAD_NOT_IN_ZONE: m_ZoneConnectionChoice->SetSelection( 3 ); break; } if( m_currentPad ) { MODULE* module = m_currentPad->GetParent(); angle = m_currentPad->GetOrientation() - module->GetOrientation(); if( m_isFlipped ) NEGATE( angle ); m_dummyPad->SetOrientation( angle ); } angle = m_dummyPad->GetOrientation(); NORMALIZE_ANGLE_180( angle ); // ? normalizing is in D_PAD::SetOrientation() // Set layers used by this pad: : setPadLayersList( m_dummyPad->GetLayerSet() ); // Pad Orient switch( int( angle ) ) { case 0: m_PadOrient->SetSelection( 0 ); break; case 900: m_PadOrient->SetSelection( 1 ); break; case -900: m_PadOrient->SetSelection( 2 ); break; case 1800: case -1800: m_PadOrient->SetSelection( 3 ); break; default: m_PadOrient->SetSelection( 4 ); break; } switch( m_dummyPad->GetShape() ) { default: case PAD_CIRCLE: m_PadShape->SetSelection( 0 ); break; case PAD_OVAL: m_PadShape->SetSelection( 1 ); break; case PAD_RECT: m_PadShape->SetSelection( 2 ); break; case PAD_TRAPEZOID: m_PadShape->SetSelection( 3 ); break; } msg.Printf( wxT( "%g" ), angle ); m_PadOrientCtrl->SetValue( msg ); // Type of pad selection m_PadType->SetSelection( 0 ); for( unsigned ii = 0; ii < DIM( code_type ); ii++ ) { if( code_type[ii] == m_dummyPad->GetAttribute() ) { m_PadType->SetSelection( ii ); break; } } // Enable/disable Pad name,and pad length die // (disable for NPTH pads (mechanical pads) bool enable = m_dummyPad->GetAttribute() != PAD_HOLE_NOT_PLATED; m_PadNumCtrl->Enable( enable ); m_PadNetNameCtrl->Enable( m_canEditNetName && enable && m_currentPad != NULL ); m_LengthPadToDieCtrl->Enable( enable ); if( m_dummyPad->GetDrillShape() != PAD_DRILL_OBLONG ) m_DrillShapeCtrl->SetSelection( 0 ); else m_DrillShapeCtrl->SetSelection( 1 ); // Update some dialog widgets state (Enable/disable options): wxCommandEvent cmd_event; setPadLayersList( m_dummyPad->GetLayerSet() ); OnDrillShapeSelected( cmd_event ); OnPadShapeSelection( cmd_event ); }
bool BOARD_NETLIST_UPDATER::deleteSinglePadNets() { int count = 0; wxString netname; wxString msg; D_PAD* pad = NULL; D_PAD* previouspad = NULL; // We need the pad list, for next tests. // padlist is the list of pads, sorted by netname. m_board->BuildListOfNets(); if( m_isDryRun ) return false; std::vector<D_PAD*> padlist = m_board->GetPads(); for( unsigned kk = 0; kk < padlist.size(); kk++ ) { pad = padlist[kk]; if( pad->GetNetname().IsEmpty() ) continue; if( netname != pad->GetNetname() ) // End of net { if( previouspad && count == 1 ) { // First, see if we have a copper zone attached to this pad. // If so, this is not really a single pad net for( int ii = 0; ii < m_board->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = m_board->GetArea( ii ); if( !zone->IsOnCopperLayer() ) continue; if( zone->GetIsKeepout() ) continue; if( zone->GetNet() == previouspad->GetNet() ) { count++; break; } } if( count == 1 ) // Really one pad, and nothing else { msg.Printf( _( "Remove single pad net %s." ), GetChars( previouspad->GetNetname() ) ); m_reporter->Report( msg, REPORTER::RPT_ACTION ); msg.Printf( _( "Remove single pad net \"%s\" on \"%s\" pad '%s'\n" ), GetChars( previouspad->GetNetname() ), GetChars( previouspad->GetParent()->GetReference() ), GetChars( previouspad->GetPadName() ) ); m_reporter->Report( msg, REPORTER::RPT_ACTION ); previouspad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } } netname = pad->GetNetname(); count = 1; } else { count++; } previouspad = pad; } // Examine last pad if( pad && count == 1 ) pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); return true; }
bool BOARD_NETLIST_UPDATER::updateComponentPadConnections( MODULE* aPcbComponent, COMPONENT* aNewComponent ) { wxString msg; bool changed = false; MODULE* copy = (MODULE*) aPcbComponent->Clone(); // At this point, the component footprint is updated. Now update the nets. for( D_PAD* pad = aPcbComponent->Pads(); pad; pad = pad->Next() ) { COMPONENT_NET net = aNewComponent->GetNet( pad->GetPadName() ); if( !net.IsValid() ) // New footprint pad has no net. { if( !pad->GetNetname().IsEmpty() ) { msg.Printf( _( "Disconnect component %s pin %s.\n" ), GetChars( aPcbComponent->GetReference() ), GetChars( pad->GetPadName() ) ); m_reporter->Report( msg, REPORTER::RPT_ACTION ); msg.Printf( _( "Clearing component \"%s:%s\" pin \"%s\" net name.\n" ), GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetPath() ), GetChars( pad->GetPadName() ) ); m_reporter->Report( msg, REPORTER::RPT_INFO ); } if( !m_isDryRun ) { changed = true; pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); } } else // New footprint pad has a net. { if( net.GetNetName() != pad->GetNetname() ) { const wxString& netName = net.GetNetName(); NETINFO_ITEM* netinfo = m_board->FindNet( netName ); if( netinfo == nullptr ) { // It might be a new net that has not been added to the board yet auto netIt = m_addedNets.find( netName ); if( netIt != m_addedNets.end() ) netinfo = netIt->second; } if( netinfo == nullptr ) { // It is a new net, we have to add it if( !m_isDryRun ) { changed = true; netinfo = new NETINFO_ITEM( m_board, netName ); m_commit.Add( netinfo ); m_addedNets[netName] = netinfo; } msg.Printf( _( "Add net %s.\n" ), GetChars( netName ) ); m_reporter->Report( msg, REPORTER::RPT_ACTION ); } if( !pad->GetNetname().IsEmpty() ) { msg.Printf( _( "Reconnect component %s pin %s from net %s to net %s.\n"), GetChars( aPcbComponent->GetReference() ), GetChars( pad->GetPadName() ), GetChars( pad->GetNetname() ), GetChars( netName ) ); } else { msg.Printf( _( "Connect component %s pin %s to net %s.\n"), GetChars( aPcbComponent->GetReference() ), GetChars( pad->GetPadName() ), GetChars( netName ) ); } m_reporter->Report( msg, REPORTER::RPT_ACTION ); msg.Printf( _( "Changing component \"%s:%s\" pin \"%s\" net name from " "\"%s\" to \"%s\".\n" ), GetChars( aPcbComponent->GetReference() ), GetChars( aPcbComponent->GetPath() ), GetChars( pad->GetPadName() ), GetChars( pad->GetNetname() ), GetChars( netName ) ); m_reporter->Report( msg, REPORTER::RPT_INFO ); if( !m_isDryRun ) { changed = true; pad->SetNet( netinfo ); } } } } if( changed ) m_commit.Modified( aPcbComponent, copy ); else delete copy; return true; }