more amazing free specctra work

This commit is contained in:
dickelbeck 2008-02-14 01:07:52 +00:00
parent 10ded82dbd
commit 709be49518
5 changed files with 685 additions and 553 deletions

View File

@ -5,20 +5,29 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
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
================================================================================
+eeschema
* commiting my changes to allow multiple instances of a given schematic file within a hierarchy:
** 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
a series of timestamps, which is converted to flat component reference via a look-up
table in the schematic files.
** 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.
** all sub-sheets in a given schematic must have different names to generate a meaningful netlist.
* commiting my changes to allow multiple instances of a given schematic file within a hierarchy:
** 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
a series of timestamps, which is converted to flat component reference via a look-up
table in the schematic files.
** 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.
** 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>
================================================================================
+eeschema
@ -26,6 +35,7 @@ email address.
+all
Russian translation update.
2008-Feb-11 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+pcbnew

View File

@ -27,7 +27,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
wxString text, msg;
const BOARD_ITEM* item = this;
EQUIPOT* net;
D_PAD * pad;
D_PAD * pad;
switch( item->Type() )
{
@ -42,17 +42,17 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
break;
case TYPEPAD:
pad = (D_PAD *) this;
pad = (D_PAD *) this;
text << _( "Pad" ) << wxT( " \"" ) << pad->ReturnStringPadName()
<< wxT( "\" (" );
if ( (pad->m_Masque_Layer & ALL_CU_LAYERS) == ALL_CU_LAYERS )
text << _("all copper layers");
else if( (pad->m_Masque_Layer & CUIVRE_LAYER) == CUIVRE_LAYER )
text << _("copper layer");
else if( (pad->m_Masque_Layer & CMP_LAYER) == CMP_LAYER )
text << _("cmp layer");
else text << _("???");
text << _( ") of " ) << ( (MODULE*) GetParent() )->GetReference();
<< wxT( "\" (" );
if ( (pad->m_Masque_Layer & ALL_CU_LAYERS) == ALL_CU_LAYERS )
text << _("all copper layers");
else if( (pad->m_Masque_Layer & CUIVRE_LAYER) == CUIVRE_LAYER )
text << _("copper layer");
else if( (pad->m_Masque_Layer & CMP_LAYER) == CMP_LAYER )
text << _("cmp layer");
else text << _("???");
text << _( ") of " ) << ( (MODULE*) GetParent() )->GetReference();
break;
case TYPEDRAWSEGMENT:
@ -89,7 +89,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
break;
case TYPEEDGEMODULE:
{
{
text << _( "Graphic" ) << wxT( " " );
wxString cp;
@ -129,23 +129,23 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
text << cp;
text << wxT( " (" ) << ReturnPcbLayerName( ((EDGE_MODULE*) item )->m_Layer ).Trim() << wxT( ")" );
text << _( " of " )
text << _( " of " )
<< ( (MODULE*) GetParent() )->GetReference();
break;
}
}
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!
{
wxString txt;
text << _( "Track" ) << wxT( " " ) << ((TRACK*)item)->ShowWidth();
net = aPcb->FindNet( ((TRACK*)item)->GetNet() );
if( net )
{
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
}
text << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim()
text << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim()
<< wxT(" ") << _("Net:") << ((TRACK*)item)->GetNet()
<< wxT(" ") << _("Length:") << valeur_param( (int) ((TRACK*)item)->GetLength(), txt );
}
@ -153,36 +153,36 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
case TYPEZONE_CONTAINER:
text = _( "Zone Outline" );
{
ZONE_CONTAINER* area = (ZONE_CONTAINER*) this;
int ncont = area->m_Poly->GetContour(area->m_CornerSelection);
if ( ncont ) text << wxT(" ") << _("(Cutout)");
}
text << wxT( " " );
{
ZONE_CONTAINER* area = (ZONE_CONTAINER*) this;
int ncont = area->m_Poly->GetContour(area->m_CornerSelection);
if ( ncont ) text << wxT(" ") << _("(Cutout)");
}
text << wxT( " " );
{
wxString TimeStampText;
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
text << TimeStampText;
}
if ( ((ZONE_CONTAINER*) item)->GetNet() >= 0 )
{
net = aPcb->FindNet( ( (ZONE_CONTAINER*) item )->GetNet() );
if( net )
{
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
}
}
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(" <") << _("Not Found") << wxT(">");
}
if ( ((ZONE_CONTAINER*) item)->GetNet() >= 0 )
{
net = aPcb->FindNet( ( (ZONE_CONTAINER*) item )->GetNet() );
if( net )
{
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
}
}
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(" <") << _("Not Found") << wxT(">");
}
text << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim();
break;
break;
case TYPEZONE:
text = _( "Zone" );
text << wxT( " " );
case TYPEZONE:
text = _( "Zone" );
text << wxT( " " );
{
wxString TimeStampText;
TimeStampText.Printf( wxT( "(%8.8X)" ), item->m_TimeStamp );
@ -200,34 +200,35 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
{
SEGVIA* via = (SEGVIA*) item;
text << _( "Via" ) << wxT( " " ) << via->ShowWidth();
int shape = via->Shape();
int shape = via->Shape();
if( shape == VIA_BLIND_BURIED )
text << wxT(" ") << _( "Blind/Buried" );
else if( shape == VIA_MICROVIA )
text << wxT(" ") << _("Micro Via");
// else say nothing about normal (through) vias
net = aPcb->FindNet( via->GetNet() );
if( net )
{
text << wxT( " [" ) << net->m_Netname << wxT( "]" );
}
text << wxChar(' ') << _("Net:") << via->GetNet();
if( shape != VIA_THROUGH )
{
// say which layers, only two for now
int topLayer;
int botLayer;
via->ReturnLayerPair( &topLayer, &botLayer );
text << _( " on " ) << ReturnPcbLayerName( topLayer).Trim() << wxT(" <-> ")
text << _( " on " ) << ReturnPcbLayerName( topLayer).Trim() << wxT(" <-> ")
<< ReturnPcbLayerName( botLayer ).Trim();
}
}
break;
case TYPEMARKER:
text << _( "Marker" ) << wxT( " @(" ) << ((MARKER*)item)->GetPos().x
text << _( "Marker" ) << wxT( " @(" ) << ((MARKER*)item)->GetPos().x
<< wxT(",") << ((MARKER*)item)->GetPos().y << wxT(")");
break;
@ -236,7 +237,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const
break;
case TYPEMIRE:
valeur_param( ((MIREPCB*)item)->m_Size, msg );
valeur_param( ((MIREPCB*)item)->m_Size, msg );
text << _( "Target" ) << _( " on " ) << ReturnPcbLayerName( item->GetLayer() ).Trim()
<< wxT( " " ) << _( "size" ) << wxT( " " ) << msg
;

View File

@ -76,6 +76,7 @@ namespace DSN {
//-----<SPECCTRA_DB>-------------------------------------------------
#if !defined(STANDALONE)
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 ) ) );
}
}
#endif
int SPECCTRA_DB::findLayerName( const std::string& aLayerName ) const
@ -183,13 +185,21 @@ void SPECCTRA_DB::needRIGHT() throw( IOError )
expecting( T_RIGHT );
}
void SPECCTRA_DB::needSYMBOL() throw( IOError )
DSN_T SPECCTRA_DB::needSYMBOL() throw( IOError )
{
DSN_T tok = nextTok();
if( !isSymbol( tok ) )
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 )
{
@ -467,7 +477,9 @@ void SPECCTRA_DB::doPCB( PCB* 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
@ -519,17 +531,19 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
break;
case T_host_version:
needSYMBOL();
needSYMBOLorNUMBER();
growth->host_version = lexer->CurText();
needRIGHT();
break;
case T_constant:
needSYMBOL();
growth->const_id1 = lexer->CurText();
needSYMBOL();
growth->const_id2 = lexer->CurText();
needSYMBOLorNUMBER();
const1 = lexer->CurText();
needSYMBOLorNUMBER();
const2 = lexer->CurText();
needRIGHT();
growth->constants.push_back( const1 );
growth->constants.push_back( const2 );
break;
case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
@ -710,6 +724,8 @@ void SPECCTRA_DB::doSTRUCTURE( STRUCTURE* growth ) throw(IOError)
break;
case T_layer_noise_weight:
if( growth->layer_noise_weight )
unexpected( tok );
growth->layer_noise_weight = new LAYER_NOISE_WEIGHT( growth );
doLAYER_NOISE_WEIGHT( growth->layer_noise_weight );
break;
@ -755,11 +771,15 @@ L_place:
break;
case T_via:
if( growth->via )
unexpected( tok );
growth->via = new VIA( growth );
doVIA( growth->via );
break;
case T_control:
if( growth->control )
unexpected( tok );
growth->control = new CONTROL( growth );
doCONTROL( growth->control );
break;
@ -772,11 +792,15 @@ L_place:
break;
case T_rule:
if( growth->rules )
unexpected( tok );
growth->rules = new RULE( growth, T_rule );
doRULE( growth->rules );
break;
case T_place_rule:
if( growth->place_rules )
unexpected( tok );
growth->place_rules = new RULE( growth, T_place_rule );
doRULE( growth->place_rules );
break;
@ -2219,35 +2243,35 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError )
growth->padstack_id = lexer->CurText();
tok = nextTok();
if( tok == T_LEFT )
while( (tok = nextTok()) != T_RIGHT )
{
tok = nextTok();
if( tok != T_rotate )
expecting( T_rotate );
if( tok == T_LEFT )
{
tok = nextTok();
if( tok != T_rotate )
expecting( T_rotate );
if( nextTok() != T_NUMBER )
expecting( T_NUMBER );
growth->SetRotation( strtod( lexer->CurText(), 0 ) );
needRIGHT();
tok = nextTok();
if( nextTok() != T_NUMBER )
expecting( T_NUMBER );
growth->SetRotation( strtod( lexer->CurText(), 0 ) );
needRIGHT();
}
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:
PADSTACK* padstack;
padstack = new PADSTACK( growth );
growth->padstacks.push_back( padstack );
padstack = new PADSTACK();
growth->AddPadstack( padstack );
doPADSTACK( padstack );
break;
@ -2307,7 +2331,8 @@ void SPECCTRA_DB::doLIBRARY( LIBRARY* 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 <net_id >
@ -2358,14 +2383,38 @@ void SPECCTRA_DB::doNET( NET* growth ) throw( IOError )
case T_pins:
case T_order:
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 );
while( (tok = nextTok()) != T_RIGHT )
{
// 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 );
}
@ -3431,7 +3480,7 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
if( strlen(wrapee)==0 )
return quote_char;
bool isNumber = true;
// bool isNumber = true;
for( ; *wrapee; ++wrapee )
{
@ -3444,12 +3493,12 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
if( strchr( quoteThese, *wrapee ) )
return quote_char;
if( !strchr( "01234567890.-+", *wrapee ) )
isNumber = false;
// if( !strchr( "01234567890.-+", *wrapee ) )
// isNumber = false;
}
if( isNumber )
return quote_char;
// if( isNumber )
// return quote_char;
return ""; // can use an unwrapped string.
}
@ -3670,6 +3719,11 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
return -1;
}
// a reasonably small memory price to pay for improved performance
STRINGFORMATTER ELEM::sf;
//-----<UNIT_RES>---------------------------------------------------------
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 )
{
// printf( "PADSTACK::Compare( %p, %p)\n", lhs, rhs );
if( !lhs->hash.size() )
lhs->hash = lhs->makeHash();
@ -3725,7 +3781,6 @@ int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* rhs )
*/
//-----<PARSER>-----------------------------------------------------------
PARSER::PARSER( ELEM* 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_version \"%s\")\n", host_version.c_str() );
if( const_id1.length()>0 || const_id2.length()>0 )
out->Print( nestLevel, "(constant %c%s%c %c%s%c)\n",
string_quote, const_id1.c_str(), string_quote,
string_quote, const_id2.c_str(), string_quote );
for( STRINGS::iterator i=constants.begin(); i!=constants.end(); )
{
const std::string& s1 = *i++;
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 )
out->Print( nestLevel, "(routes_include%s%s%s)\n",

View File

@ -29,6 +29,10 @@
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
#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 "dsn.h"
@ -303,14 +307,16 @@ protected:
*/
std::string makeHash()
{
STRINGFORMATTER sf;
sf.Clear();
FormatContents( &sf, 0 );
sf.StripUseless();
return sf.GetString();
}
// avoid creating this for every compare, make static.
static STRINGFORMATTER sf;
public:
@ -466,8 +472,8 @@ class PARSER : public ELEM
bool via_rotate_first;
bool generated_by_freeroute;
std::string const_id1;
std::string const_id2;
/// This holds pairs of strings, one pair for each constant definition
STRINGS constants;
std::string host_cad;
std::string host_version;
@ -1924,12 +1930,16 @@ class PIN : public ELEM
std::string pin_id;
POINT vertex;
int kiNetCode; ///< kicad netcode
public:
PIN( ELEM* aParent ) :
ELEM( T_pin, aParent )
{
rotation = 0.0;
isRotated = false;
kiNetCode = 0;
}
void SetRotation( double aRotation )
@ -1960,6 +1970,8 @@ public:
vertex.x, vertex.y );
}
};
typedef boost::ptr_vector<PIN> PINS;
class LIBRARY;
class IMAGE : public ELEM_HOLDER
@ -1978,7 +1990,6 @@ class IMAGE : public ELEM_HOLDER
the kids list.
*/
typedef boost::ptr_vector<PIN> PINS;
PINS pins;
RULE* rules;
@ -2085,7 +2096,7 @@ typedef boost::ptr_vector<IMAGE> IMAGES;
* Class PADSTACK
* 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;
@ -2105,8 +2116,14 @@ class PADSTACK : public ELEM_HOLDER
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;
rotate = T_on;
@ -2131,6 +2148,7 @@ public:
*/
static int Compare( PADSTACK* lhs, PADSTACK* rhs );
void SetPadstackId( const char* aPadstackId )
{
padstack_id = aPadstackId;
@ -2194,6 +2212,15 @@ public:
};
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
@ -2228,6 +2255,7 @@ public:
void AddPadstack( PADSTACK* aPadstack )
{
aPadstack->SetParent( this );
padstacks.push_back( aPadstack );
}
@ -2537,10 +2565,15 @@ class NET : public ELEM
bool unassigned;
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 expose;
PIN_REFS noexpose;
PIN_REFS source;
PIN_REFS load;
PIN_REFS terminator;
DSN_T type; ///< T_fix | T_normal
DSN_T supply; ///< T_power | T_ground
@ -3525,6 +3558,9 @@ public:
};
typedef boost::ptr_set<PADSTACK> PADSTACKSET;
/**
* Class SPECCTRA_DB
* 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[];
PADSTACKSET padstackset;
/// we don't want ownership here permanently, so we don't use boost::ptr_vector
std::vector<NET*> nets;
/**
* Function buildLayerMaps
* 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
* satisfies bool isSymbol().
* If not, an IOError is thrown.
* @return DSN_T - the actual token read in.
* @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
@ -3718,28 +3771,35 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
/**
* Function makeIMAGE
* 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
* makes all the PADSTACKs, and marks each D_PAD with the index into the
* LIBRARY::padstacks list that it matches.
* 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.
*/
void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads );
PADSTACK* makePADSTACK( BOARD* aBoard, D_PAD* aPad );
/**
* Function makeVia
* makes a round through hole PADSTACK using the given Kicad diameter in deci-mils.
* @param aCopperDiameter The diameter of the copper pad.
* @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
* or delete it.
*/
PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter );
PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter,
int aTopLayer, int aBotLayer );
/**
* Function makeVia
@ -3751,6 +3811,19 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
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>-----------------------------------------------------
/**
@ -3786,6 +3859,8 @@ public:
delete pcb;
delete session;
deleteNETs();
if( fp )
fclose( fp );
}

View File

@ -40,7 +40,9 @@
#include "trigo.h" // RotatePoint()
#include <set> // std::set
#include <map> // std::map
#include <boost/utility.hpp> // boost::addressof()
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 )
/**************************************************************************/
{
const D_PAD* padref = *(D_PAD**)refptr;
const D_PAD* padcmp = *(D_PAD**)objptr;
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;
wxString padName;
// get all the MODULE's pads.
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
if( isKeepout( pad ) )
{
KEEPOUT* keepout = new KEEPOUT(image, T_keepout);
image->keepouts.push_back( keepout );
double diameter = scale( pad->m_Drill.x );
POINT vertex = mapPt( pad->m_Pos0 );
CIRCLE* circle = new CIRCLE(keepout);
keepout->SetShape( circle );
int layerCount = aBoard->GetCopperLayerCount();
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->SetVertex( mapPt( pad->m_Pos0 ) );
circle->layer_id = "signal";
CIRCLE* circle = new CIRCLE( keepout );
keepout->SetShape( circle );
circle->SetDiameter( diameter );
circle->SetVertex( vertex );
circle->SetLayerId( layerIds[layer].c_str() );
}
}
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);
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 );
pin->padstack_id = padstack->padstack_id;
pin->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() );
wxPoint pos( pad->m_Pos0 );
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 )
{
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 )
PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
int aTopLayer, int aBotLayer )
{
char name[48];
PADSTACK* padstack = new PADSTACK( pcb->library );
SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape );
CIRCLE* circle = new CIRCLE( shape );
shape->SetShape( circle );
PADSTACK* padstack = new PADSTACK();
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,
// encode the drill value into the name for later import
scale( aDrillDiameter ) );
CIRCLE* 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",
aTopLayer, aBotLayer, dsnDiameter,
// encode the drill value into the name for later import
scale( aDrillDiameter )
);
name[ sizeof(name)-1 ] = 0;
padstack->SetPadstackId( name );
@ -472,262 +661,32 @@ PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter )
}
/**
* Struct ltWX
* is used secretly by the std:set<> class below. See STRINGSET typedef.
*/
struct ltWX
PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
{
// 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
}
};
int topLayer;
int botLayer;
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 )
{
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 )
@ -740,14 +699,15 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
// Not all boards are exportable. Check that all reference Ids are unique.
// 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 );
typedef std::set<const wxString*, ltWX> STRINGSET;
typedef std::pair<STRINGSET::iterator, bool> PAIR;
STRINGSET references; // holds unique component references
STRINGSET refs; // holds module reference designators
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.
PAIR pair = references.insert( &module->GetReference() );
if( !pair.second ) // insert failed
STRINGSET_PAIR refpair = refs.insert( module->GetReference() );
if( !refpair.second ) // insert failed
{
ThrowIOError( _("Multiple components have identical reference IDs of \"%s\"."),
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>-----------------------------------------------
{
// 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.
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.
// 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 initial padstack list>--------------------------------
//-----<build the images, components, and netlist>-----------------------
{
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'.
pads.Collect( aBoard, scanPADs );
deleteNETs();
makePADSTACKs( aBoard, pads );
// expand the net vector to highestNetCode+1, setting empty to NULL
nets.resize( highestNetCode+1, NULL );
#if 0 && defined(DEBUG)
for( int p=0; p<pads.GetCount(); ++p )
pads[p]->Show( 0, std::cout );
#endif
}
// skip netcode = 0
for( unsigned i=1; i<nets.size(); ++i )
nets[i] = new NET( pcb->network );
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 );
padstackset.clear();
for( int m=0; m<items.GetCount(); ++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 );
if( registered != image )
{
// 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;
image = registered;
}
// @todo: this only works if the user has not modified the MODULE within the PCB
// 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() );
COMPONENT* comp = pcb->placement->LookupCOMPONENT( image->GetImageId() );
PLACE* place = new PLACE( comp );
comp->places.push_back( place );
@ -1060,69 +1040,73 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
if( module->flag )
{
int angle = 1800 - module->m_Orient;
NORMALIZE_ANGLE_POS(angle);
place->SetRotation( angle/10.0 );
place->side = T_back;
}
}
}
//-----<create the nets>------------------------------------------------
{
NETWORK* network = pcb->network;
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 )
// copy the SPECCTRA_DB::padstackset to the LIBRARY. Since we are
// removing, do not increment the iterator
for( PADSTACKSET::iterator i=padstackset.begin(); i!=padstackset.end();
i=padstackset.begin() )
{
EQUIPOT* kinet = (EQUIPOT*) nets[n];
PADSTACKSET::auto_type ps = padstackset.release( i );
PADSTACK* padstack = ps.release();
if( kinet->GetNet() == 0 )
continue;
pcb->library->AddPadstack( padstack );
}
NET* net = new NET( network );
network->nets.push_back( net );
net->net_id = CONV_TO_UTF8( kinet->m_Netname );
net->net_number = kinet->GetNet();
for( int m=0; m<items.GetCount(); ++m )
// copy our SPECCTRA_DB::nets to the pcb->network
for( unsigned n=1; n<nets.size(); ++n )
{
NET* net = nets[n];
if( net->pins.size() )
{
MODULE* module = (MODULE*) items[m];
pads.Collect( module, scanPADs );
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() );
}
}
// give ownership to pcb->network
pcb->network->nets.push_back( net );
nets[n] = 0;
}
}
}
//-----< 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
//-----<create the wires from tracks>-----------------------------------