Commit 709be495 authored by dickelbeck's avatar dickelbeck

more amazing free specctra work

parent 10ded82d
...@@ -5,6 +5,15 @@ Started 2007-June-11 ...@@ -5,6 +5,15 @@ 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
================================================================================ ================================================================================
...@@ -18,7 +27,7 @@ email address. ...@@ -18,7 +27,7 @@ email address.
** 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. ...@@ -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
......
...@@ -213,6 +213,7 @@ wxString BOARD_ITEM::MenuText( const BOARD* aPcb ) const ...@@ -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 )
{ {
......
...@@ -76,6 +76,7 @@ namespace DSN { ...@@ -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 ) ...@@ -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 ) ...@@ -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 )
{ {
...@@ -468,6 +478,8 @@ void SPECCTRA_DB::doPCB( PCB* growth ) throw( IOError ) ...@@ -468,6 +478,8 @@ 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 ) ...@@ -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) ...@@ -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: ...@@ -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: ...@@ -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,7 +2243,8 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError ) ...@@ -2219,7 +2243,8 @@ 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 ) if( tok == T_LEFT )
{ {
tok = nextTok(); tok = nextTok();
...@@ -2230,9 +2255,9 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError ) ...@@ -2230,9 +2255,9 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError )
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 ) if( !isSymbol(tok) && tok!=T_NUMBER )
expecting( "pin_id" ); expecting( "pin_id" );
...@@ -2245,9 +2270,8 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError ) ...@@ -2245,9 +2270,8 @@ void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError )
if( nextTok() != T_NUMBER ) if( nextTok() != T_NUMBER )
expecting( T_NUMBER ); expecting( T_NUMBER );
growth->vertex.y = strtod( lexer->CurText(), 0 ); 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 ) ...@@ -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;
...@@ -2308,6 +2332,7 @@ void SPECCTRA_DB::doLIBRARY( LIBRARY* growth ) throw( IOError ) ...@@ -2308,6 +2332,7 @@ 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 ) ...@@ -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 ...@@ -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 ...@@ -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 ) ...@@ -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 ); ...@@ -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 ) ...@@ -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 ...@@ -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 @@ ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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 ...@@ -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; ...@@ -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 ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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: ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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 @@ ...@@ -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 ) ...@@ -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,246 +314,52 @@ static PATH* makePath( const POINT& aStart, const POINT& aEnd, const std::string ...@@ -312,246 +314,52 @@ static PATH* makePath( const POINT& aStart, const POINT& aEnd, const std::string
} }
IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
{
PADSTACKS& padstacks = pcb->library->padstacks;
TYPE_COLLECTOR pads;
// get all the MODULE's pads.
pads.Collect( aModule, scanPADs );
IMAGE* image = new IMAGE(0);
image->image_id = CONV_TO_UTF8( aModule->m_LibRef );
// from the pads, and make an IMAGE using collated padstacks.
for( int p=0; p<pads.GetCount(); ++p )
{
D_PAD* pad = (D_PAD*) pads[p];
// 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 );
CIRCLE* circle = new CIRCLE(keepout);
keepout->SetShape( circle );
circle->SetDiameter( scale(pad->m_Drill.x) );
circle->SetVertex( mapPt( pad->m_Pos0 ) );
circle->layer_id = "signal";
}
else
{
PADSTACK* padstack = &padstacks[pad->m_logical_connexion];
PIN* pin = new PIN(image);
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 );
int angle = pad->m_Orient - aModule->m_Orient; // tenths of degrees
if( angle )
{
NORMALIZE_ANGLE_POS(angle);
pin->SetRotation( angle / 10.0 );
if( pad->m_Offset.x || pad->m_Offset.y )
{
RotatePoint( &offset, angle );
}
}
pos += offset;
pin->SetVertex( mapPt( pos ) );
}
}
return image;
}
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 )
{
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 );
double dsnDiameter = scale(aCopperDiameter);
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( aDrillDiameter ) );
name[ sizeof(name)-1 ] = 0;
padstack->SetPadstackId( name );
return padstack;
}
/** /**
* Struct ltWX * Struct wxString_less_than_
* is used secretly by the std:set<> class below. See STRINGSET typedef. * is used the std:set<> and std::map<> instantiations below.
* See STRINGSET typedef and PINMAP typedef below.
*/ */
struct ltWX struct wxString_less_than
{ {
// a "less than" test on two wxStrings, by pointer. // a "less than" test on two wxStrings, by pointer.
bool operator()( const wxString* s1, const wxString* s2) const bool operator()( const wxString& s1, const wxString& s2) const
{ {
return s1->Cmp( *s2 ) < 0; // case specific wxString compare return s1.Cmp( s2 ) < 0; // case specific wxString compare
} }
}; };
void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) /**
* 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 char name[80]; // padstack name builder
std::string uniqifier; 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 bool doLayer[2] = { // top and bottom layers only
pad->IsOnLayer( LAYER_CMP_N ), aPad->IsOnLayer( LAYER_CMP_N ),
pad->IsOnLayer( COPPER_LAYER_N ) aPad->IsOnLayer( COPPER_LAYER_N )
}; };
if( old_pad && 0==D_PAD::Compare( old_pad, pad ) ) // caller must do this screen before calling here.
{ wxASSERT( !isKeepout( aPad ) );
// 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 ); wxASSERT( doLayer[0] || doLayer[1] );
pcb->library->AddPadstack( padstack );
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks PADSTACK* padstack = new PADSTACK();
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
/* Through hole pads are reported on the <reserved_layer_name> int reportedLayers = 0; // how many in reported padstack
"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]; const char* layerName[NB_COPPER_LAYERS];
static const char signal[] = "signal"; if( aPad->m_Attribut==PAD_SMD || aPad->m_Attribut==PAD_CONN )
if( pad->m_Attribut==PAD_SMD || pad->m_Attribut==PAD_CONN )
{ {
reportedLayers = 0; // PAD_SMD and PAD_CONN are reported on each layer for which
// they are present.
uniqifier = '['; uniqifier = '[';
if( doLayer[0] ) if( doLayer[0] )
...@@ -568,19 +376,41 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) ...@@ -568,19 +376,41 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
uniqifier += ']'; uniqifier += ']';
} }
else
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; reportedLayers = 1;
layerName[0] = signal; layerName[0] = signal;
uniqifier = "[A]"; // A for all 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( pad->m_PadShape ) switch( aPad->m_PadShape )
{ {
default: default:
case PAD_CIRCLE: case PAD_CIRCLE:
{ {
double diameter = scale(pad->m_Size.x); double diameter = scale(aPad->m_Size.x);
for( int ndx=0; ndx<reportedLayers; ++ndx ) for( int ndx=0; ndx<reportedLayers; ++ndx )
{ {
...@@ -595,21 +425,16 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) ...@@ -595,21 +425,16 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
} }
snprintf( name, sizeof(name), "Round%sPad_%.6g_mil", snprintf( name, sizeof(name), "Round%sPad_%.6g_mil",
uniqifier.c_str(), scale(pad->m_Size.x) ); uniqifier.c_str(), scale(aPad->m_Size.x) );
name[ sizeof(name)-1 ] = 0; 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 ); padstack->SetPadstackId( name );
} }
break; break;
case PAD_RECT: case PAD_RECT:
{ {
double dx = scale( pad->m_Size.x ) / 2.0; double dx = scale( aPad->m_Size.x ) / 2.0;
double dy = scale( pad->m_Size.y ) / 2.0; double dy = scale( aPad->m_Size.y ) / 2.0;
POINT lowerLeft( -dx, -dy ); POINT lowerLeft( -dx, -dy );
POINT upperRight( dx, dy ); POINT upperRight( dx, dy );
...@@ -627,21 +452,17 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) ...@@ -627,21 +452,17 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
} }
snprintf( name, sizeof(name), "Rect%sPad_%.6gx%.6g_mil", snprintf( name, sizeof(name), "Rect%sPad_%.6gx%.6g_mil",
uniqifier.c_str(), scale(pad->m_Size.x), scale(pad->m_Size.y) ); uniqifier.c_str(), scale(aPad->m_Size.x), scale(aPad->m_Size.y) );
name[ sizeof(name)-1 ] = 0; 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 ); padstack->SetPadstackId( name );
} }
break; break;
case PAD_OVAL: case PAD_OVAL:
{ {
double dx = scale( pad->m_Size.x ) / 2.0; double dx = scale( aPad->m_Size.x ) / 2.0;
double dy = scale( pad->m_Size.y ) / 2.0; double dy = scale( aPad->m_Size.y ) / 2.0;
double dr = dx - dy; double dr = dx - dy;
if( dr >= 0 ) // oval is horizontal if( dr >= 0 ) // oval is horizontal
...@@ -680,13 +501,9 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) ...@@ -680,13 +501,9 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
} }
snprintf( name, sizeof(name), "Oval%sPad_%.6gx%.6g_mil", snprintf( name, sizeof(name), "Oval%sPad_%.6gx%.6g_mil",
uniqifier.c_str(), scale(pad->m_Size.x), scale(pad->m_Size.y) ); uniqifier.c_str(), scale(aPad->m_Size.x), scale(aPad->m_Size.y) );
name[ sizeof(name)-1 ] = 0; 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 ); padstack->SetPadstackId( name );
} }
break; break;
...@@ -696,40 +513,182 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads ) ...@@ -696,40 +513,182 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
break; 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 );
IMAGE* image = new IMAGE(0);
image->image_id = CONV_TO_UTF8( aModule->m_LibRef );
// from the pads, and make an IMAGE using collated padstacks.
for( int p=0; p<pads.GetCount(); ++p )
{
D_PAD* pad = (D_PAD*) pads[p];
// see if this pad is a through hole with no copper on its perimeter
if( isKeepout( pad ) )
{
double diameter = scale( pad->m_Drill.x );
POINT vertex = mapPt( pad->m_Pos0 );
int layerCount = aBoard->GetCopperLayerCount();
for( int layer=0; layer<layerCount; ++layer )
{
KEEPOUT* keepout = new KEEPOUT(image, T_keepout);
image->keepouts.push_back( keepout );
CIRCLE* circle = new CIRCLE( keepout );
keepout->SetShape( circle );
circle->SetDiameter( diameter );
circle->SetVertex( vertex );
circle->SetLayerId( layerIds[layer].c_str() );
}
} }
else
{
PADSTACK* padstack = makePADSTACK( aBoard, pad );
// unique pads are now in the padstack list. PADSTACKSET::iterator iter = padstackset.find( *padstack );
// next we add the via's which may be used. 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 );
}
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize; PIN* pin = new PIN(image);
if( defaultViaSize )
padName = pad->ReturnStringPadName();
pin->pin_id = CONV_TO_UTF8( padName );
if( padName!=wxEmptyString && pinmap.find( padName )==pinmap.end() )
{ {
PADSTACK* padstack = makeVia( defaultViaSize, g_DesignSettings.m_ViaDrill ); pinmap[ padName ] = 0;
pcb->library->AddPadstack( padstack ); }
else
{
char buf[32];
// remember this index, it is the default via and also the start of the int duplicates = ++pinmap[ padName ];
// vias within the padstack list. Before this index are the pads.
// At this index and later are the vias. sprintf( buf, "@%d", duplicates );
pcb->library->SetViaStartIndex( pcb->library->padstacks.size()-1 );
// padstack->SetPadstackId( "Via_Default" ); I like the padstack_id with the size in it. pin->pin_id += buf; // append "@1" or "@2", etc. to pin name
} }
for( int i=0; i<HISTORY_NUMBER; ++i ) pin->kiNetCode = pad->GetNet();
image->pins.push_back( pin );
pin->padstack_id = padstack->padstack_id;
wxPoint pos( pad->m_Pos0 );
wxPoint offset( pad->m_Offset.x, pad->m_Offset.y );
int angle = pad->m_Orient - aModule->m_Orient; // tenths of degrees
if( angle )
{ {
int viaSize = aBoard->m_BoardSettings->m_ViaSizeHistory[i]; NORMALIZE_ANGLE_POS(angle);
if( !viaSize ) pin->SetRotation( angle / 10.0 );
break;
if( viaSize == defaultViaSize ) if( pad->m_Offset.x || pad->m_Offset.y )
continue; {
RotatePoint( &offset, angle );
}
}
PADSTACK* padstack = makeVia( viaSize, g_DesignSettings.m_ViaDrill ); pos += offset;
pcb->library->AddPadstack( padstack );
pin->SetVertex( mapPt( pos ) );
}
} }
return image;
} }
PADSTACK* SPECCTRA_DB::makeVia( int aCopperDiameter, int aDrillDiameter,
int aTopLayer, int aBotLayer )
{
char name[48];
PADSTACK* padstack = new PADSTACK();
double dsnDiameter = scale(aCopperDiameter);
for( int layer=aTopLayer; layer<=aBotLayer; ++layer )
{
SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape );
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 );
return padstack;
}
PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
{
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 )
{
}
#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 )
{ {
TYPE_COLLECTOR items; TYPE_COLLECTOR items;
...@@ -740,14 +699,15 @@ 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.
{ {
items.Collect( aBoard, scanMODULEs ); TYPE_COLLECTOR padItems;
typedef std::set<const wxString*, ltWX> STRINGSET; items.Collect( aBoard, scanMODULEs );
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 ) for( int i=0; i<items.GetCount(); ++i )
{ {
...@@ -760,8 +720,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError ) ...@@ -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 ) ...@@ -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 ) ...@@ -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 ) ...@@ -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;
// get all the D_PADs into 'pads'. for( EQUIPOT* equipot = aBoard->m_Equipots; equipot; equipot = equipot->Next() )
pads.Collect( aBoard, scanPADs ); highestNetCode = MAX( highestNetCode, equipot->GetNet() );
makePADSTACKs( aBoard, pads ); deleteNETs();
#if 0 && defined(DEBUG) // expand the net vector to highestNetCode+1, setting empty to NULL
for( int p=0; p<pads.GetCount(); ++p ) nets.resize( highestNetCode+1, NULL );
pads[p]->Show( 0, std::cout );
#endif
}
// skip netcode = 0
for( unsigned i=1; i<nets.size(); ++i )
nets[i] = new NET( pcb->network );
//-----<build the images and components>--------------------------------- 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 );
}
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 ) ...@@ -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();
i=padstackset.begin() )
{ {
NETWORK* network = pcb->network; PADSTACKSET::auto_type ps = padstackset.release( i );
TYPE_COLLECTOR nets; PADSTACK* padstack = ps.release();
TYPE_COLLECTOR pads;
static const KICAD_T scanNETs[] = { PCB_EQUIPOT_STRUCT_TYPE, EOT };
nets.Collect( aBoard, scanNETs ); pcb->library->AddPadstack( padstack );
}
items.Collect( aBoard, scanMODULEs );
PIN_REF emptypin(0);
for( int n=0; n<nets.GetCount(); ++n ) // copy our SPECCTRA_DB::nets to the pcb->network
for( unsigned n=1; n<nets.size(); ++n )
{ {
EQUIPOT* kinet = (EQUIPOT*) nets[n]; NET* net = nets[n];
if( net->pins.size() )
if( kinet->GetNet() == 0 ) {
continue; // give ownership to pcb->network
pcb->network->nets.push_back( net );
nets[n] = 0;
}
}
}
NET* net = new NET( network );
network->nets.push_back( net );
net->net_id = CONV_TO_UTF8( kinet->m_Netname ); //-----< output the vias >-----------------------------------------------
net->net_number = kinet->GetNet(); {
// 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.
for( int m=0; m<items.GetCount(); ++m ) int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
if( defaultViaSize )
{ {
MODULE* module = (MODULE*) items[m]; PADSTACK* padstack = makeVia( defaultViaSize, g_DesignSettings.m_ViaDrill,
0, aBoard->GetCopperLayerCount()-1 );
pcb->library->AddPadstack( padstack );
pads.Collect( module, scanPADs ); // 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 p=0; p<pads.GetCount(); ++p ) for( int i=0; i<HISTORY_NUMBER; ++i )
{ {
D_PAD* pad = (D_PAD*) pads[p]; int viaSize = aBoard->m_BoardSettings->m_ViaSizeHistory[i];
if( !viaSize )
break;
if( pad->GetNet() == kinet->GetNet() ) if( viaSize == defaultViaSize )
{ continue;
// 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 ); PADSTACK* padstack = makeVia( viaSize, g_DesignSettings.m_ViaDrill,
pin_ref->component_id = CONV_TO_UTF8( module->GetReference() ); 0, aBoard->GetCopperLayerCount()-1 );
pin_ref->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() ); 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>-----------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment