Commit 1c294c33 authored by dickelbeck's avatar dickelbeck

more free specctra support, MODULE::GetValue()

parent 6d6ca5ee
......@@ -5,6 +5,13 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with
email address.
2008-Jan-29 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
+pcbnew:
SPECCTRA export does most items now, except existing tracks. Soon will
need testing.
2008-Jan-28 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+pcbnew:
......
......@@ -180,13 +180,21 @@ public:
/**
* Function GetReference
* @return wxString - the reference designator text.
* @return const wxString& - the reference designator text.
*/
const wxString& GetReference()
{
return m_Reference->m_Text;
}
/**
* Function GetValue
* @return const wxString& - the value text.
*/
const wxString& GetValue()
{
return m_Value->m_Text;
}
/**
* Function Visit
......
......@@ -617,7 +617,8 @@ public:
/**
* Function SetSpaceInQuotedTokens
* changes the setting controlling whether a space in a quoted string is
* a terminator
* a terminator.
* @param val If true, means
*/
bool SetSpaceInQuotedTokens( bool val )
{
......
......@@ -57,7 +57,7 @@
// 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"
#define STANDALONE // define "stand alone, i.e. unit testing"
#if defined(STANDALONE)
......@@ -1707,6 +1707,10 @@ void SPECCTRA_DB::doPLACE( PLACE* growth ) throw( IOError )
while( (tok = nextTok()) != T_RIGHT )
{
if( tok != T_LEFT )
expecting( T_LEFT );
tok = nextTok();
switch( tok )
{
case T_mirror:
......@@ -1772,7 +1776,9 @@ void SPECCTRA_DB::doPLACE( PLACE* growth ) throw( IOError )
case T_pn:
if( growth->part_number.size() )
unexpected( tok );
needSYMBOL();
growth->part_number = lexer->CurText();
needRIGHT();
break;
default:
......@@ -3633,6 +3639,22 @@ int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
}
//-----<COMPONENT>--------------------------------------------------------
/*
int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* 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;
}
*/
//-----<PARSER>-----------------------------------------------------------
PARSER::PARSER( ELEM* aParent ) :
......@@ -3688,8 +3710,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
const char* quote = out->GetQuoteChar( component_id.c_str() );
if( place_rules || properties.size() || lock_type!=T_NONE || rules
|| region || part_number.size() )
if( place_rules || properties.size() || rules || region )
{
useMultiLine = true;
......@@ -3714,17 +3735,19 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
out->Print( 0, " %.6g", rotation );
}
out->Print( 0, " " );
if( mirror != T_NONE )
out->Print( 0, " (mirror %s)", LEXER::GetTokenText( mirror ) );
out->Print( 0, "(mirror %s)", LEXER::GetTokenText( mirror ) );
if( status != T_NONE )
out->Print( 0, " (status %s)", LEXER::GetTokenText( status ) );
out->Print( 0, "(status %s)", LEXER::GetTokenText( status ) );
if( logical_part.size() )
{
quote = out->GetQuoteChar( logical_part.c_str() );
out->Print( 0, " (logical_part %s%s%s)",
out->Print( 0, "(logical_part %s%s%s)",
quote, logical_part.c_str(), quote );
}
......@@ -3764,7 +3787,20 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
}
}
else
out->Print( 0, ")\n" );
{
if( lock_type != T_NONE )
out->Print( 0, "(lock_type %s)",
LEXER::GetTokenText(lock_type) );
if( part_number.size() )
{
const char* quote = out->GetQuoteChar( part_number.c_str() );
out->Print( 0, "(PN %s%s%s)",
quote, part_number.c_str(), quote );
}
}
out->Print( 0, ")\n" );
}
......
......@@ -616,49 +616,6 @@ public:
};
#if 0
class PLACE_RULE : public RULE
{
friend class SPECCTRA_DB;
DSN_T object_type;
DSN_T image_type;
/* T_spacing, T_permit_orient, T_permit_side & T_opposite_side are
all stored in the kids list.
*/
public:
PLACE_RULE( ELEM* aParent ) :
RULE( aParent, T_place_rule )
{
object_type = T_NONE;
image_type = T_NONE;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( object_type != T_NONE )
{
if( object_type == T_pcb )
out->Print( nestLevel, "(object_type %s",
LEXER::GetTokenText( object_type ) );
else
out->Print( nestLevel, "(object_type image_set %s",
LEXER::GetTokenText( object_type ) );
if( image_type != T_NONE )
out->Print( 0, " (image_type %s)", LEXER::GetTokenText( image_type ) );
out->Print( 0, ")\n" );
}
RULE::FormatContents( out, nestLevel );
}
};
#endif
class LAYER_RULE : public ELEM
{
friend class SPECCTRA_DB;
......@@ -1680,6 +1637,10 @@ public:
};
/**
* Class PLACE
* implements the &lt;placement_reference&gt; in the specctra dsn spec.
*/
class PLACE : public ELEM
{
friend class SPECCTRA_DB;
......@@ -1688,7 +1649,6 @@ class PLACE : public ELEM
DSN_T side;
bool isRotated;
double rotation;
bool hasVertex;
......@@ -1718,7 +1678,9 @@ public:
ELEM( T_place, aParent )
{
side = T_front;
isRotated = false;
rotation = 0.0;
hasVertex = false;
mirror = T_NONE;
......@@ -1740,26 +1702,31 @@ public:
void SetVertex( const POINT& aVertex )
{
vertex = aVertex;
vertex.FixNegativeZero();
hasVertex = true;
}
void SetRotation( double aRotation )
{
rotation = aRotation;
isRotated = (aRotation != 0.0);
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
};
typedef boost::ptr_vector<PLACE> PLACES;
/**
* Class COMPONENT
* implements the &lt;component_descriptor&gt; in the specctra dsn spec.
*/
class COMPONENT : public ELEM
{
friend class SPECCTRA_DB;
// std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
std::string image_id;
typedef boost::ptr_vector<PLACE> PLACES;
PLACES places;
public:
......@@ -1768,17 +1735,35 @@ public:
{
}
const std::string& GetImageId() const { return image_id; }
void SetImageId( const std::string& aImageId )
{
image_id = aImageId;
}
/**
* 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\n", LEXER::GetTokenText( Type() ),
quote, image_id.c_str(), quote );
for( PLACES::iterator i=places.begin(); i!=places.end(); ++i )
i->Format( out, nestLevel+1 );
FormatContents( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( PLACES::iterator i=places.begin(); i!=places.end(); ++i )
i->Format( out, nestLevel );
}
};
......@@ -1805,6 +1790,27 @@ public:
{
delete unit;
}
/**
* Function LookupCOMPONENT
* looks up a COMPONENT by name. If the name is not found, a new
* COMPONENT is added to the components container. At any time the
* names in the component container should remain unique.
* @return COMPONENT* - an existing or new
*/
COMPONENT* LookupCOMPONENT( const std::string& imageName )
{
for( unsigned i=0; i<components.size(); ++i )
{
if( 0 == components[i].GetImageId().compare( imageName ) )
return &components[i];
}
COMPONENT* added = new COMPONENT(this);
components.push_back( added );
added->SetImageId( imageName );
return added;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
......@@ -2111,7 +2117,7 @@ public:
// format the kids, which in this class are the shapes
ELEM_HOLDER::FormatContents( out, nestLevel );
out->Print( nestLevel+1, "%s", "" );
out->Print( nestLevel, "%s", "" );
// spec for <attach_descriptor> says default is on, so
// print the off condition to override this.
......@@ -2193,6 +2199,12 @@ public:
return via_start_index;
}
/**
* Function FindIMAGE
* searches this LIBRARY for an image which matches the argument.
* @return int - if found the index into the images list, else -1.
*/
int FindIMAGE( IMAGE* aImage )
{
for( unsigned i=0; i<images.size(); ++i )
......@@ -2202,22 +2214,35 @@ public:
}
return -1;
}
/**
* Function AppendIMAGE
* adds the image to the image list.
*/
void AppendIMAGE( IMAGE* aImage )
{
aImage->SetParent( this );
images.push_back( aImage );
}
bool LookupIMAGE( IMAGE* aImage )
/**
* Function LookupIMAGE
* will add the image only if one exactly like it does not alread exist
* in the image list.
* @return IMAGE* - the IMAGE which is registered in the LIBRARY that
* matches the argument, and it will be either the argument or
* a previous image which is a duplicate.
*/
IMAGE* LookupIMAGE( IMAGE* aImage )
{
int ndx = FindIMAGE( aImage );
if( ndx == -1 )
{
AppendIMAGE( aImage );
return false;
return aImage;
}
return true;
return &images[ndx];
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
......
......@@ -76,11 +76,11 @@ void WinEDA_PcbFrame::ExportToSPECCTRA( wxCommandEvent& event )
// if an exception is thrown by FromBOARD or ExportPCB(), then
// ~SPECCTRA_DB() will close the file.
}
catch ( IOError ioe )
catch( IOError ioe )
{
ok = false;
// display no messages until we flip back the modules below.
// copy the error string to safe place, ioe is in this scope only.
errorText = ioe.errorText;
}
......@@ -112,6 +112,11 @@ static inline void swap( POINT_PAIR& pair )
}
/**
* Function scale
* converts a distance from kicad units to our reported specctra dsn units:
* 1/10000 inches (deci-mils) to mils. So the factor of 10 comes in.
*/
static inline double scale( int kicadDist )
{
return kicadDist/10.0;
......@@ -139,6 +144,7 @@ static POINT mapPt( const wxPoint& pt )
POINT ret;
ret.x = mapX( pt.x );
ret.y = mapY( pt.y );
ret.FixNegativeZero();
return ret;
}
......@@ -238,32 +244,55 @@ static QARC* makeArc( const POINT& aStart, const POINT& aEnd,
IMAGE* SPECCTRA_DB::makeIMAGE( MODULE* aModule )
{
TYPE_COLLECTOR items;
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
PADSTACKS& padstacks = pcb->library->padstacks;
TYPE_COLLECTOR pads;
static const KICAD_T scanPADs[] = { TYPEPAD, EOT };
// get all the MODULE's pads.
items.Collect( aModule, scanPADs );
pads.Collect( aModule, scanPADs );
IMAGE* image = new IMAGE( 0 );
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 )
// from the pads, and make an IMAGE using collated padstacks.
for( int p=0; p<pads.GetCount(); ++p )
{
D_PAD* pad = (D_PAD*) items[p];
D_PAD* pad = (D_PAD*) pads[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 ) );
// see if this pad is a through hole with no copper on its perimeter
if( !pad->IsOnLayer( LAYER_CMP_N ) && !pad->IsOnLayer( COPPER_LAYER_N ) )
{
if( pad->m_Drill.x!=0 )
{
KEEPOUT* keepout = new KEEPOUT(image, T_keepout);
image->keepouts.push_back( keepout );
WINDOW* window = new WINDOW(keepout);
keepout->windows.push_back( window );
CIRCLE* circle = new CIRCLE(window);
window->SetShape( circle );
circle->SetDiameter( scale(pad->m_Drill.x) );
circle->SetVertex( POINT( mapPt( pad->m_Pos0 ) ) );
circle->layer_id = "signal";
// ?? the keepout is not affecting the power layers?
}
}
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() );
pin->SetVertex( mapPt( pad->m_Pos0 ) );
}
}
return image;
......@@ -562,7 +591,8 @@ void SPECCTRA_DB::makePADSTACKs( BOARD* aBoard, TYPE_COLLECTOR& aPads )
}
}
// unique pads are now in the padstack. next we add the via's which may be used.
// 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 )
......@@ -636,6 +666,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
}
}
// a space in a quoted token is NOT a terminator, true establishes this.
pcb->parser->space_in_quoted_tokens = true;
//-----<unit_descriptor> & <resolution_descriptor>--------------------
{
......@@ -648,7 +680,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
//-----<boundary_descriptor>------------------------------------------
{
// get all the DRAWSEGMENTS into 'items', then look for layer == EDGE_N,
// and those segments comprize the board's perimeter.
// and those segments comprise the board's perimeter.
static const KICAD_T scanDRAWSEGMENTS[] = { TYPEDRAWSEGMENT, EOT };
items.Collect( aBoard, scanDRAWSEGMENTS );
......@@ -725,8 +757,8 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
bottomRight.x = aBoard->m_BoundaryBox.GetRight();
bottomRight.y = aBoard->m_BoundaryBox.GetBottom();
rect->point0 = mapPt( aBoard->m_BoundaryBox.GetOrigin() );
rect->point1 = mapPt( bottomRight );
rect->SetCorners( mapPt( aBoard->m_BoundaryBox.GetOrigin() ),
mapPt( bottomRight ) );
boundary->rectangle = rect;
......@@ -808,7 +840,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
}
//-----<build the images>----------------------------------------------
//-----<build the images and components>---------------------------------
{
static const KICAD_T scanMODULEs[] = { TYPEMODULE, EOT };
items.Collect( aBoard, scanMODULEs );
......@@ -819,10 +851,29 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
IMAGE* image = makeIMAGE( module );
if( pcb->library->LookupIMAGE( image ) )
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.
delete image;
}
const std::string& imageId = registered->image_id;
COMPONENT* comp = pcb->placement->LookupCOMPONENT( imageId );
PLACE* place = new PLACE( comp );
comp->places.push_back( place );
place->SetRotation( module->m_Orient/10.0 );
place->SetVertex( mapPt( module->m_Pos ) );
place->component_id = CONV_TO_UTF8( module->GetReference() );
place->part_number = CONV_TO_UTF8( module->GetValue() );
// module is flipped from bottom side, set side to T_back
if( module->flag )
place->side = T_back;
}
}
......@@ -844,6 +895,44 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
}
//-----<create the nets>------------------------------------------------
{
NETWORK* network = pcb->network;
static const KICAD_T scanNETs[] = { PCB_EQUIPOT_STRUCT_TYPE, EOT };
items.Collect( aBoard, scanNETs );
PIN_REF emptypin(0);
for( int i=0; i<items.GetCount(); ++i )
{
EQUIPOT* kinet = (EQUIPOT*)items[i];
NET* net = new NET( network );
network->nets.push_back( net );
net->net_id = CONV_TO_UTF8( kinet->m_Netname );
net->net_number = kinet->GetNet();
D_PAD** ppad = kinet->m_PadzoneStart;
for( ; ppad < kinet->m_PadzoneEnd; ++ppad )
{
D_PAD* pad = *ppad;
wxASSERT( pad->Type() == TYPEPAD );
// 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*)pad->m_Parent)->GetReference() );;
pin_ref->pin_id = CONV_TO_UTF8( pad->ReturnStringPadName() );
}
}
}
//-----<restore MODULEs>------------------------------------------------
// DSN Images (=Kicad MODULES and pads) must be presented from the
......
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