Commit 67ebe29b authored by dickelbeck's avatar dickelbeck

more free specctra work

parent 7878ba27
Change Log for Kicad
Started 2007-June-11
......@@ -16,7 +15,6 @@ email address.
the new track takes the width of the existing track
2008-Jan-27 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+all:
......
......@@ -55,6 +55,8 @@
#include <wx/ffile.h>
// To build the DSN beautifier and unit tester, simply uncomment this and then
// use CMake's makefile to build target "specctra_test".
//#define STANDALONE // define "stand alone, i.e. unit testing"
......@@ -861,24 +863,32 @@ void SPECCTRA_DB::doWINDOW( WINDOW* growth ) throw( IOError )
switch( tok )
{
case T_rect:
growth->rectangle = new RECTANGLE( growth );
doRECTANGLE( growth->rectangle );
if( growth->shape )
unexpected( tok );
growth->shape = new RECTANGLE( growth );
doRECTANGLE( (RECTANGLE*) growth->shape );
break;
case T_circle:
growth->circle = new CIRCLE( growth );
doCIRCLE( growth->circle );
if( growth->shape )
unexpected( tok );
growth->shape = new CIRCLE( growth );
doCIRCLE( (CIRCLE*) growth->shape );
break;
case T_path:
case T_polygon:
growth->path = new PATH( growth, tok );
doPATH( growth->path );
if( growth->shape )
unexpected( tok );
growth->shape = new PATH( growth, tok );
doPATH( (PATH*) growth->shape );
break;
case T_qarc:
growth->qarc = new QARC( growth );
doQARC( growth->qarc );
if( growth->shape )
unexpected( tok );
growth->shape = new QARC( growth );
doQARC( (QARC*) growth->shape );
break;
default:
......@@ -3353,18 +3363,19 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
return total;
}
// factor out a common GetQuoteChar
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char )
{
// I include '#' so a symbol is not confused with a comment. We intend
// to wrap any symbol starting with a '#'.
// Our LEXER class handles comments, and comments appear to be an extension
// to the SPECCTRA DSN specification.
if( *wrapee == '#' )
return quote_char.c_str();
return quote_char;
if( strlen(wrapee)==0 )
return quote_char.c_str();
return quote_char;
bool isNumber = true;
......@@ -3373,19 +3384,25 @@ const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
// if the string to be wrapped (wrapee) has a delimiter in it,
// return the quote_char so caller wraps the wrapee.
if( strchr( "\t ()", *wrapee ) )
return quote_char.c_str();
return quote_char;
if( !strchr( "01234567890.-+", *wrapee ) )
isNumber = false;
}
if( isNumber )
return quote_char.c_str();
return quote_char;
return ""; // can use an unwrapped string.
}
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
{
return OUTPUTFORMATTER::GetQuoteChar( wrapee, quote_char.c_str() );
}
void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
{
fp = wxFopen( filename, wxT("w") );
......@@ -3438,6 +3455,8 @@ PCB* SPECCTRA_DB::MakePCB()
pcb->structure = new STRUCTURE( pcb );
pcb->structure->boundary = new BOUNDARY( pcb->structure );
pcb->structure->via = new VIA( pcb->structure );
pcb->structure->rules = new RULE( pcb->structure, T_rule );
pcb->placement = new PLACEMENT( pcb );
......@@ -3451,6 +3470,87 @@ PCB* SPECCTRA_DB::MakePCB()
}
//-----<STRINGFORMATTER>----------------------------------------------------
const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
{
// for what we are using STRINGFORMATTER for at this time, we can return the nul string
// always.
return "";
// return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
}
int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
{
int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
if( ret >= (int) buffer.size() )
{
buffer.reserve( ret+200 );
ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
}
if( ret > 0 )
mystring.append( (const char*) &buffer[0] );
return ret;
}
int STRINGFORMATTER::sprint( const char* fmt, ... )
{
va_list args;
va_start( args, fmt );
int ret = vprint( fmt, args);
va_end( args );
return ret;
}
int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
va_list args;
va_start( args, fmt );
int result = 0;
int total = 0;
for( int i=0; i<nestLevel; ++i )
{
result = sprint( "%*c", NESTWIDTH, ' ' );
if( result < 0 )
break;
total += result;
}
if( result<0 || (result=vprint( fmt, args ))<0 )
{
throw IOError( _("Error writing to STRINGFORMATTER") );
}
va_end( args );
total += result;
return total;
}
void STRINGFORMATTER::StripUseless()
{
for( std::string::iterator i=mystring.begin(); i!=mystring.end(); )
{
if( isspace( *i ) || *i==')' || *i=='(' )
mystring.erase(i);
else
++i;
}
}
//-----<ELEM>---------------------------------------------------------------
ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
......@@ -3500,8 +3600,40 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
}
//-----<PARSER>-----------------------------------------------------------
//-----<PADSTACK>---------------------------------------------------------
int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
{
if( !lhs->hash.size() )
lhs->hash = lhs->makeHash();
if( !rhs->hash.size() )
rhs->hash = rhs->makeHash();
int result = lhs->hash.compare( rhs->hash );
return result;
}
//-----<IMAGE>------------------------------------------------------------
int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
{
if( !lhs->hash.size() )
lhs->hash = lhs->makeHash();
if( !rhs->hash.size() )
rhs->hash = rhs->makeHash();
int result = lhs->hash.compare( rhs->hash );
// printf("\"%s\" \"%s\" ret=%d\n", lhs->hash.c_str(), rhs->hash.c_str(), result );
return result;
}
//-----<PARSER>-----------------------------------------------------------
PARSER::PARSER( ELEM* aParent ) :
ELEM( T_parser, aParent )
......
......@@ -32,6 +32,8 @@
#include "fctsys.h"
#include "dsn.h"
class TYPE_COLLECTOR; // outside the DSN namespace
/**
......@@ -101,9 +103,86 @@ public:
* if the wrapee does not need to be wrapped.
*/
virtual const char* GetQuoteChar( const char* wrapee ) = 0;
virtual ~OUTPUTFORMATTER() {}
/**
* Function GetQuoteChar
* factor may be used by derived classes to perform quote character selection.
* @param wrapee A string that might need wrapping on each end.
* @param quote_char A single character C string which hold the current quote character.
* @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped.
*/
static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
};
/**
* Class STRINGFORMATTER
* implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
* string is available through GetString()
*/
class STRINGFORMATTER : public OUTPUTFORMATTER
{
std::vector<char> buffer;
std::string mystring;
int sprint( const char* fmt, ... );
int vprint( const char* fmt, va_list ap );
public:
/**
* Constructor STRINGFORMATTER
* reserves space in the buffer
*/
STRINGFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' )
{
}
/**
* Function Clear
* clears the buffer and empties the internal string.
*/
void Clear()
{
mystring.clear();
}
/**
* Function StripUseless
* removes whitespace, '(', and ')' from the mystring.
*/
void StripUseless();
/*
const char* c_str()
{
return mystring.c_str();
}
*/
std::string GetString()
{
return mystring;
}
//-----<OUTPUTFORMATTER>------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>-----------------------------------------------
};
/**
* Class POINT
* is a holder for a point in the SPECCTRA DSN coordinate system. It can also
* be used to hold a distance (vector really) from some origin.
*/
struct POINT
{
double x;
......@@ -136,14 +215,23 @@ struct POINT
POINT& operator=( const POINT& other )
{
x = other.x;
if( x == -0.0 ) // correct -0.0 so output looks nice.
x = 0.0;
y = other.y;
if( y == -0.0 )
y = 0.0;
return *this;
}
/**
* Function FixNegativeZero
* will change negative zero to positive zero in the IEEE floating point
* storage format. Basically turns off the sign bit if the mantiss and exponent
* would say the value is zero.
*/
void FixNegativeZero()
{
if( x == -0.0 )
x = 0.0;
if( y == -0.0 )
y = 0.0;
}
/**
* Function Format
......@@ -196,10 +284,33 @@ typedef std::vector<PROPERTY> PROPERTIES;
class ELEM
{
friend class SPECCTRA_DB;
protected:
DSN_T type;
ELEM* parent;
/**
* Function makeHash
* returns a string which uniquely represents this ELEM amoung other
* ELEMs of the same derived class as "this" one.
* It is not useable for all derived classes, only those which plan for
* it by implementing a FormatContents() function that captures all info
* which will be used in the subsequent string compare. THIS SHOULD
* NORMALLY EXCLUDE THE TYPENAME, AND INSTANCE NAME OR ID AS WELL.
*/
std::string makeHash()
{
STRINGFORMATTER sf;
FormatContents( &sf, 0 );
sf.StripUseless();
return sf.GetString();
}
public:
......@@ -207,7 +318,7 @@ public:
virtual ~ELEM();
DSN_T Type() { return type; }
DSN_T Type() const { return type; }
/**
......@@ -216,7 +327,7 @@ public:
* to check for section specific overrides.
* @return DSN_T - one of the allowed values to &lt;unit_descriptor&gt;
*/
virtual DSN_T GetUnits()
virtual DSN_T GetUnits() const
{
if( parent )
return parent->GetUnits();
......@@ -324,14 +435,14 @@ public:
kids.insert( kids.begin()+aIndex, aElem );
}
ELEM* At( int aIndex )
ELEM* At( int aIndex ) const
{
// we have varying sized objects and are using polymorphism, so we
// must return a pointer not a reference.
return &kids[aIndex];
return (ELEM*) &kids[aIndex];
}
ELEM* operator[]( int aIndex )
ELEM* operator[]( int aIndex ) const
{
return At( aIndex );
}
......@@ -408,7 +519,7 @@ public:
LEXER::GetTokenText(units), value );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
return units;
}
......@@ -439,7 +550,10 @@ public:
void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
{
point0 = aPoint0;
point0.FixNegativeZero();
point1 = aPoint1;
point1.FixNegativeZero();
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
......@@ -581,7 +695,6 @@ public:
out->Print( nestLevel, ")\n" );
}
};
typedef boost::ptr_vector<LAYER_RULE> LAYER_RULES;
......@@ -780,15 +893,21 @@ public:
}
void SetStart( const POINT& aStart )
{
vertex[0] = aStart;
vertex[0] = aStart;
// no -0.0 on the printouts!
vertex[0].FixNegativeZero();
}
void SetEnd( const POINT& aEnd )
{
vertex[1] = aEnd;
// no -0.0 on the printouts!
vertex[1].FixNegativeZero();
}
void SetCenter( const POINT& aCenter )
{
vertex[2] = aCenter;
// no -0.0 on the printouts!
vertex[2].FixNegativeZero();
}
};
......@@ -797,49 +916,53 @@ class WINDOW : public ELEM
{
friend class SPECCTRA_DB;
//----- only one of these is used, like a union -----
protected:
/* shape holds one of these
PATH* path; ///< used for both path and polygon
RECTANGLE* rectangle;
CIRCLE* circle;
QARC* qarc;
//---------------------------------------------------
*/
ELEM* shape;
public:
WINDOW( ELEM* aParent ) :
ELEM( T_window, aParent )
WINDOW( ELEM* aParent, DSN_T aType = T_window ) :
ELEM( aType, aParent )
{
path = 0;
rectangle = 0;
circle = 0;
qarc = 0;
shape = 0;
}
~WINDOW()
{
delete path;
delete rectangle;
delete circle;
delete qarc;
delete shape;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
void SetShape( ELEM* aShape )
{
// these are mutually exclusive
if( rectangle )
rectangle->Format( out, nestLevel );
else if( path )
path->Format( out, nestLevel );
delete shape;
shape = aShape;
else if( circle )
circle->Format( out, nestLevel );
if( aShape )
{
wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
|| aShape->Type()==T_qarc || aShape->Type()==T_path
|| aShape->Type()==T_polygon);
aShape->SetParent( this );
}
}
else if( qarc )
qarc->Format( out, nestLevel );
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) );
if( shape )
shape->Format( out, 0 );
out->Print( 0, ")\n" );
}
};
typedef boost::ptr_vector<WINDOW> WINDOWS;
......@@ -956,6 +1079,11 @@ public:
ELEM( T_via, aParent )
{
}
void AppendVia( const char* aViaName )
{
padstacks.push_back( aViaName );
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
......@@ -1217,13 +1345,13 @@ public:
layer_weight );
}
};
typedef boost::ptr_vector<LAYER_PAIR> LAYER_PAIRS;
class LAYER_NOISE_WEIGHT : public ELEM
{
friend class SPECCTRA_DB;
typedef boost::ptr_vector<LAYER_PAIR> LAYER_PAIRS;
LAYER_PAIRS layer_pairs;
public:
......@@ -1542,7 +1670,7 @@ public:
i->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -1693,7 +1821,7 @@ public:
i->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -1710,7 +1838,7 @@ public:
* elements contains, i.e. in its "shape" field. This class also implements
* the "(outline ...)" element as a dual personality.
*/
class SHAPE : public ELEM
class SHAPE : public WINDOW
{
friend class SPECCTRA_DB;
......@@ -1722,38 +1850,18 @@ class SHAPE : public ELEM
<polygon_descriptor> |
<path_descriptor> |
<qarc_descriptor> ]
ELEM* shape; // inherited from WINDOW
*/
ELEM* shape;
WINDOWS windows;
public:
SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
ELEM( aType, aParent )
WINDOW( aParent, aType )
{
connect = T_on;
shape = 0;
}
~SHAPE()
{
delete shape;
}
void SetShape( ELEM* aShape )
{
delete shape;
shape = aShape;
if( aShape )
{
wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
|| aShape->Type()==T_qarc || aShape->Type()==T_path
|| aShape->Type()==T_polygon);
aShape->SetParent( this );
}
}
void SetConnect( DSN_T aConnect )
{
connect = aConnect;
......@@ -1808,6 +1916,12 @@ public:
isRotated = (aRotation != 0.0);
}
void SetVertex( const POINT& aPoint )
{
vertex = aPoint;
vertex.FixNegativeZero();
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
......@@ -1830,6 +1944,8 @@ class IMAGE : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
std::string image_id;
DSN_T side;
UNIT_RES* unit;
......@@ -1864,42 +1980,53 @@ public:
delete place_rules;
}
/**
* Function Compare
* compares two objects of this type and returns <0, 0, or >0.
*/
static int Compare( IMAGE* lhs, IMAGE* rhs );
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( image_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
quote, image_id.c_str(), quote );
FormatContents( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
// this is here for makeHash()
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( side != T_both )
out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) );
out->Print( 0, "\n");
if( unit )
unit->Format( out, nestLevel+1 );
unit->Format( out, nestLevel );
// format the kids, which in this class are the shapes
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
ELEM_HOLDER::FormatContents( out, nestLevel );
for( PINS::iterator i=pins.begin(); i!=pins.end(); ++i )
i->Format( out, nestLevel+1 );
i->Format( out, nestLevel );
if( rules )
rules->Format( out, nestLevel+1 );
rules->Format( out, nestLevel );
if( place_rules )
place_rules->Format( out, nestLevel+1 );
place_rules->Format( out, nestLevel );
for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
i->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
i->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -1907,12 +2034,20 @@ public:
return ELEM::GetUnits();
}
};
typedef boost::ptr_vector<IMAGE> IMAGES;
/**
* Class PADSTACK
* holds either a via or a pad definition.
*/
class PADSTACK : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
std::string padstack_id;
UNIT_RES* unit;
......@@ -1942,6 +2077,13 @@ public:
delete rules;
}
/**
* Function Compare
* compares two objects of this type and returns <0, 0, or >0.
*/
static int Compare( PADSTACK* lhs, PADSTACK* rhs );
void SetPadstackId( const char* aPadstackId )
{
padstack_id = aPadstackId;
......@@ -1954,11 +2096,20 @@ public:
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, padstack_id.c_str(), quote );
FormatContents( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
// this factored out for use by Compare()
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( unit )
unit->Format( out, nestLevel+1 );
unit->Format( out, nestLevel );
// format the kids, which in this class are the shapes
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
ELEM_HOLDER::FormatContents( out, nestLevel );
out->Print( nestLevel+1, "%s", "" );
......@@ -1982,12 +2133,11 @@ public:
out->Print( 0, "\n" );
if( rules )
rules->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
rules->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -2007,25 +2157,68 @@ typedef boost::ptr_vector<PADSTACK> PADSTACKS;
class LIBRARY : public ELEM
{
friend class SPECCTRA_DB;
UNIT_RES* unit;
typedef boost::ptr_vector<IMAGE> IMAGES;
UNIT_RES* unit;
IMAGES images;
PADSTACKS padstacks;
/// The start of the vias within the padstacks, which trail the pads.
/// This field is not Format()ed.
int via_start_index;
public:
LIBRARY( ELEM* aParent, DSN_T aType = T_library ) :
ELEM( aType, aParent )
{
unit = 0;
via_start_index = -1; // 0 or greater means there is at least one via
}
~LIBRARY()
{
delete unit;
}
void AddPadstack( PADSTACK* aPadstack )
{
padstacks.push_back( aPadstack );
}
void SetViaStartIndex( int aIndex )
{
via_start_index = aIndex;
}
int GetViaStartIndex()
{
return via_start_index;
}
int FindIMAGE( IMAGE* aImage )
{
for( unsigned i=0; i<images.size(); ++i )
{
if( 0 == IMAGE::Compare( aImage, &images[i] ) )
return (int) i;
}
return -1;
}
void AppendIMAGE( IMAGE* aImage )
{
aImage->SetParent( this );
images.push_back( aImage );
}
bool LookupIMAGE( IMAGE* aImage )
{
int ndx = FindIMAGE( aImage );
if( ndx == -1 )
{
AppendIMAGE( aImage );
return false;
}
return true;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
......@@ -2039,18 +2232,13 @@ public:
i->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
void AddPadstack( PADSTACK* aPadstack )
{
padstacks.push_back( aPadstack );
}
};
......@@ -2422,6 +2610,8 @@ public:
class CONNECT : public ELEM
{
// @todo not completed.
public:
CONNECT( ELEM* parent ) :
ELEM( T_connect, parent ) {}
......@@ -2695,7 +2885,7 @@ public:
i->Format( out, nestLevel );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -2780,7 +2970,7 @@ public:
out->Print( nestLevel, ")\n" );
}
DSN_T GetUnits()
DSN_T GetUnits() const
{
if( unit )
return unit->GetUnits();
......@@ -3179,6 +3369,8 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
wxString filename;
std::string quote_char;
STRINGFORMATTER sf;
/**
......@@ -3321,6 +3513,22 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
void doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError );
/**
* Function makeIMAGE
* allocates an IMAGE on the heap and creates all the PINs according
* to the PADs in the MODULE.
*/
IMAGE* makeIMAGE( MODULE* aModule );
/**
* Function makePADSTACKs
* makes all the PADSTACKs, and marks each D_PAD with the index into the
* LIBRARY::padstacks list that it matches.
*/
void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads );
public:
SPECCTRA_DB()
......@@ -3332,7 +3540,7 @@ public:
quote_char += '"';
}
~SPECCTRA_DB()
virtual ~SPECCTRA_DB()
{
delete lexer;
delete pcb;
......
......@@ -234,14 +234,43 @@ static QARC* makeArc( const POINT& aStart, const POINT& aEnd,
qarc->SetLayerId( aLayerName.c_str() );
return qarc;
}
/**
* Function makePADSTACKs
* makes all the PADSTACKs, and marks each D_PAD with the index into the
* LIBRARY::padstacks list that it matches.
*/
static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibrary )
IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
{
TYPE_COLLECTOR items;
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
PADSTACKS& padstacks = pcb->library->padstacks;
// get all the MODULE's pads.
items.Collect( aModule, scanPADs );
IMAGE* image = new IMAGE( 0 );
image->image_id = CONV_TO_UTF8( aModule->m_LibRef );
// collate all the pads, and make a component.
for( int p=0; p<items.GetCount(); ++p )
{
D_PAD* pad = (D_PAD*) items[p];
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() );
pin->SetVertex( mapPt( pad->m_Pos0 ) );
}
return image;
}
void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
{
char name[80]; // padstack name builder
......@@ -251,7 +280,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
}
D_PAD* old_pad = NULL;
int padstackNdx = 0;
#define COPPER_LAYERS 2 // top and bottom
......@@ -262,7 +290,7 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
// within a pad's padstack. this is usually correct, but not rigorous. 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
// See page bottom of page 74 of the SECCTRA Design Language Reference, May 2000.
// See bottom of page 74 of the SECCTRA Design Language Reference, May 2000.
std::string layerId[COPPER_LAYERS] = {
CONV_TO_UTF8(aBoard->GetLayerName( LAYER_CMP_N )),
......@@ -270,8 +298,9 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
};
#if 1
// late breaking news, we can use "signal" as the layer name and report the
// padstack as a single layer.
// Late breaking news: we can use the reserved layer name "signal" and report the
// padstack as a single layer. See <reserved_layer_name> in the spec.
// But this probably gives problems for a "power" layer or power pin, we'll see.
reportedLayers = 1;
layerId[0] = "signal";
#endif
......@@ -280,8 +309,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
{
D_PAD* pad = (D_PAD*) aPads[i];
pad->m_logical_connexion = padstackNdx;
bool doLayer[COPPER_LAYERS] = {
pad->IsOnLayer( LAYER_CMP_N ),
pad->IsOnLayer( COPPER_LAYER_N )
......@@ -289,6 +316,10 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
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;
}
......@@ -296,6 +327,9 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
// an "image->keepout" later. No copper pad here, it is probably a hole.
if( !doLayer[0] && !doLayer[1] )
{
// padstacks.size()-1 is the index of the matching padstack in LIBRARY::padstacks
pad->m_logical_connexion = pcb->library->padstacks.size()-1;
continue;
}
......@@ -305,11 +339,11 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
old_pad = pad;
// this is the index into the library->padstacks, be careful.
pad->m_logical_connexion = padstackNdx++;
PADSTACK* padstack = new PADSTACK( aLibrary );
aLibrary->AddPadstack( padstack );
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;
// paddOfset is the offset of copper shape relative to hole position,
// and pad->m_Pos is hole position. All shapes must be shifted by
......@@ -331,12 +365,10 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
{
if( doLayer[layer] )
{
CIRCLE* circle;
SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape );
circle = new CIRCLE( shape );
CIRCLE* circle = new CIRCLE( shape );
shape->SetShape( circle );
circle->SetLayerId( layerId[layer].c_str() );
......@@ -347,7 +379,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
}
snprintf( name, sizeof(name), "Round%dPad_%.6g_mil", coppers, scale(pad->m_Size.x) );
name[ sizeof(name)-1 ] = 0;
// @todo verify that all pad names are unique, there is a chance that
......@@ -536,9 +567,13 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;
if( defaultViaSize )
{
PADSTACK* padstack = new PADSTACK( aLibrary );
aLibrary->AddPadstack( padstack );
padstackNdx++; // remember this index, it is the default via
PADSTACK* padstack = new PADSTACK( pcb->library );
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 );
SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape );
......@@ -560,9 +595,8 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
if( viaSize == defaultViaSize )
continue;
PADSTACK* padstack = new PADSTACK( aLibrary );
aLibrary->AddPadstack( padstack );
padstackNdx++; // remember this index, it is the default via
PADSTACK* padstack = new PADSTACK( pcb->library );
pcb->library->AddPadstack( padstack );
SHAPE* shape = new SHAPE( padstack );
padstack->Append( shape );
......@@ -575,10 +609,6 @@ static void makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads, LIBRARY* aLibra
snprintf( name, sizeof(name), "Via_%.6g_mil", scale(viaSize) );
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 );
}
}
......@@ -593,7 +623,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
if( !pcb )
pcb = SPECCTRA_DB::MakePCB();
// DSN Images (=Kicad MODULES and pads) must be presented from the
// top view. So we temporarily flip any modules which are on the back
// side of the board to the front, and record this in the MODULE's flag field.
......@@ -661,8 +690,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
rect->layer_id = "pcb";
// opposite corners
rect->point0 = ppairs[0].p1;
rect->point1 = ppairs[2].p1;
rect->SetCorners( ppairs[0].p1, ppairs[2].p1 );
boundary->rectangle = rect;
}
......@@ -763,54 +791,60 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
// but in that case they are WINDOWs within the COPPER_PLANEs.
//-----<build the padstack list here, no output>------------------------
//-----<build the initial padstack list>--------------------------------
{
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
TYPE_COLLECTOR pads;
// get all the D_PADs into pads.
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
// get all the D_PADs into 'pads'.
pads.Collect( aBoard, scanPADs );
makePADSTACKs( aBoard, pads, pcb->library );
makePADSTACKs( aBoard, pads );
#if 0 && defined(DEBUG)
for( int p=0; p<pads.GetCount(); ++p )
pads[p]->Show( 0, std::cout );
#endif
}
//-----<via_descriptor>-------------------------------------------------
{
// Output the vias in the padstack list here, by name
}
//-----<build the images>----------------------------------------------
{
/*
static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT };
items.Collect( aBoard, scanMODULEs );
for( int m=0; m<items.GetCount(); ++m )
{
MODULE* module = (MODULE*) items[m];
// collate all the pads, and make a component.
for( int p=0; p<pads.GetCount(); ++p )
IMAGE* image = makeIMAGE( module );
if( pcb->library->LookupIMAGE( image ) )
{
D_PAD* pad = (D_PAD*) pads[p];
D(pad->Show( 0, std::cout );)
// lookup and maybe add this pad to the padstack.
wxString padName = lookupPad( pcb->library->padstacks, pad );
delete image;
}
}
}
//-----<via_descriptor>-------------------------------------------------
{
// Output the vias in the padstack list here, by name
VIA* vias = pcb->structure->via;
PADSTACKS& padstacks = pcb->library->padstacks;
int viaNdx = pcb->library->via_start_index;
if( viaNdx != -1 )
{
for( ; viaNdx < (int)padstacks.size(); ++viaNdx )
{
vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() );
}
}
*/
}
//-----<restore MODULEs>------------------------------------------------
// DSN Images (=Kicad MODULES and pads) must be presented from the
// top view. Restore those that were flipped.
......@@ -822,6 +856,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
module->flag = 0;
}
}
}
......
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