more amazing free specctra work
This commit is contained in:
parent
10ded82dbd
commit
709be49518
|
@ -5,20 +5,29 @@ Started 2007-June-11
|
||||||
Please add newer entries at the top, list the date and your name with
|
Please add newer entries at the top, list the date and your name with
|
||||||
email address.
|
email address.
|
||||||
|
|
||||||
|
2008-Feb-13 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
|
================================================================================
|
||||||
|
+pcbnew
|
||||||
|
specctra export: now generate unique pin names from module padnames in the
|
||||||
|
case where there are non-unique pad names within a module. Tested with
|
||||||
|
Electra demo, and *.dsn files load OK in there as well as in freerouter.
|
||||||
|
Stopped using reserved layer name "signal" and instead output a full
|
||||||
|
padstack consisting of all pertinent layers for via, pads, and keepouts.
|
||||||
|
|
||||||
|
|
||||||
2008-Feb-12 UPDATE Tim Hanson sideskate@gmail.com
|
2008-Feb-12 UPDATE Tim Hanson sideskate@gmail.com
|
||||||
================================================================================
|
================================================================================
|
||||||
+eeschema
|
+eeschema
|
||||||
* commiting my changes to allow multiple instances of a given schematic file within a hierarchy:
|
* commiting my changes to allow multiple instances of a given schematic file within a hierarchy:
|
||||||
** internally, m_currentScreen has been replaced with m_currentSheet,
|
** internally, m_currentScreen has been replaced with m_currentSheet,
|
||||||
which is a list or 'path' of screens. The path of screens is used to generate
|
which is a list or 'path' of screens. The path of screens is used to generate
|
||||||
a series of timestamps, which is converted to flat component reference via a look-up
|
a series of timestamps, which is converted to flat component reference via a look-up
|
||||||
table in the schematic files.
|
table in the schematic files.
|
||||||
** this means that m_currentScreen is no longer used -- use GetScreen().
|
** this means that m_currentScreen is no longer used -- use GetScreen().
|
||||||
** GetScreen is virtual, as some of the dialogs keep around a WinEDA_BaseScreen pointer.
|
** GetScreen is virtual, as some of the dialogs keep around a WinEDA_BaseScreen pointer.
|
||||||
** all sub-sheets in a given schematic must have different names to generate a meaningful netlist.
|
** all sub-sheets in a given schematic must have different names to generate a meaningful netlist.
|
||||||
|
|
||||||
|
|
||||||
=======
|
|
||||||
2008-Feb-12 UPDATE Igor Plyatov <plyatov@mail.ru>
|
2008-Feb-12 UPDATE Igor Plyatov <plyatov@mail.ru>
|
||||||
================================================================================
|
================================================================================
|
||||||
+eeschema
|
+eeschema
|
||||||
|
@ -26,6 +35,7 @@ email address.
|
||||||
+all
|
+all
|
||||||
Russian translation update.
|
Russian translation update.
|
||||||
|
|
||||||
|
|
||||||
2008-Feb-11 UPDATE Dick Hollenbeck <dick@softplc.com>
|
2008-Feb-11 UPDATE Dick Hollenbeck <dick@softplc.com>
|
||||||
================================================================================
|
================================================================================
|
||||||
+pcbnew
|
+pcbnew
|
||||||
|
|
|
@ -27,7 +27,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
wxString text, msg;
|
wxString text, msg;
|
||||||
const BOARD_ITEM* item = this;
|
const BOARD_ITEM* item = this;
|
||||||
EQUIPOT* net;
|
EQUIPOT* net;
|
||||||
D_PAD * pad;
|
D_PAD * pad;
|
||||||
|
|
||||||
switch( item->Type() )
|
switch( item->Type() )
|
||||||
{
|
{
|
||||||
|
@ -42,17 +42,17 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEPAD:
|
case TYPEPAD:
|
||||||
pad = (D_PAD *) this;
|
pad = (D_PAD *) this;
|
||||||
text << _( "Pad" ) << wxT( " \"" ) << pad->ReturnStringPadName()
|
text << _( "Pad" ) << wxT( " \"" ) << pad->ReturnStringPadName()
|
||||||
<< wxT( "\" (" );
|
<< wxT( "\" (" );
|
||||||
if ( (pad->m_Masque_Layer & ALL_CU_LAYERS) == ALL_CU_LAYERS )
|
if ( (pad->m_Masque_Layer & ALL_CU_LAYERS) == ALL_CU_LAYERS )
|
||||||
text << _("all copper layers");
|
text << _("all copper layers");
|
||||||
else if( (pad->m_Masque_Layer & CUIVRE_LAYER) == CUIVRE_LAYER )
|
else if( (pad->m_Masque_Layer & CUIVRE_LAYER) == CUIVRE_LAYER )
|
||||||
text << _("copper layer");
|
text << _("copper layer");
|
||||||
else if( (pad->m_Masque_Layer & CMP_LAYER) == CMP_LAYER )
|
else if( (pad->m_Masque_Layer & CMP_LAYER) == CMP_LAYER )
|
||||||
text << _("cmp layer");
|
text << _("cmp layer");
|
||||||
else text << _("???");
|
else text << _("???");
|
||||||
text << _( ") of " ) << ( (MODULE*) GetParent() )->GetReference();
|
text << _( ") of " ) << ( (MODULE*) GetParent() )->GetReference();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEDRAWSEGMENT:
|
case TYPEDRAWSEGMENT:
|
||||||
|
@ -89,7 +89,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEEDGEMODULE:
|
case TYPEEDGEMODULE:
|
||||||
{
|
{
|
||||||
text << _( "Graphic" ) << wxT( " " );
|
text << _( "Graphic" ) << wxT( " " );
|
||||||
wxString cp;
|
wxString cp;
|
||||||
|
|
||||||
|
@ -129,10 +129,10 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
|
|
||||||
text << cp;
|
text << cp;
|
||||||
text << wxT( " (" ) << ReturnPcbLayerName( ((EDGE_MODULE*) item )->m_Layer ).Trim() << wxT( ")" );
|
text << wxT( " (" ) << ReturnPcbLayerName( ((EDGE_MODULE*) item )->m_Layer ).Trim() << wxT( ")" );
|
||||||
text << _( " of " )
|
text << _( " of " )
|
||||||
<< ( (MODULE*) GetParent() )->GetReference();
|
<< ( (MODULE*) GetParent() )->GetReference();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPETRACK:
|
case TYPETRACK:
|
||||||
// deleting tracks requires all the information we can get to
|
// deleting tracks requires all the information we can get to
|
||||||
// disambiguate all the crap under the cursor!
|
// disambiguate all the crap under the cursor!
|
||||||
|
@ -153,36 +153,36 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
|
|
||||||
case TYPEZONE_CONTAINER:
|
case TYPEZONE_CONTAINER:
|
||||||
text = _( "Zone Outline" );
|
text = _( "Zone Outline" );
|
||||||
{
|
{
|
||||||
ZONE_CONTAINER* area = (ZONE_CONTAINER*) this;
|
ZONE_CONTAINER* area = (ZONE_CONTAINER*) this;
|
||||||
int ncont = area->m_Poly->GetContour(area->m_CornerSelection);
|
int ncont = area->m_Poly->GetContour(area->m_CornerSelection);
|
||||||
if ( ncont ) text << wxT(" ") << _("(Cutout)");
|
if ( ncont ) text << wxT(" ") << _("(Cutout)");
|
||||||
}
|
}
|
||||||
text << wxT( " " );
|
text << wxT( " " );
|
||||||
{
|
{
|
||||||
wxString TimeStampText;
|
wxString TimeStampText;
|
||||||
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
|
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
|
||||||
text << TimeStampText;
|
text << TimeStampText;
|
||||||
}
|
}
|
||||||
if ( ((ZONE_CONTAINER*) item)->GetNet() >= 0 )
|
if ( ((ZONE_CONTAINER*) item)->GetNet() >= 0 )
|
||||||
{
|
{
|
||||||
net = aPcb->FindNet( ( (ZONE_CONTAINER*) item )->GetNet() );
|
net = aPcb->FindNet( ( (ZONE_CONTAINER*) item )->GetNet() );
|
||||||
if( net )
|
if( net )
|
||||||
{
|
{
|
||||||
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
|
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // A netcode < 0 is an error flag (Netname not found or area not initialised)
|
else // A netcode < 0 is an error flag (Netname not found or area not initialised)
|
||||||
{
|
{
|
||||||
text << wxT( " [" ) << ( (ZONE_CONTAINER*) item )->m_Netname << wxT( "]" );
|
text << wxT( " [" ) << ( (ZONE_CONTAINER*) item )->m_Netname << wxT( "]" );
|
||||||
text << wxT(" <") << _("Not Found") << wxT(">");
|
text << wxT(" <") << _("Not Found") << wxT(">");
|
||||||
}
|
}
|
||||||
text << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim();
|
text << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEZONE:
|
case TYPEZONE:
|
||||||
text = _( "Zone" );
|
text = _( "Zone" );
|
||||||
text << wxT( " " );
|
text << wxT( " " );
|
||||||
{
|
{
|
||||||
wxString TimeStampText;
|
wxString TimeStampText;
|
||||||
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
|
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
|
||||||
|
@ -213,6 +213,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
{
|
{
|
||||||
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
|
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
|
||||||
}
|
}
|
||||||
|
text << wxChar(' ') << _("Net:") << via->GetNet();
|
||||||
|
|
||||||
if( shape != VIA_THROUGH )
|
if( shape != VIA_THROUGH )
|
||||||
{
|
{
|
||||||
|
@ -236,7 +237,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPEMIRE:
|
case TYPEMIRE:
|
||||||
valeur_param( ((MIREPCB*)item)->m_Size, msg );
|
valeur_param( ((MIREPCB*)item)->m_Size, msg );
|
||||||
text << _( "Target" ) << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim()
|
text << _( "Target" ) << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim()
|
||||||
<< wxT( " " ) << _( "size" ) << wxT( " " ) << msg
|
<< wxT( " " ) << _( "size" ) << wxT( " " ) << msg
|
||||||
;
|
;
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace DSN {
|
||||||
|
|
||||||
//-----<SPECCTRA_DB>-------------------------------------------------
|
//-----<SPECCTRA_DB>-------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(STANDALONE)
|
||||||
|
|
||||||
void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard )
|
void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard )
|
||||||
{
|
{
|
||||||
|
@ -100,6 +101,7 @@ void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard )
|
||||||
layerIds.push_back( CONV_TO_UTF8( aBoard->GetLayerName( kilayer ) ) );
|
layerIds.push_back( CONV_TO_UTF8( aBoard->GetLayerName( kilayer ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int SPECCTRA_DB::findLayerName( const std::string& aLayerName ) const
|
int SPECCTRA_DB::findLayerName( const std::string& aLayerName ) const
|
||||||
|
@ -183,13 +185,21 @@ void SPECCTRA_DB::needRIGHT() throw( IOError )
|
||||||
expecting( T_RIGHT );
|
expecting( T_RIGHT );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPECCTRA_DB::needSYMBOL() throw( IOError )
|
DSN_T SPECCTRA_DB::needSYMBOL() throw( IOError )
|
||||||
{
|
{
|
||||||
DSN_T tok = nextTok();
|
DSN_T tok = nextTok();
|
||||||
if( !isSymbol( tok ) )
|
if( !isSymbol( tok ) )
|
||||||
expecting( T_SYMBOL );
|
expecting( T_SYMBOL );
|
||||||
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DSN_T SPECCTRA_DB::needSYMBOLorNUMBER() throw( IOError )
|
||||||
|
{
|
||||||
|
DSN_T tok = nextTok();
|
||||||
|
if( !isSymbol( tok ) && tok!=T_NUMBER )
|
||||||
|
expecting( "symbol|number" );
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError )
|
void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError )
|
||||||
{
|
{
|
||||||
|
@ -467,7 +477,9 @@ void SPECCTRA_DB::doPCB( PCB* growth ) throw( IOError )
|
||||||
|
|
||||||
void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
|
void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
|
||||||
{
|
{
|
||||||
DSN_T tok;
|
DSN_T tok;
|
||||||
|
std::string const1;
|
||||||
|
std::string const2;
|
||||||
|
|
||||||
/* <parser_descriptor >::=
|
/* <parser_descriptor >::=
|
||||||
(parser
|
(parser
|
||||||
|
@ -519,17 +531,19 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_host_version:
|
case T_host_version:
|
||||||
needSYMBOL();
|
needSYMBOLorNUMBER();
|
||||||
growth->host_version = lexer->CurText();
|
growth->host_version = lexer->CurText();
|
||||||
needRIGHT();
|
needRIGHT();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_constant:
|
case T_constant:
|
||||||
needSYMBOL();
|
needSYMBOLorNUMBER();
|
||||||
growth->const_id1 = lexer->CurText();
|
const1 = lexer->CurText();
|
||||||
needSYMBOL();
|
needSYMBOLorNUMBER();
|
||||||
growth->const_id2 = lexer->CurText();
|
const2 = lexer->CurText();
|
||||||
needRIGHT();
|
needRIGHT();
|
||||||
|
growth->constants.push_back( const1 );
|
||||||
|
growth->constants.push_back( const2 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
|
case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
|
||||||
|
@ -710,6 +724,8 @@ void SPECCTRA_DB::doSTRUCTURE( STRUCTURE* growth ) throw(IOError)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_layer_noise_weight:
|
case T_layer_noise_weight:
|
||||||
|
if( growth->layer_noise_weight )
|
||||||
|
unexpected( tok );
|
||||||
growth->layer_noise_weight = new LAYER_NOISE_WEIGHT( growth );
|
growth->layer_noise_weight = new LAYER_NOISE_WEIGHT( growth );
|
||||||
doLAYER_NOISE_WEIGHT( growth->layer_noise_weight );
|
doLAYER_NOISE_WEIGHT( growth->layer_noise_weight );
|
||||||
break;
|
break;
|
||||||
|
@ -755,11 +771,15 @@ L_place:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_via:
|
case T_via:
|
||||||
|
if( growth->via )
|
||||||
|
unexpected( tok );
|
||||||
growth->via = new VIA( growth );
|
growth->via = new VIA( growth );
|
||||||
doVIA( growth->via );
|
doVIA( growth->via );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_control:
|
case T_control:
|
||||||
|
if( growth->control )
|
||||||
|
unexpected( tok );
|
||||||
growth->control = new CONTROL( growth );
|
growth->control = new CONTROL( growth );
|
||||||
doCONTROL( growth->control );
|
doCONTROL( growth->control );
|
||||||
break;
|
break;
|
||||||
|
@ -772,11 +792,15 @@ L_place:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_rule:
|
case T_rule:
|
||||||
|
if( growth->rules )
|
||||||
|
unexpected( tok );
|
||||||
growth->rules = new RULE( growth, T_rule );
|
growth->rules = new RULE( growth, T_rule );
|
||||||
doRULE( growth->rules );
|
doRULE( growth->rules );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_place_rule:
|
case T_place_rule:
|
||||||
|
if( growth->place_rules )
|
||||||
|
unexpected( tok );
|
||||||
growth->place_rules = new RULE( growth, T_place_rule );
|
growth->place_rules = new RULE( growth, T_place_rule );
|
||||||
doRULE( growth->place_rules );
|
doRULE( growth->place_rules );
|
||||||
break;
|
break;
|
||||||
|
@ -2219,35 +2243,35 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError )
|
||||||
|
|
||||||
growth->padstack_id = lexer->CurText();
|
growth->padstack_id = lexer->CurText();
|
||||||
|
|
||||||
tok = nextTok();
|
while( (tok = nextTok()) != T_RIGHT )
|
||||||
if( tok == T_LEFT )
|
|
||||||
{
|
{
|
||||||
tok = nextTok();
|
if( tok == T_LEFT )
|
||||||
if( tok != T_rotate )
|
{
|
||||||
expecting( T_rotate );
|
tok = nextTok();
|
||||||
|
if( tok != T_rotate )
|
||||||
|
expecting( T_rotate );
|
||||||
|
|
||||||
if( nextTok() != T_NUMBER )
|
if( nextTok() != T_NUMBER )
|
||||||
expecting( T_NUMBER );
|
expecting( T_NUMBER );
|
||||||
growth->SetRotation( strtod( lexer->CurText(), 0 ) );
|
growth->SetRotation( strtod( lexer->CurText(), 0 ) );
|
||||||
needRIGHT();
|
needRIGHT();
|
||||||
tok = nextTok();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !isSymbol(tok) && tok!=T_NUMBER )
|
||||||
|
expecting( "pin_id" );
|
||||||
|
|
||||||
|
growth->pin_id = lexer->CurText();
|
||||||
|
|
||||||
|
if( nextTok() != T_NUMBER )
|
||||||
|
expecting( T_NUMBER );
|
||||||
|
growth->vertex.x = strtod( lexer->CurText(), 0 );
|
||||||
|
|
||||||
|
if( nextTok() != T_NUMBER )
|
||||||
|
expecting( T_NUMBER );
|
||||||
|
growth->vertex.y = strtod( lexer->CurText(), 0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isSymbol(tok) && tok!=T_NUMBER )
|
|
||||||
expecting( "pin_id" );
|
|
||||||
|
|
||||||
growth->pin_id = lexer->CurText();
|
|
||||||
|
|
||||||
if( nextTok() != T_NUMBER )
|
|
||||||
expecting( T_NUMBER );
|
|
||||||
growth->vertex.x = strtod( lexer->CurText(), 0 );
|
|
||||||
|
|
||||||
if( nextTok() != T_NUMBER )
|
|
||||||
expecting( T_NUMBER );
|
|
||||||
growth->vertex.y = strtod( lexer->CurText(), 0 );
|
|
||||||
|
|
||||||
if( nextTok() != T_RIGHT )
|
|
||||||
unexpected( lexer->CurText() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2286,8 +2310,8 @@ void SPECCTRA_DB::doLIBRARY( LIBRARY* growth ) throw( IOError )
|
||||||
|
|
||||||
case T_padstack:
|
case T_padstack:
|
||||||
PADSTACK* padstack;
|
PADSTACK* padstack;
|
||||||
padstack = new PADSTACK( growth );
|
padstack = new PADSTACK();
|
||||||
growth->padstacks.push_back( padstack );
|
growth->AddPadstack( padstack );
|
||||||
doPADSTACK( padstack );
|
doPADSTACK( padstack );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2307,7 +2331,8 @@ void SPECCTRA_DB::doLIBRARY( LIBRARY* growth ) throw( IOError )
|
||||||
|
|
||||||
void SPECCTRA_DB::doNET( NET* growth ) throw( IOError )
|
void SPECCTRA_DB::doNET( NET* growth ) throw( IOError )
|
||||||
{
|
{
|
||||||
DSN_T tok = nextTok();
|
DSN_T tok = nextTok();
|
||||||
|
PIN_REFS* pin_refs;
|
||||||
|
|
||||||
/* <net_descriptor >::=
|
/* <net_descriptor >::=
|
||||||
(net <net_id >
|
(net <net_id >
|
||||||
|
@ -2358,14 +2383,38 @@ void SPECCTRA_DB::doNET( NET* growth ) throw( IOError )
|
||||||
case T_pins:
|
case T_pins:
|
||||||
case T_order:
|
case T_order:
|
||||||
growth->pins_type = tok;
|
growth->pins_type = tok;
|
||||||
|
pin_refs = &growth->pins;
|
||||||
|
goto L_pins;
|
||||||
|
|
||||||
|
case T_expose:
|
||||||
|
pin_refs = &growth->expose;
|
||||||
|
goto L_pins;
|
||||||
|
|
||||||
|
case T_noexpose:
|
||||||
|
pin_refs = &growth->noexpose;
|
||||||
|
goto L_pins;
|
||||||
|
|
||||||
|
case T_source:
|
||||||
|
pin_refs = &growth->source;
|
||||||
|
goto L_pins;
|
||||||
|
|
||||||
|
case T_load:
|
||||||
|
pin_refs = &growth->load;
|
||||||
|
goto L_pins;
|
||||||
|
|
||||||
|
case T_terminator:
|
||||||
|
pin_refs = &growth->terminator;
|
||||||
|
//goto L_pins;
|
||||||
|
|
||||||
|
L_pins:
|
||||||
{
|
{
|
||||||
PIN_REF empty( growth );
|
PIN_REF empty( growth );
|
||||||
while( (tok = nextTok()) != T_RIGHT )
|
while( (tok = nextTok()) != T_RIGHT )
|
||||||
{
|
{
|
||||||
// copy the empty one, then fill its copy later thru pin_ref.
|
// copy the empty one, then fill its copy later thru pin_ref.
|
||||||
growth->pins.push_back( empty );
|
pin_refs->push_back( empty );
|
||||||
|
|
||||||
PIN_REF* pin_ref = &growth->pins.back();
|
PIN_REF* pin_ref = &pin_refs->back();
|
||||||
|
|
||||||
readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
|
readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
|
||||||
}
|
}
|
||||||
|
@ -3431,7 +3480,7 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
|
||||||
if( strlen(wrapee)==0 )
|
if( strlen(wrapee)==0 )
|
||||||
return quote_char;
|
return quote_char;
|
||||||
|
|
||||||
bool isNumber = true;
|
// bool isNumber = true;
|
||||||
|
|
||||||
for( ; *wrapee; ++wrapee )
|
for( ; *wrapee; ++wrapee )
|
||||||
{
|
{
|
||||||
|
@ -3444,12 +3493,12 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
|
||||||
if( strchr( quoteThese, *wrapee ) )
|
if( strchr( quoteThese, *wrapee ) )
|
||||||
return quote_char;
|
return quote_char;
|
||||||
|
|
||||||
if( !strchr( "01234567890.-+", *wrapee ) )
|
// if( !strchr( "01234567890.-+", *wrapee ) )
|
||||||
isNumber = false;
|
// isNumber = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isNumber )
|
// if( isNumber )
|
||||||
return quote_char;
|
// return quote_char;
|
||||||
|
|
||||||
return ""; // can use an unwrapped string.
|
return ""; // can use an unwrapped string.
|
||||||
}
|
}
|
||||||
|
@ -3670,6 +3719,11 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// a reasonably small memory price to pay for improved performance
|
||||||
|
STRINGFORMATTER ELEM::sf;
|
||||||
|
|
||||||
|
|
||||||
//-----<UNIT_RES>---------------------------------------------------------
|
//-----<UNIT_RES>---------------------------------------------------------
|
||||||
|
|
||||||
UNIT_RES UNIT_RES::Default( NULL, T_resolution );
|
UNIT_RES UNIT_RES::Default( NULL, T_resolution );
|
||||||
|
@ -3679,6 +3733,8 @@ UNIT_RES UNIT_RES::Default( NULL, T_resolution );
|
||||||
|
|
||||||
int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
|
int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
|
||||||
{
|
{
|
||||||
|
// printf( "PADSTACK::Compare( %p, %p)\n", lhs, rhs );
|
||||||
|
|
||||||
if( !lhs->hash.size() )
|
if( !lhs->hash.size() )
|
||||||
lhs->hash = lhs->makeHash();
|
lhs->hash = lhs->makeHash();
|
||||||
|
|
||||||
|
@ -3725,7 +3781,6 @@ int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* rhs )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//-----<PARSER>-----------------------------------------------------------
|
//-----<PARSER>-----------------------------------------------------------
|
||||||
|
|
||||||
PARSER::PARSER( ELEM* aParent ) :
|
PARSER::PARSER( ELEM* aParent ) :
|
||||||
ELEM( T_parser, aParent )
|
ELEM( T_parser, aParent )
|
||||||
{
|
{
|
||||||
|
@ -3752,10 +3807,17 @@ void PARSER::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOErro
|
||||||
out->Print( nestLevel, "(host_cad \"%s\")\n", host_cad.c_str() );
|
out->Print( nestLevel, "(host_cad \"%s\")\n", host_cad.c_str() );
|
||||||
out->Print( nestLevel, "(host_version \"%s\")\n", host_version.c_str() );
|
out->Print( nestLevel, "(host_version \"%s\")\n", host_version.c_str() );
|
||||||
|
|
||||||
if( const_id1.length()>0 || const_id2.length()>0 )
|
for( STRINGS::iterator i=constants.begin(); i!=constants.end(); )
|
||||||
out->Print( nestLevel, "(constant %c%s%c %c%s%c)\n",
|
{
|
||||||
string_quote, const_id1.c_str(), string_quote,
|
const std::string& s1 = *i++;
|
||||||
string_quote, const_id2.c_str(), string_quote );
|
const std::string& s2 = *i++;
|
||||||
|
|
||||||
|
const char* q1 = out->GetQuoteChar( s1.c_str() );
|
||||||
|
const char* q2 = out->GetQuoteChar( s2.c_str() );
|
||||||
|
out->Print( nestLevel, "(constant %s%s%s %s%s%s)\n",
|
||||||
|
q1, s1.c_str(), q1,
|
||||||
|
q2, s2.c_str(), q2 );
|
||||||
|
}
|
||||||
|
|
||||||
if( routes_include_testpoint || routes_include_guides || routes_include_image_conductor )
|
if( routes_include_testpoint || routes_include_guides || routes_include_image_conductor )
|
||||||
out->Print( nestLevel, "(routes_include%s%s%s)\n",
|
out->Print( nestLevel, "(routes_include%s%s%s)\n",
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
|
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
|
||||||
#include <boost/ptr_container/ptr_vector.hpp>
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
|
// see http://www.boost.org/libs/ptr_container/doc/ptr_set.html
|
||||||
|
#include <boost/ptr_container/ptr_set.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include "fctsys.h"
|
#include "fctsys.h"
|
||||||
#include "dsn.h"
|
#include "dsn.h"
|
||||||
|
|
||||||
|
@ -303,14 +307,16 @@ protected:
|
||||||
*/
|
*/
|
||||||
std::string makeHash()
|
std::string makeHash()
|
||||||
{
|
{
|
||||||
STRINGFORMATTER sf;
|
sf.Clear();
|
||||||
|
|
||||||
FormatContents( &sf, 0 );
|
FormatContents( &sf, 0 );
|
||||||
sf.StripUseless();
|
sf.StripUseless();
|
||||||
|
|
||||||
return sf.GetString();
|
return sf.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// avoid creating this for every compare, make static.
|
||||||
|
static STRINGFORMATTER sf;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -466,8 +472,8 @@ class PARSER : public ELEM
|
||||||
bool via_rotate_first;
|
bool via_rotate_first;
|
||||||
bool generated_by_freeroute;
|
bool generated_by_freeroute;
|
||||||
|
|
||||||
std::string const_id1;
|
/// This holds pairs of strings, one pair for each constant definition
|
||||||
std::string const_id2;
|
STRINGS constants;
|
||||||
|
|
||||||
std::string host_cad;
|
std::string host_cad;
|
||||||
std::string host_version;
|
std::string host_version;
|
||||||
|
@ -1924,12 +1930,16 @@ class PIN : public ELEM
|
||||||
std::string pin_id;
|
std::string pin_id;
|
||||||
POINT vertex;
|
POINT vertex;
|
||||||
|
|
||||||
|
int kiNetCode; ///< kicad netcode
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PIN( ELEM* aParent ) :
|
PIN( ELEM* aParent ) :
|
||||||
ELEM( T_pin, aParent )
|
ELEM( T_pin, aParent )
|
||||||
{
|
{
|
||||||
rotation = 0.0;
|
rotation = 0.0;
|
||||||
isRotated = false;
|
isRotated = false;
|
||||||
|
kiNetCode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRotation( double aRotation )
|
void SetRotation( double aRotation )
|
||||||
|
@ -1960,6 +1970,8 @@ public:
|
||||||
vertex.x, vertex.y );
|
vertex.x, vertex.y );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
typedef boost::ptr_vector<PIN> PINS;
|
||||||
|
|
||||||
|
|
||||||
class LIBRARY;
|
class LIBRARY;
|
||||||
class IMAGE : public ELEM_HOLDER
|
class IMAGE : public ELEM_HOLDER
|
||||||
|
@ -1978,7 +1990,6 @@ class IMAGE : public ELEM_HOLDER
|
||||||
the kids list.
|
the kids list.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef boost::ptr_vector<PIN> PINS;
|
|
||||||
PINS pins;
|
PINS pins;
|
||||||
|
|
||||||
RULE* rules;
|
RULE* rules;
|
||||||
|
@ -2085,7 +2096,7 @@ typedef boost::ptr_vector<IMAGE> IMAGES;
|
||||||
* Class PADSTACK
|
* Class PADSTACK
|
||||||
* holds either a via or a pad definition.
|
* holds either a via or a pad definition.
|
||||||
*/
|
*/
|
||||||
class PADSTACK : public ELEM_HOLDER
|
class PADSTACK : public ELEM_HOLDER, private boost::noncopyable
|
||||||
{
|
{
|
||||||
friend class SPECCTRA_DB;
|
friend class SPECCTRA_DB;
|
||||||
|
|
||||||
|
@ -2105,8 +2116,14 @@ class PADSTACK : public ELEM_HOLDER
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PADSTACK( ELEM* aParent ) :
|
/**
|
||||||
ELEM_HOLDER( T_padstack, aParent )
|
* Constructor PADSTACK()
|
||||||
|
* cannot take ELEM* aParent because PADSTACKSET confuses this with a
|
||||||
|
* copy constructor and causes havoc. Instead set parent with
|
||||||
|
* LIBRARY::AddPadstack()
|
||||||
|
*/
|
||||||
|
PADSTACK() :
|
||||||
|
ELEM_HOLDER( T_padstack, NULL )
|
||||||
{
|
{
|
||||||
unit = 0;
|
unit = 0;
|
||||||
rotate = T_on;
|
rotate = T_on;
|
||||||
|
@ -2131,6 +2148,7 @@ public:
|
||||||
*/
|
*/
|
||||||
static int Compare( PADSTACK* lhs, PADSTACK* rhs );
|
static int Compare( PADSTACK* lhs, PADSTACK* rhs );
|
||||||
|
|
||||||
|
|
||||||
void SetPadstackId( const char* aPadstackId )
|
void SetPadstackId( const char* aPadstackId )
|
||||||
{
|
{
|
||||||
padstack_id = aPadstackId;
|
padstack_id = aPadstackId;
|
||||||
|
@ -2194,6 +2212,15 @@ public:
|
||||||
};
|
};
|
||||||
typedef boost::ptr_vector<PADSTACK> PADSTACKS;
|
typedef boost::ptr_vector<PADSTACK> PADSTACKS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function operator<()
|
||||||
|
* is used by the PADSTACKSET boost::ptr_set below
|
||||||
|
*/
|
||||||
|
inline bool operator<( const PADSTACK& lhs, const PADSTACK& rhs )
|
||||||
|
{
|
||||||
|
return PADSTACK::Compare( (PADSTACK*) &lhs, (PADSTACK*) &rhs ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LIBRARY
|
* Class LIBRARY
|
||||||
|
@ -2228,6 +2255,7 @@ public:
|
||||||
|
|
||||||
void AddPadstack( PADSTACK* aPadstack )
|
void AddPadstack( PADSTACK* aPadstack )
|
||||||
{
|
{
|
||||||
|
aPadstack->SetParent( this );
|
||||||
padstacks.push_back( aPadstack );
|
padstacks.push_back( aPadstack );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2537,10 +2565,15 @@ class NET : public ELEM
|
||||||
bool unassigned;
|
bool unassigned;
|
||||||
int net_number;
|
int net_number;
|
||||||
|
|
||||||
DSN_T pins_type; ///< T_pins | T_order
|
DSN_T pins_type; ///< T_pins | T_order, type of field 'pins' below
|
||||||
|
|
||||||
PIN_REFS pins;
|
PIN_REFS pins;
|
||||||
|
|
||||||
|
PIN_REFS expose;
|
||||||
|
PIN_REFS noexpose;
|
||||||
|
PIN_REFS source;
|
||||||
|
PIN_REFS load;
|
||||||
|
PIN_REFS terminator;
|
||||||
|
|
||||||
DSN_T type; ///< T_fix | T_normal
|
DSN_T type; ///< T_fix | T_normal
|
||||||
|
|
||||||
DSN_T supply; ///< T_power | T_ground
|
DSN_T supply; ///< T_power | T_ground
|
||||||
|
@ -3525,6 +3558,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef boost::ptr_set<PADSTACK> PADSTACKSET;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SPECCTRA_DB
|
* Class SPECCTRA_DB
|
||||||
* holds a DSN data tree, usually coming from a DSN file.
|
* holds a DSN data tree, usually coming from a DSN file.
|
||||||
|
@ -3561,6 +3597,12 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
|
|
||||||
static const KICAD_T scanPADs[];
|
static const KICAD_T scanPADs[];
|
||||||
|
|
||||||
|
PADSTACKSET padstackset;
|
||||||
|
|
||||||
|
/// we don't want ownership here permanently, so we don't use boost::ptr_vector
|
||||||
|
std::vector<NET*> nets;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function buildLayerMaps
|
* Function buildLayerMaps
|
||||||
* creates a few data translation structures for layer name and number
|
* creates a few data translation structures for layer name and number
|
||||||
|
@ -3612,9 +3654,20 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
* calls nextTok() and then verifies that the token read in
|
* calls nextTok() and then verifies that the token read in
|
||||||
* satisfies bool isSymbol().
|
* satisfies bool isSymbol().
|
||||||
* If not, an IOError is thrown.
|
* If not, an IOError is thrown.
|
||||||
|
* @return DSN_T - the actual token read in.
|
||||||
* @throw IOError, if the next token does not satisfy isSymbol()
|
* @throw IOError, if the next token does not satisfy isSymbol()
|
||||||
*/
|
*/
|
||||||
void needSYMBOL() throw( IOError );
|
DSN_T needSYMBOL() throw( IOError );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function needSYMBOLorNUMBER
|
||||||
|
* calls nextTok() and then verifies that the token read in
|
||||||
|
* satisfies bool isSymbol() or tok==T_NUMBER.
|
||||||
|
* If not, an IOError is thrown.
|
||||||
|
* @return DSN_T - the actual token read in.
|
||||||
|
* @throw IOError, if the next token does not satisfy the above test
|
||||||
|
*/
|
||||||
|
DSN_T needSYMBOLorNUMBER() throw( IOError );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function readCOMPnPIN
|
* Function readCOMPnPIN
|
||||||
|
@ -3718,28 +3771,35 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
/**
|
/**
|
||||||
* Function makeIMAGE
|
* Function makeIMAGE
|
||||||
* allocates an IMAGE on the heap and creates all the PINs according
|
* allocates an IMAGE on the heap and creates all the PINs according
|
||||||
* to the PADs in the MODULE.
|
* to the D_PADs in the MODULE.
|
||||||
|
* @param aBoard The owner of the MODULE.
|
||||||
|
* @param aModule The MODULE from which to build the IMAGE.
|
||||||
|
* @return IMAGE* - not tested for duplication yet.
|
||||||
*/
|
*/
|
||||||
IMAGE* makeIMAGE( MODULE* aModule );
|
IMAGE* makeIMAGE( BOARD* aBoard, MODULE* aModule );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function makePADSTACKs
|
* Function makePADSTACK
|
||||||
* makes all the PADSTACKs, and marks each D_PAD with the index into the
|
* creates a PADSTACK which matches the given pad. Only pads which do not
|
||||||
* LIBRARY::padstacks list that it matches.
|
* satisfy the function isKeepout() should be passed to this function.
|
||||||
|
* @param aPad The D_PAD which needs to be made into a PADSTACK.
|
||||||
|
* @return PADSTACK* - The created padstack, including its padstack_id.
|
||||||
*/
|
*/
|
||||||
void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads );
|
PADSTACK* makePADSTACK( BOARD* aBoard, D_PAD* aPad );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function makeVia
|
* Function makeVia
|
||||||
* makes a round through hole PADSTACK using the given Kicad diameter in deci-mils.
|
* makes a round through hole PADSTACK using the given Kicad diameter in deci-mils.
|
||||||
* @param aCopperDiameter The diameter of the copper pad.
|
* @param aCopperDiameter The diameter of the copper pad.
|
||||||
* @param aDrillDiameter The drill diameter, used on re-import of the session file.
|
* @param aDrillDiameter The drill diameter, used on re-import of the session file.
|
||||||
|
* @param aTopLayer The DSN::PCB top most layer index.
|
||||||
|
* @param aBotLayer The DSN::PCB bottom most layer index.
|
||||||
* @return PADSTACK* - The padstack, which is on the heap only, user must save
|
* @return PADSTACK* - The padstack, which is on the heap only, user must save
|
||||||
* or delete it.
|
* or delete it.
|
||||||
*/
|
*/
|
||||||
PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter );
|
PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter,
|
||||||
|
int aTopLayer, int aBotLayer );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function makeVia
|
* Function makeVia
|
||||||
|
@ -3751,6 +3811,19 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
|
||||||
PADSTACK* makeVia( const SEGVIA* aVia );
|
PADSTACK* makeVia( const SEGVIA* aVia );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function deleteNETs
|
||||||
|
* deletes all the NETs that may be in here.
|
||||||
|
*/
|
||||||
|
void deleteNETs()
|
||||||
|
{
|
||||||
|
for( unsigned n=0; n<nets.size(); ++n )
|
||||||
|
delete nets[n];
|
||||||
|
|
||||||
|
nets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----<FromSESSION>-----------------------------------------------------
|
//-----<FromSESSION>-----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3786,6 +3859,8 @@ public:
|
||||||
delete pcb;
|
delete pcb;
|
||||||
delete session;
|
delete session;
|
||||||
|
|
||||||
|
deleteNETs();
|
||||||
|
|
||||||
if( fp )
|
if( fp )
|
||||||
fclose( fp );
|
fclose( fp );
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@
|
||||||
|
|
||||||
#include "trigo.h" // RotatePoint()
|
#include "trigo.h" // RotatePoint()
|
||||||
#include <set> // std::set
|
#include <set> // std::set
|
||||||
|
#include <map> // std::map
|
||||||
|
|
||||||
|
#include <boost/utility.hpp> // boost::addressof()
|
||||||
|
|
||||||
using namespace DSN;
|
using namespace DSN;
|
||||||
|
|
||||||
|
@ -286,15 +288,15 @@ static bool isKeepout( D_PAD* aPad )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
/*
|
||||||
static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr )
|
static int Pad_list_Sort_by_Shapes( const void* refptr, const void* objptr )
|
||||||
/**************************************************************************/
|
|
||||||
{
|
{
|
||||||
const D_PAD* padref = *(D_PAD**)refptr;
|
const D_PAD* padref = *(D_PAD**)refptr;
|
||||||
const D_PAD* padcmp = *(D_PAD**)objptr;
|
const D_PAD* padcmp = *(D_PAD**)objptr;
|
||||||
|
|
||||||
return D_PAD::Compare( padref, padcmp );
|
return D_PAD::Compare( padref, padcmp );
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -312,11 +314,221 @@ static PATH* makePath( const POINT& aStart, const POINT& aEnd, const std::string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
|
/**
|
||||||
|
* Struct wxString_less_than_
|
||||||
|
* is used the std:set<> and std::map<> instantiations below.
|
||||||
|
* See STRINGSET typedef and PINMAP typedef below.
|
||||||
|
*/
|
||||||
|
struct wxString_less_than
|
||||||
{
|
{
|
||||||
PADSTACKS& padstacks = pcb->library->padstacks;
|
// a "less than" test on two wxStrings, by pointer.
|
||||||
|
bool operator()( const wxString& s1, const wxString& s2) const
|
||||||
|
{
|
||||||
|
return s1.Cmp( s2 ) < 0; // case specific wxString compare
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function makePADSTACK
|
||||||
|
* creates a PADSTACK which matches the given pad. Only pads which do not
|
||||||
|
* satisfy the function isKeepout() should be passed to this function.
|
||||||
|
* @param aPad The D_PAD which needs to be made into a PADSTACK.
|
||||||
|
* @return PADSTACK* - The created padstack, including its padstack_id.
|
||||||
|
*/
|
||||||
|
PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
|
||||||
|
{
|
||||||
|
char name[80]; // padstack name builder
|
||||||
|
std::string uniqifier;
|
||||||
|
|
||||||
|
bool doLayer[2] = { // top and bottom layers only
|
||||||
|
aPad->IsOnLayer( LAYER_CMP_N ),
|
||||||
|
aPad->IsOnLayer( COPPER_LAYER_N )
|
||||||
|
};
|
||||||
|
|
||||||
|
// caller must do this screen before calling here.
|
||||||
|
wxASSERT( !isKeepout( aPad ) );
|
||||||
|
|
||||||
|
wxASSERT( doLayer[0] || doLayer[1] );
|
||||||
|
|
||||||
|
PADSTACK* padstack = new PADSTACK();
|
||||||
|
|
||||||
|
int reportedLayers = 0; // how many in reported padstack
|
||||||
|
const char* layerName[NB_COPPER_LAYERS];
|
||||||
|
|
||||||
|
if( aPad->m_Attribut==PAD_SMD || aPad->m_Attribut==PAD_CONN )
|
||||||
|
{
|
||||||
|
// PAD_SMD and PAD_CONN are reported on each layer for which
|
||||||
|
// they are present.
|
||||||
|
uniqifier = '[';
|
||||||
|
|
||||||
|
if( doLayer[0] )
|
||||||
|
{
|
||||||
|
layerName[reportedLayers++] = layerIds[0].c_str();
|
||||||
|
uniqifier += 'T'; // T for top, could have used a layer index here alternatively
|
||||||
|
}
|
||||||
|
if( doLayer[1] )
|
||||||
|
{
|
||||||
|
int pcbLayerNdx = kicadLayer2pcb[COPPER_LAYER_N];
|
||||||
|
layerName[reportedLayers++] = layerIds[ pcbLayerNdx ].c_str();
|
||||||
|
uniqifier += 'B'; // B for bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqifier += ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
else // through hole pad
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* Through hole pads are reported on the <reserved_layer_name>
|
||||||
|
"signal". Reporting through hole pads on the special
|
||||||
|
"signal" layer may have problems when power layers are in the layer
|
||||||
|
stack. See bottom of page 74 of the SECCTRA Design Language
|
||||||
|
Reference, May 2000. We could do better if there was actually a
|
||||||
|
"layer type" field within Kicad which would hold one of: T_signal,
|
||||||
|
T_power, T_mixed, T_jumper.
|
||||||
|
*/
|
||||||
|
|
||||||
|
reportedLayers = 1;
|
||||||
|
layerName[0] = signal;
|
||||||
|
uniqifier = "[A]"; // A for all
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Through hole pads are reported on *all* copper layers.
|
||||||
|
int copperLayers = aBoard->GetCopperLayerCount();
|
||||||
|
|
||||||
|
for( int layer=0; layer<copperLayers; ++layer )
|
||||||
|
{
|
||||||
|
layerName[reportedLayers++] = layerIds[layer].c_str();
|
||||||
|
}
|
||||||
|
uniqifier = "[A]"; // A for all
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( aPad->m_PadShape )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case PAD_CIRCLE:
|
||||||
|
{
|
||||||
|
double diameter = scale(aPad->m_Size.x);
|
||||||
|
|
||||||
|
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
||||||
|
{
|
||||||
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
|
padstack->Append( shape );
|
||||||
|
|
||||||
|
CIRCLE* circle = new CIRCLE( shape );
|
||||||
|
shape->SetShape( circle );
|
||||||
|
|
||||||
|
circle->SetLayerId( layerName[ndx] );
|
||||||
|
circle->SetDiameter( diameter );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( name, sizeof(name), "Round%sPad_%.6g_mil",
|
||||||
|
uniqifier.c_str(), scale(aPad->m_Size.x) );
|
||||||
|
name[ sizeof(name)-1 ] = 0;
|
||||||
|
padstack->SetPadstackId( name );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAD_RECT:
|
||||||
|
{
|
||||||
|
double dx = scale( aPad->m_Size.x ) / 2.0;
|
||||||
|
double dy = scale( aPad->m_Size.y ) / 2.0;
|
||||||
|
|
||||||
|
POINT lowerLeft( -dx, -dy );
|
||||||
|
POINT upperRight( dx, dy );
|
||||||
|
|
||||||
|
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
||||||
|
{
|
||||||
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
|
padstack->Append( shape );
|
||||||
|
|
||||||
|
RECTANGLE* rect = new RECTANGLE( shape );
|
||||||
|
shape->SetShape( rect );
|
||||||
|
|
||||||
|
rect->SetLayerId( layerName[ndx] );
|
||||||
|
rect->SetCorners( lowerLeft, upperRight );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( name, sizeof(name), "Rect%sPad_%.6gx%.6g_mil",
|
||||||
|
uniqifier.c_str(), scale(aPad->m_Size.x), scale(aPad->m_Size.y) );
|
||||||
|
name[ sizeof(name)-1 ] = 0;
|
||||||
|
|
||||||
|
padstack->SetPadstackId( name );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAD_OVAL:
|
||||||
|
{
|
||||||
|
double dx = scale( aPad->m_Size.x ) / 2.0;
|
||||||
|
double dy = scale( aPad->m_Size.y ) / 2.0;
|
||||||
|
double dr = dx - dy;
|
||||||
|
|
||||||
|
if( dr >= 0 ) // oval is horizontal
|
||||||
|
{
|
||||||
|
double radius = dy;
|
||||||
|
|
||||||
|
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
||||||
|
{
|
||||||
|
SHAPE* shape;
|
||||||
|
PATH* path;
|
||||||
|
// see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408
|
||||||
|
shape = new SHAPE( padstack );
|
||||||
|
padstack->Append( shape );
|
||||||
|
path = makePath( POINT(-dr, 0.0), POINT(dr, 0.0), layerName[ndx] );
|
||||||
|
shape->SetShape( path );
|
||||||
|
path->aperture_width = 2.0 * radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // oval is vertical
|
||||||
|
{
|
||||||
|
double radius = dx;
|
||||||
|
|
||||||
|
dr = -dr;
|
||||||
|
|
||||||
|
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
||||||
|
{
|
||||||
|
SHAPE* shape;
|
||||||
|
PATH* path;
|
||||||
|
// see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408
|
||||||
|
shape = new SHAPE( padstack );
|
||||||
|
padstack->Append( shape );
|
||||||
|
path = makePath( POINT(0.0, -dr), POINT(0.0, dr), layerName[ndx] );
|
||||||
|
shape->SetShape( path );
|
||||||
|
path->aperture_width = 2.0 * radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( name, sizeof(name), "Oval%sPad_%.6gx%.6g_mil",
|
||||||
|
uniqifier.c_str(), scale(aPad->m_Size.x), scale(aPad->m_Size.y) );
|
||||||
|
name[ sizeof(name)-1 ] = 0;
|
||||||
|
|
||||||
|
padstack->SetPadstackId( name );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
case PAD_TRAPEZOID:
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return padstack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// data type used to ensure unique-ness of pin names
|
||||||
|
typedef std::map<wxString, int, wxString_less_than> PINMAP;
|
||||||
|
typedef std::pair<const wxString, int> PINMAP_PAIR;
|
||||||
|
|
||||||
|
|
||||||
|
IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
|
||||||
|
{
|
||||||
|
PINMAP pinmap;
|
||||||
TYPE_COLLECTOR pads;
|
TYPE_COLLECTOR pads;
|
||||||
|
wxString padName;
|
||||||
|
|
||||||
|
|
||||||
// get all the MODULE's pads.
|
// get all the MODULE's pads.
|
||||||
pads.Collect( aModule, scanPADs );
|
pads.Collect( aModule, scanPADs );
|
||||||
|
@ -333,25 +545,64 @@ IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
|
||||||
// see if this pad is a through hole with no copper on its perimeter
|
// see if this pad is a through hole with no copper on its perimeter
|
||||||
if( isKeepout( pad ) )
|
if( isKeepout( pad ) )
|
||||||
{
|
{
|
||||||
KEEPOUT* keepout = new KEEPOUT(image, T_keepout);
|
double diameter = scale( pad->m_Drill.x );
|
||||||
image->keepouts.push_back( keepout );
|
POINT vertex = mapPt( pad->m_Pos0 );
|
||||||
|
|
||||||
CIRCLE* circle = new CIRCLE(keepout);
|
int layerCount = aBoard->GetCopperLayerCount();
|
||||||
keepout->SetShape( circle );
|
for( int layer=0; layer<layerCount; ++layer )
|
||||||
|
{
|
||||||
|
KEEPOUT* keepout = new KEEPOUT(image, T_keepout);
|
||||||
|
image->keepouts.push_back( keepout );
|
||||||
|
|
||||||
circle->SetDiameter( scale(pad->m_Drill.x) );
|
CIRCLE* circle = new CIRCLE( keepout );
|
||||||
circle->SetVertex( mapPt( pad->m_Pos0 ) );
|
keepout->SetShape( circle );
|
||||||
circle->layer_id = "signal";
|
|
||||||
|
circle->SetDiameter( diameter );
|
||||||
|
circle->SetVertex( vertex );
|
||||||
|
circle->SetLayerId( layerIds[layer].c_str() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PADSTACK* padstack = &padstacks[pad->m_logical_connexion];
|
PADSTACK* padstack = makePADSTACK( aBoard, pad );
|
||||||
|
|
||||||
|
PADSTACKSET::iterator iter = padstackset.find( *padstack );
|
||||||
|
if( iter != padstackset.end() )
|
||||||
|
{
|
||||||
|
// padstack is a duplicate, delete it and use the original
|
||||||
|
delete padstack;
|
||||||
|
padstack = (PADSTACK*) *iter.base(); // folk lore, becareful here
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
padstackset.insert( padstack );
|
||||||
|
}
|
||||||
|
|
||||||
PIN* pin = new PIN(image);
|
PIN* pin = new PIN(image);
|
||||||
|
|
||||||
|
padName = pad->ReturnStringPadName();
|
||||||
|
pin->pin_id = CONV_TO_UTF8( padName );
|
||||||
|
|
||||||
|
if( padName!=wxEmptyString && pinmap.find( padName )==pinmap.end() )
|
||||||
|
{
|
||||||
|
pinmap[ padName ] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
int duplicates = ++pinmap[ padName ];
|
||||||
|
|
||||||
|
sprintf( buf, "@%d", duplicates );
|
||||||
|
|
||||||
|
pin->pin_id += buf; // append "@1" or "@2", etc. to pin name
|
||||||
|
}
|
||||||
|
|
||||||
|
pin->kiNetCode = pad->GetNet();
|
||||||
|
|
||||||
image->pins.push_back( pin );
|
image->pins.push_back( pin );
|
||||||
|
|
||||||
pin->padstack_id = padstack->padstack_id;
|
pin->padstack_id = padstack->padstack_id;
|
||||||
pin->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() );
|
|
||||||
|
|
||||||
wxPoint pos( pad->m_Pos0 );
|
wxPoint pos( pad->m_Pos0 );
|
||||||
wxPoint offset( pad->m_Offset.x, pad->m_Offset.y );
|
wxPoint offset( pad->m_Offset.x, pad->m_Offset.y );
|
||||||
|
@ -378,93 +629,31 @@ IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
|
PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
|
||||||
{
|
int aTopLayer, int aBotLayer )
|
||||||
CIRCLE* circle;
|
|
||||||
SHAPE* shape;
|
|
||||||
double dsnDiameter;
|
|
||||||
char name[48];
|
|
||||||
|
|
||||||
PADSTACK* padstack = new PADSTACK( pcb->library );
|
|
||||||
|
|
||||||
switch( aVia->Shape() )
|
|
||||||
{
|
|
||||||
case VIA_THROUGH:
|
|
||||||
shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
|
|
||||||
circle = new CIRCLE( shape );
|
|
||||||
shape->SetShape( circle );
|
|
||||||
|
|
||||||
dsnDiameter = scale( aVia->m_Width );
|
|
||||||
circle->SetDiameter( dsnDiameter );
|
|
||||||
|
|
||||||
circle->SetLayerId( "signal" );
|
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Via[A]%.6g:%.6g_mil", dsnDiameter,
|
|
||||||
// encode the drill value into the name for later import
|
|
||||||
scale( aVia->GetDrillValue() ) );
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
|
||||||
padstack->SetPadstackId( name );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIA_BLIND_BURIED:
|
|
||||||
case VIA_MICROVIA:
|
|
||||||
int topLayer;
|
|
||||||
int botLayer;
|
|
||||||
aVia->ReturnLayerPair( &topLayer, &botLayer );
|
|
||||||
topLayer = kicadLayer2pcb[topLayer];
|
|
||||||
botLayer = kicadLayer2pcb[botLayer];
|
|
||||||
if( topLayer > botLayer )
|
|
||||||
EXCHG( topLayer, botLayer );
|
|
||||||
|
|
||||||
dsnDiameter = scale( aVia->m_Width );
|
|
||||||
|
|
||||||
for( int layer=topLayer; layer<=botLayer; ++layer )
|
|
||||||
{
|
|
||||||
shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
|
|
||||||
circle = new CIRCLE( shape );
|
|
||||||
shape->SetShape( circle );
|
|
||||||
|
|
||||||
circle->SetDiameter( dsnDiameter );
|
|
||||||
circle->SetLayerId( layerIds[layer].c_str() );
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Via[%d-%d]_%.6g:%.6g_mil",
|
|
||||||
topLayer, botLayer, dsnDiameter,
|
|
||||||
// encode the drill value into the name for later import
|
|
||||||
scale( aVia->GetDrillValue() )
|
|
||||||
);
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
|
||||||
padstack->SetPadstackId( name );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return padstack;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter )
|
|
||||||
{
|
{
|
||||||
char name[48];
|
char name[48];
|
||||||
PADSTACK* padstack = new PADSTACK( pcb->library );
|
PADSTACK* padstack = new PADSTACK();
|
||||||
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
|
|
||||||
CIRCLE* circle = new CIRCLE( shape );
|
|
||||||
shape->SetShape( circle );
|
|
||||||
|
|
||||||
double dsnDiameter = scale(aCopperDiameter);
|
double dsnDiameter = scale(aCopperDiameter);
|
||||||
circle->SetDiameter( dsnDiameter );
|
|
||||||
|
|
||||||
circle->SetLayerId( "signal" );
|
for( int layer=aTopLayer; layer<=aBotLayer; ++layer )
|
||||||
|
{
|
||||||
|
SHAPE* shape = new SHAPE( padstack );
|
||||||
|
padstack->Append( shape );
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Via[A]%.6g:%.6g_mil", dsnDiameter,
|
CIRCLE* circle = new CIRCLE( shape );
|
||||||
// encode the drill value into the name for later import
|
shape->SetShape( circle );
|
||||||
scale( aDrillDiameter ) );
|
|
||||||
|
circle->SetDiameter( dsnDiameter );
|
||||||
|
circle->SetLayerId( layerIds[layer].c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf( name, sizeof(name), "Via[%d-%d]_%.6g:%.6g_mil",
|
||||||
|
aTopLayer, aBotLayer, dsnDiameter,
|
||||||
|
// encode the drill value into the name for later import
|
||||||
|
scale( aDrillDiameter )
|
||||||
|
);
|
||||||
name[ sizeof(name)-1 ] = 0;
|
name[ sizeof(name)-1 ] = 0;
|
||||||
padstack->SetPadstackId( name );
|
padstack->SetPadstackId( name );
|
||||||
|
|
||||||
|
@ -472,262 +661,32 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
|
||||||
* Struct ltWX
|
|
||||||
* is used secretly by the std:set<> class below. See STRINGSET typedef.
|
|
||||||
*/
|
|
||||||
struct ltWX
|
|
||||||
{
|
{
|
||||||
// a "less than" test on two wxStrings, by pointer.
|
int topLayer;
|
||||||
bool operator()( const wxString* s1, const wxString* s2) const
|
int botLayer;
|
||||||
{
|
|
||||||
return s1->Cmp( *s2 ) < 0; // case specific wxString compare
|
aVia->ReturnLayerPair( &topLayer, &botLayer );
|
||||||
}
|
|
||||||
};
|
topLayer = kicadLayer2pcb[topLayer];
|
||||||
|
botLayer = kicadLayer2pcb[botLayer];
|
||||||
|
|
||||||
|
if( topLayer > botLayer )
|
||||||
|
EXCHG( topLayer, botLayer );
|
||||||
|
|
||||||
|
return makeVia( aVia->m_Width, aVia->GetDrillValue(), topLayer, botLayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
|
void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
|
||||||
{
|
{
|
||||||
char name[80]; // padstack name builder
|
|
||||||
std::string uniqifier;
|
|
||||||
|
|
||||||
if( aPads.GetCount() )
|
|
||||||
{
|
|
||||||
qsort( (void*) aPads.BasePtr(), aPads.GetCount(), sizeof(D_PAD*), Pad_list_Sort_by_Shapes );
|
|
||||||
}
|
|
||||||
|
|
||||||
D_PAD* old_pad = NULL;
|
|
||||||
|
|
||||||
for( int i=0; i<aPads.GetCount(); ++i )
|
|
||||||
{
|
|
||||||
D_PAD* pad = (D_PAD*) aPads[i];
|
|
||||||
|
|
||||||
bool doLayer[2] = { // top and bottom layers only
|
|
||||||
pad->IsOnLayer( LAYER_CMP_N ),
|
|
||||||
pad->IsOnLayer( COPPER_LAYER_N )
|
|
||||||
};
|
|
||||||
|
|
||||||
if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
|
|
||||||
{
|
|
||||||
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
|
|
||||||
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
|
|
||||||
|
|
||||||
// this is the same as the last pad, so do not add it to the padstack list.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if pad has no copper presence, then it will be made into
|
|
||||||
// an "image->keepout" later. No copper pad here, it is probably a hole.
|
|
||||||
if( (!doLayer[0] && !doLayer[1]) || isKeepout( pad ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
old_pad = pad;
|
|
||||||
|
|
||||||
PADSTACK* padstack = new PADSTACK( pcb->library );
|
|
||||||
pcb->library->AddPadstack( padstack );
|
|
||||||
|
|
||||||
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
|
|
||||||
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
|
|
||||||
|
|
||||||
/* Through hole pads are reported on the <reserved_layer_name>
|
|
||||||
"signal". Reporting through hole pads on the special
|
|
||||||
"signal" layer may have problems when power layers are in the layer
|
|
||||||
stack. See bottom of page 74 of the SECCTRA Design Language
|
|
||||||
Reference, May 2000. We could do better if there was actually a
|
|
||||||
"layer type" field within Kicad which would hold one of: T_signal,
|
|
||||||
T_power, T_mixed, T_jumper.
|
|
||||||
|
|
||||||
PAD_SMD and PAD_CONN are reported on each layer for which
|
|
||||||
they are present.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int reportedLayers; // how many in reported padstack
|
|
||||||
const char* layerName[NB_COPPER_LAYERS];
|
|
||||||
|
|
||||||
static const char signal[] = "signal";
|
|
||||||
|
|
||||||
if( pad->m_Attribut==PAD_SMD || pad->m_Attribut==PAD_CONN )
|
|
||||||
{
|
|
||||||
reportedLayers = 0;
|
|
||||||
|
|
||||||
uniqifier = '[';
|
|
||||||
|
|
||||||
if( doLayer[0] )
|
|
||||||
{
|
|
||||||
layerName[reportedLayers++] = layerIds[0].c_str();
|
|
||||||
uniqifier += 'T'; // T for top, could have used a layer index here alternatively
|
|
||||||
}
|
|
||||||
if( doLayer[1] )
|
|
||||||
{
|
|
||||||
int pcbLayerNdx = kicadLayer2pcb[COPPER_LAYER_N];
|
|
||||||
layerName[reportedLayers++] = layerIds[ pcbLayerNdx ].c_str();
|
|
||||||
uniqifier += 'B'; // B for bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
uniqifier += ']';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reportedLayers = 1;
|
|
||||||
layerName[0] = signal;
|
|
||||||
uniqifier = "[A]"; // A for all
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( pad->m_PadShape )
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case PAD_CIRCLE:
|
|
||||||
{
|
|
||||||
double diameter = scale(pad->m_Size.x);
|
|
||||||
|
|
||||||
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
|
||||||
{
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
|
|
||||||
CIRCLE* circle = new CIRCLE( shape );
|
|
||||||
shape->SetShape( circle );
|
|
||||||
|
|
||||||
circle->SetLayerId( layerName[ndx] );
|
|
||||||
circle->SetDiameter( diameter );
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Round%sPad_%.6g_mil",
|
|
||||||
uniqifier.c_str(), scale(pad->m_Size.x) );
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
|
||||||
|
|
||||||
// @todo verify that all pad names are unique, there is a chance that
|
|
||||||
// D_PAD::Compare() could say two pads are different, yet the get the same
|
|
||||||
// name here. If so, blend in the padNdx into the name.
|
|
||||||
|
|
||||||
padstack->SetPadstackId( name );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAD_RECT:
|
|
||||||
{
|
|
||||||
double dx = scale( pad->m_Size.x ) / 2.0;
|
|
||||||
double dy = scale( pad->m_Size.y ) / 2.0;
|
|
||||||
|
|
||||||
POINT lowerLeft( -dx, -dy );
|
|
||||||
POINT upperRight( dx, dy );
|
|
||||||
|
|
||||||
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
|
||||||
{
|
|
||||||
SHAPE* shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
|
|
||||||
RECTANGLE* rect = new RECTANGLE( shape );
|
|
||||||
shape->SetShape( rect );
|
|
||||||
|
|
||||||
rect->SetLayerId( layerName[ndx] );
|
|
||||||
rect->SetCorners( lowerLeft, upperRight );
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Rect%sPad_%.6gx%.6g_mil",
|
|
||||||
uniqifier.c_str(), scale(pad->m_Size.x), scale(pad->m_Size.y) );
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
|
||||||
|
|
||||||
// @todo verify that all pad names are unique, there is a chance that
|
|
||||||
// D_PAD::Compare() could say two pads are different, yet they get the same
|
|
||||||
// name here. If so, blend in the padNdx into the name.
|
|
||||||
|
|
||||||
padstack->SetPadstackId( name );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PAD_OVAL:
|
|
||||||
{
|
|
||||||
double dx = scale( pad->m_Size.x ) / 2.0;
|
|
||||||
double dy = scale( pad->m_Size.y ) / 2.0;
|
|
||||||
double dr = dx - dy;
|
|
||||||
|
|
||||||
if( dr >= 0 ) // oval is horizontal
|
|
||||||
{
|
|
||||||
double radius = dy;
|
|
||||||
|
|
||||||
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
|
||||||
{
|
|
||||||
SHAPE* shape;
|
|
||||||
PATH* path;
|
|
||||||
// see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408
|
|
||||||
shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
path = makePath( POINT(-dr, 0.0), POINT(dr, 0.0), layerName[ndx] );
|
|
||||||
shape->SetShape( path );
|
|
||||||
path->aperture_width = 2.0 * radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // oval is vertical
|
|
||||||
{
|
|
||||||
double radius = dx;
|
|
||||||
|
|
||||||
dr = -dr;
|
|
||||||
|
|
||||||
for( int ndx=0; ndx<reportedLayers; ++ndx )
|
|
||||||
{
|
|
||||||
SHAPE* shape;
|
|
||||||
PATH* path;
|
|
||||||
// see http://www.freerouting.net/usren/viewtopic.php?f=3&t=317#p408
|
|
||||||
shape = new SHAPE( padstack );
|
|
||||||
padstack->Append( shape );
|
|
||||||
path = makePath( POINT(0.0, -dr), POINT(0.0, dr), layerName[ndx] );
|
|
||||||
shape->SetShape( path );
|
|
||||||
path->aperture_width = 2.0 * radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf( name, sizeof(name), "Oval%sPad_%.6gx%.6g_mil",
|
|
||||||
uniqifier.c_str(), scale(pad->m_Size.x), scale(pad->m_Size.y) );
|
|
||||||
name[ sizeof(name)-1 ] = 0;
|
|
||||||
|
|
||||||
// @todo verify that all pad names are unique, there is a chance that
|
|
||||||
// D_PAD::Compare() could say two pads are different, yet they get the same
|
|
||||||
// name here. If so, blend in the padNdx into the name.
|
|
||||||
|
|
||||||
padstack->SetPadstackId( name );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
case PAD_TRAPEZOID:
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unique pads are now in the padstack list.
|
|
||||||
// next we add the via's which may be used.
|
|
||||||
|
|
||||||
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
|
|
||||||
if( defaultViaSize )
|
|
||||||
{
|
|
||||||
PADSTACK* padstack = makeVia( defaultViaSize, g_DesignSettings.m_ViaDrill );
|
|
||||||
pcb->library->AddPadstack( padstack );
|
|
||||||
|
|
||||||
// remember this index, it is the default via and also the start of the
|
|
||||||
// vias within the padstack list. Before this index are the pads.
|
|
||||||
// At this index and later are the vias.
|
|
||||||
pcb->library->SetViaStartIndex( pcb->library->padstacks.size()-1 );
|
|
||||||
|
|
||||||
// padstack->SetPadstackId( "Via_Default" ); I like the padstack_id with the size in it.
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int i=0; i<HISTORY_NUMBER; ++i )
|
|
||||||
{
|
|
||||||
int viaSize = aBoard->m_BoardSettings->m_ViaSizeHistory[i];
|
|
||||||
if( !viaSize )
|
|
||||||
break;
|
|
||||||
|
|
||||||
if( viaSize == defaultViaSize )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
PADSTACK* padstack = makeVia( viaSize, g_DesignSettings.m_ViaDrill );
|
|
||||||
pcb->library->AddPadstack( padstack );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::set<wxString, wxString_less_than> STRINGSET;
|
||||||
|
typedef std::pair<STRINGSET::iterator, bool> STRINGSET_PAIR;
|
||||||
|
|
||||||
|
|
||||||
void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
|
@ -740,14 +699,15 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
|
|
||||||
// Not all boards are exportable. Check that all reference Ids are unique.
|
// Not all boards are exportable. Check that all reference Ids are unique.
|
||||||
// Unless they are unique, we cannot import the session file which comes
|
// Unless they are unique, we cannot import the session file which comes
|
||||||
// back to us later from the router.
|
// back to us later from the router. Also check that all pad names within
|
||||||
|
// a part are unique, otherwise Electra and Freerouter will not draw the
|
||||||
|
// pads properly.
|
||||||
{
|
{
|
||||||
|
TYPE_COLLECTOR padItems;
|
||||||
|
|
||||||
items.Collect( aBoard, scanMODULEs );
|
items.Collect( aBoard, scanMODULEs );
|
||||||
|
|
||||||
typedef std::set<const wxString*, ltWX> STRINGSET;
|
STRINGSET refs; // holds module reference designators
|
||||||
typedef std::pair<STRINGSET::iterator, bool> PAIR;
|
|
||||||
|
|
||||||
STRINGSET references; // holds unique component references
|
|
||||||
|
|
||||||
for( int i=0; i<items.GetCount(); ++i )
|
for( int i=0; i<items.GetCount(); ++i )
|
||||||
{
|
{
|
||||||
|
@ -760,8 +720,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we cannot insert OK, that means the reference has been seen before.
|
// if we cannot insert OK, that means the reference has been seen before.
|
||||||
PAIR pair = references.insert( &module->GetReference() );
|
STRINGSET_PAIR refpair = refs.insert( module->GetReference() );
|
||||||
if( !pair.second ) // insert failed
|
if( !refpair.second ) // insert failed
|
||||||
{
|
{
|
||||||
ThrowIOError( _("Multiple components have identical reference IDs of \"%s\"."),
|
ThrowIOError( _("Multiple components have identical reference IDs of \"%s\"."),
|
||||||
module->GetReference().GetData() );
|
module->GetReference().GetData() );
|
||||||
|
@ -785,11 +745,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since none of these statements cause any immediate output, the order
|
|
||||||
// of them is somewhat flexible. The outputting to disk is done at the
|
|
||||||
// end. We start by gathering all the layer information from the board.
|
|
||||||
|
|
||||||
|
|
||||||
//-----<layer_descriptor>-----------------------------------------------
|
//-----<layer_descriptor>-----------------------------------------------
|
||||||
{
|
{
|
||||||
// specctra wants top physical layer first, then going down to the
|
// specctra wants top physical layer first, then going down to the
|
||||||
|
@ -818,10 +773,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// for now, report on only the top and bottom layers with respect to the copper
|
|
||||||
// within a pad's padstack. this is usually correct, but not rigorous.
|
|
||||||
|
|
||||||
// a space in a quoted token is NOT a terminator, true establishes this.
|
// a space in a quoted token is NOT a terminator, true establishes this.
|
||||||
pcb->parser->space_in_quoted_tokens = true;
|
pcb->parser->space_in_quoted_tokens = true;
|
||||||
|
|
||||||
|
@ -1004,49 +955,78 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
}
|
}
|
||||||
|
|
||||||
// keepouts could go here, there are none in Kicad at this time.
|
// keepouts could go here, there are none in Kicad at this time.
|
||||||
// although COPPER_PLANEs probably will need them for the thru holes, etc.
|
|
||||||
// but in that case they are WINDOWs within the COPPER_PLANEs.
|
|
||||||
|
|
||||||
|
//-----<build the images, components, and netlist>-----------------------
|
||||||
//-----<build the initial padstack list>--------------------------------
|
|
||||||
{
|
{
|
||||||
TYPE_COLLECTOR pads;
|
// find the highest numbered netCode within the board.
|
||||||
|
int highestNetCode = -1;
|
||||||
|
for( EQUIPOT* equipot = aBoard->m_Equipots; equipot; equipot = equipot->Next() )
|
||||||
|
highestNetCode = MAX( highestNetCode, equipot->GetNet() );
|
||||||
|
|
||||||
// get all the D_PADs into 'pads'.
|
deleteNETs();
|
||||||
pads.Collect( aBoard, scanPADs );
|
|
||||||
|
|
||||||
makePADSTACKs( aBoard, pads );
|
// expand the net vector to highestNetCode+1, setting empty to NULL
|
||||||
|
nets.resize( highestNetCode+1, NULL );
|
||||||
|
|
||||||
#if 0 && defined(DEBUG)
|
// skip netcode = 0
|
||||||
for( int p=0; p<pads.GetCount(); ++p )
|
for( unsigned i=1; i<nets.size(); ++i )
|
||||||
pads[p]->Show( 0, std::cout );
|
nets[i] = new NET( pcb->network );
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for( EQUIPOT* equipot = aBoard->m_Equipots; equipot; equipot = equipot->Next() )
|
||||||
|
{
|
||||||
|
int netcode = equipot->GetNet();
|
||||||
|
if( netcode > 0 )
|
||||||
|
nets[ netcode ]->net_id = CONV_TO_UTF8( equipot->m_Netname );
|
||||||
|
}
|
||||||
|
|
||||||
//-----<build the images and components>---------------------------------
|
|
||||||
{
|
|
||||||
items.Collect( aBoard, scanMODULEs );
|
items.Collect( aBoard, scanMODULEs );
|
||||||
|
|
||||||
|
padstackset.clear();
|
||||||
|
|
||||||
for( int m=0; m<items.GetCount(); ++m )
|
for( int m=0; m<items.GetCount(); ++m )
|
||||||
{
|
{
|
||||||
MODULE* module = (MODULE*) items[m];
|
MODULE* module = (MODULE*) items[m];
|
||||||
|
|
||||||
IMAGE* image = makeIMAGE( module );
|
IMAGE* image = makeIMAGE( aBoard, module );
|
||||||
|
|
||||||
|
// create a net list entry for all the actual pins in the image
|
||||||
|
// for the current module. location of this code is critical
|
||||||
|
// because we fabricated some pin names to ensure unique-ness
|
||||||
|
// of pin names within a module, do not move this code. The
|
||||||
|
// exported netlist will have some fabricated pin names in it.
|
||||||
|
// If you don't like fabricated pin names, then make sure all pads
|
||||||
|
// within your MODULEs are uniquely named!
|
||||||
|
|
||||||
|
PIN_REF empty( pcb->network );
|
||||||
|
for( unsigned p=0; p<image->pins.size(); ++p )
|
||||||
|
{
|
||||||
|
PIN* pin = &image->pins[p];
|
||||||
|
|
||||||
|
int netcode = pin->kiNetCode;
|
||||||
|
if( netcode > 0 )
|
||||||
|
{
|
||||||
|
NET* net = nets[netcode];
|
||||||
|
|
||||||
|
net->pins.push_back( empty );
|
||||||
|
|
||||||
|
PIN_REF& pin_ref = net->pins.back();
|
||||||
|
|
||||||
|
pin_ref.component_id = CONV_TO_UTF8( module->GetReference() );
|
||||||
|
pin_ref.pin_id = pin->pin_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IMAGE* registered = pcb->library->LookupIMAGE( image );
|
IMAGE* registered = pcb->library->LookupIMAGE( image );
|
||||||
if( registered != image )
|
if( registered != image )
|
||||||
{
|
{
|
||||||
// If our new 'image' is not a unique IMAGE, delete it.
|
// If our new 'image' is not a unique IMAGE, delete it.
|
||||||
// In either case, 'registered' is the one we'll work with henceforth.
|
// and use the registered one, known as 'image' after this.
|
||||||
delete image;
|
delete image;
|
||||||
|
image = registered;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo: this only works if the user has not modified the MODULE within the PCB
|
COMPONENT* comp = pcb->placement->LookupCOMPONENT( image->GetImageId() );
|
||||||
// and made it different from what is in the PCBNEW library. Need to test
|
|
||||||
// each image for uniqueness, not just based on name as is done here:
|
|
||||||
|
|
||||||
COMPONENT* comp = pcb->placement->LookupCOMPONENT( registered->GetImageId() );
|
|
||||||
|
|
||||||
PLACE* place = new PLACE( comp );
|
PLACE* place = new PLACE( comp );
|
||||||
comp->places.push_back( place );
|
comp->places.push_back( place );
|
||||||
|
@ -1060,69 +1040,73 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
|
||||||
if( module->flag )
|
if( module->flag )
|
||||||
{
|
{
|
||||||
int angle = 1800 - module->m_Orient;
|
int angle = 1800 - module->m_Orient;
|
||||||
|
|
||||||
NORMALIZE_ANGLE_POS(angle);
|
NORMALIZE_ANGLE_POS(angle);
|
||||||
|
|
||||||
place->SetRotation( angle/10.0 );
|
place->SetRotation( angle/10.0 );
|
||||||
|
|
||||||
place->side = T_back;
|
place->side = T_back;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// copy the SPECCTRA_DB::padstackset to the LIBRARY. Since we are
|
||||||
//-----<create the nets>------------------------------------------------
|
// removing, do not increment the iterator
|
||||||
{
|
for( PADSTACKSET::iterator i=padstackset.begin(); i!=padstackset.end();
|
||||||
NETWORK* network = pcb->network;
|
i=padstackset.begin() )
|
||||||
TYPE_COLLECTOR nets;
|
|
||||||
TYPE_COLLECTOR pads;
|
|
||||||
|
|
||||||
static const KICAD_T scanNETs[] = { PCB_EQUIPOT_STRUCT_TYPE, EOT };
|
|
||||||
|
|
||||||
nets.Collect( aBoard, scanNETs );
|
|
||||||
|
|
||||||
items.Collect( aBoard, scanMODULEs );
|
|
||||||
|
|
||||||
PIN_REF emptypin(0);
|
|
||||||
|
|
||||||
for( int n=0; n<nets.GetCount(); ++n )
|
|
||||||
{
|
{
|
||||||
EQUIPOT* kinet = (EQUIPOT*) nets[n];
|
PADSTACKSET::auto_type ps = padstackset.release( i );
|
||||||
|
PADSTACK* padstack = ps.release();
|
||||||
|
|
||||||
if( kinet->GetNet() == 0 )
|
pcb->library->AddPadstack( padstack );
|
||||||
continue;
|
}
|
||||||
|
|
||||||
NET* net = new NET( network );
|
// copy our SPECCTRA_DB::nets to the pcb->network
|
||||||
network->nets.push_back( net );
|
for( unsigned n=1; n<nets.size(); ++n )
|
||||||
|
{
|
||||||
net->net_id = CONV_TO_UTF8( kinet->m_Netname );
|
NET* net = nets[n];
|
||||||
net->net_number = kinet->GetNet();
|
if( net->pins.size() )
|
||||||
|
|
||||||
for( int m=0; m<items.GetCount(); ++m )
|
|
||||||
{
|
{
|
||||||
MODULE* module = (MODULE*) items[m];
|
// give ownership to pcb->network
|
||||||
|
pcb->network->nets.push_back( net );
|
||||||
pads.Collect( module, scanPADs );
|
nets[n] = 0;
|
||||||
|
|
||||||
for( int p=0; p<pads.GetCount(); ++p )
|
|
||||||
{
|
|
||||||
D_PAD* pad = (D_PAD*) pads[p];
|
|
||||||
|
|
||||||
if( pad->GetNet() == kinet->GetNet() )
|
|
||||||
{
|
|
||||||
// push on an empty one, then fill it via 'pin_ref'
|
|
||||||
net->pins.push_back( emptypin );
|
|
||||||
PIN_REF* pin_ref = &net->pins.back();
|
|
||||||
|
|
||||||
pin_ref->SetParent( net );
|
|
||||||
pin_ref->component_id = CONV_TO_UTF8( module->GetReference() );
|
|
||||||
pin_ref->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----< output the vias >-----------------------------------------------
|
||||||
|
{
|
||||||
|
// ASSUME: unique pads are now in the padstack list! i.e. this code
|
||||||
|
// must follow the initial padstack construction code.
|
||||||
|
// Next we add the via's which may be used.
|
||||||
|
|
||||||
|
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
|
||||||
|
if( defaultViaSize )
|
||||||
|
{
|
||||||
|
PADSTACK* padstack = makeVia( defaultViaSize, g_DesignSettings.m_ViaDrill,
|
||||||
|
0, aBoard->GetCopperLayerCount()-1 );
|
||||||
|
pcb->library->AddPadstack( padstack );
|
||||||
|
|
||||||
|
// remember this index, it is the default via and also the start of the
|
||||||
|
// vias within the padstack list. Before this index are the pads.
|
||||||
|
// At this index and later are the vias.
|
||||||
|
pcb->library->SetViaStartIndex( pcb->library->padstacks.size()-1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i=0; i<HISTORY_NUMBER; ++i )
|
||||||
|
{
|
||||||
|
int viaSize = aBoard->m_BoardSettings->m_ViaSizeHistory[i];
|
||||||
|
if( !viaSize )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( viaSize == defaultViaSize )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PADSTACK* padstack = makeVia( viaSize, g_DesignSettings.m_ViaDrill,
|
||||||
|
0, aBoard->GetCopperLayerCount()-1 );
|
||||||
|
pcb->library->AddPadstack( padstack );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 1 // do existing wires and vias
|
#if 1 // do existing wires and vias
|
||||||
|
|
||||||
//-----<create the wires from tracks>-----------------------------------
|
//-----<create the wires from tracks>-----------------------------------
|
||||||
|
|
Loading…
Reference in New Issue