Commit 8ef96230 authored by dickelbeck's avatar dickelbeck
Browse files

more amazing free specctra software

parent 316d7b73
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -1251,10 +1251,10 @@ void SPECCTRA_DB::doPROPERTIES( PROPERTIES* growth ) throw( IOError )
        if( tok != T_LEFT )
            expecting( T_LEFT );

        needSYMBOL();
        needSYMBOLorNUMBER();
        property.name = lexer->CurText();

        needSYMBOL();
        needSYMBOLorNUMBER();
        property.value = lexer->CurText();

        growth->push_back( property );
@@ -1848,7 +1848,7 @@ void SPECCTRA_DB::doPLACE( PLACE* growth ) throw( IOError )
        case T_pn:
            if( growth->part_number.size() )
                unexpected( tok );
            needSYMBOL();
            needSYMBOLorNUMBER();
            growth->part_number = lexer->CurText();
            needRIGHT();
            break;
@@ -2561,7 +2561,7 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
            doTOPOLOGY( growth->topology );
            break;

        default:    // handle all the circuit_descriptor here as strings
        case T_circuit:  // handle all the circuit_descriptor here as strings
            {
                std::string     builder;
                int             bracketNesting = 1; // we already saw the opening T_LEFT
@@ -2607,6 +2607,10 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
                if( tok==T_EOF )
                    unexpected( T_EOF );
            }                                   // scope bracket
            break;

        default:
                unexpected( lexer->CurText() );
        }                                       // switch

        tok = nextTok();
@@ -3486,6 +3490,7 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote
    {
        static const char quoteThese[] = "\t ()"
            "%"     // per Alfons of freerouting.net, he does not like this unquoted as of 1-Feb-2008
            "{}"    // guessing that these are problems too
            ;

        // if the string to be wrapped (wrapee) has a delimiter in it,
+35 −24
Original line number Diff line number Diff line
@@ -225,8 +225,8 @@ struct POINT
    /**
     * 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.
     * storage format.  Basically turns off the sign bit if the mantissa and
     * exponent say the value is otherwise zero.
     */
    void FixNegativeZero()
    {
@@ -536,7 +536,7 @@ class RECTANGLE : public ELEM

    std::string     layer_id;

    POINT           point0;
    POINT           point0;         ///< one of two opposite corners
    POINT           point1;

public:
@@ -882,11 +882,12 @@ class WINDOW : public ELEM
    friend class SPECCTRA_DB;

protected:
    /*  shape holds one of these
    PATH*           path;           ///< used for both path and polygon
    RECTANGLE*      rectangle;
    CIRCLE*         circle;
    QARC*           qarc;
    /*  <shape_descriptor >::=
        [<rectangle_descriptor> |
        <circle_descriptor> |
        <polygon_descriptor> |
        <path_descriptor> |
        <qarc_descriptor> ]
    */
    ELEM*       shape;

@@ -2561,6 +2562,7 @@ public:
            out->Print( 0, "\n" );
    }
};
typedef boost::ptr_vector<COMP_ORDER>   COMP_ORDERS;


class NET : public ELEM
@@ -2677,6 +2679,7 @@ public:
        out->Print( nestLevel, ")\n" );
    }
};
typedef boost::ptr_vector<NET>  NETS;


class TOPOLOGY : public ELEM
@@ -2685,7 +2688,6 @@ class TOPOLOGY : public ELEM

    FROMTOS         fromtos;

    typedef boost::ptr_vector<COMP_ORDER>   COMP_ORDERS;
    COMP_ORDERS     comp_orders;

public:
@@ -2739,35 +2741,45 @@ public:

    void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
    {
        const int RIGHTMARGIN = 80;

        const char* quote = out->GetQuoteChar( class_id.c_str() );

        int perLine = out->Print( nestLevel, "(%s %s%s%s",
                              LEXER::GetTokenText( Type() ),
                              quote, class_id.c_str(), quote );

        const int RIGHTMARGIN = 72;

        for( STRINGS::iterator i=net_ids.begin();  i!=net_ids.end();  ++i )
        {
            const char* space = " ";
            if( perLine > RIGHTMARGIN )
            {
                out->Print( 0, "\n" );
                perLine = out->Print( nestLevel+1, "%s", "" );
                space = ""; // no space at first net_id of the line
            }

            quote = out->GetQuoteChar( i->c_str() );
            perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
            perLine += out->Print( 0, "%s%s%s%s", space, quote, i->c_str(), quote );
        }

        bool newLine = false;
        if( circuit.size() || layer_rules.size() || topology )
        if( circuit.size() || rules || layer_rules.size() || topology )
        {
            out->Print( 0, "\n" );
            newLine = true;
        }

        if( circuit.size() )
        {
            out->Print( nestLevel+1, "(circuit\n" );
            for( STRINGS::iterator i=circuit.begin();  i!=circuit.end();  ++i )
            out->Print( nestLevel+1, "%s\n", i->c_str() );
                out->Print( nestLevel+2, "%s\n", i->c_str() );
            out->Print( nestLevel+1, ")\n" );
        }

        if( rules )
            rules->Format( out, nestLevel+1 );

        for( LAYER_RULES::iterator i=layer_rules.begin();  i!=layer_rules.end();  ++i )
            i->Format( out, nestLevel+1 );
@@ -2778,16 +2790,14 @@ public:
        out->Print( newLine ? nestLevel : 0, ")\n" );
    }
};
typedef boost::ptr_vector<CLASS> CLASSLIST;


class NETWORK : public ELEM
{
    friend class SPECCTRA_DB;

    typedef boost::ptr_vector<NET>  NETS;
    NETS        nets;

    typedef boost::ptr_vector<CLASS> CLASSLIST;
    CLASSLIST   classes;


@@ -3637,6 +3647,7 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
     */
    int findLayerName( const std::string& aLayerName ) const;


    /**
     * Function nextTok
     * returns the next token from the lexer.
@@ -3843,12 +3854,6 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
        nets.clear();
    }

    /**
     * Function flipMODULEs
     * flips the modules which are on the back side of the board to the front.
     */
    void flipMODULEs( BOARD* aBoard );

    //-----<FromSESSION>-----------------------------------------------------

    /**
@@ -4002,6 +4007,12 @@ public:
     */
    void ExportSESSION( wxString aFilename );

    /**
     * Function FlipMODULEs
     * flips the modules which are on the back side of the board to the front.
     */
    void FlipMODULEs( BOARD* aBoard );

    /**
     * Function RevertMODULEs
     * flips the modules which were on the back side of the board back to the back.
+95 −46
Original line number Diff line number Diff line
@@ -84,6 +84,11 @@ void WinEDA_PcbFrame::ExportToSpecctra( wxCommandEvent& event )

    setlocale( LC_NUMERIC, "C" );    // Switch the locale to standard C

    //  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.
    db.FlipMODULEs( m_Pcb );

    try
    {
        db.FromBOARD( m_Pcb );
@@ -102,8 +107,7 @@ void WinEDA_PcbFrame::ExportToSpecctra( wxCommandEvent& event )

    setlocale( LC_NUMERIC, "" );      // revert to the current locale

    // this is called in FromBOARD() too, but if it throws an exception, that call
    // does not happen, so call it again just in case here.
    // done assuredly, even if an exception was thrown and caught.
    db.RevertMODULEs( m_Pcb );


@@ -538,7 +542,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad )
}


/// data type used to ensure unique-ness of pin names
/// data type used to ensure unique-ness of pin names, holding (wxString and int)
typedef std::map<wxString, int, wxString_less_than> PINMAP;


@@ -672,19 +676,26 @@ IMAGE* SPECCTRA_DB::makeIMAGE( BOARD* aBoard, MODULE* aModule )
                path->SetAperture( scale( graphic->m_Width ) );
                path->SetLayerId( "signal" );

                double  radius = hypot( scale( graphic->m_Start.x - graphic->m_End.x ),
                                        scale( graphic->m_Start.y - graphic->m_End.y ) );
                // Do the math using Kicad units, that way we stay out of the
                // scientific notation range of floating point numbers in the
                // DSN file.   We do not parse scientific notation in our own
                // lexer/beautifier, and the spec is not clear that this is
                // required.  Fixed point floats are all that should be needed.

                POINT   offset = mapPt( graphic->m_Start0 );
                double  radius = hypot( double( graphic->m_Start.x - graphic->m_End.x ),
                                        double( graphic->m_Start.y - graphic->m_End.y ) );

                // better if evenly divisible into 360
                const int DEGREE_INTERVAL = 18;         // 18 means 20 line segments

                for( double radians = 0.0;  radians < 2*M_PI;  radians += DEGREE_INTERVAL * M_PI / 180.0 )
                {
                    POINT   point(  radius*cos( radians ), radius*sin( radians )  );
                    point += offset;
                    path->AppendPoint( point );
                    wxPoint   point( int( radius * cos( radians ) ),
                                     int( radius * sin( radians ) ) );

                    point += graphic->m_Start0;     // an offset

                    path->AppendPoint( mapPt(point) );
                }
            }
            break;
@@ -749,8 +760,7 @@ PADSTACK* SPECCTRA_DB::makeVia( const SEGVIA* aVia )
    return makeVia( aVia->m_Width, aVia->GetDrillValue(), topLayer, botLayer );
}


typedef std::set<wxString, wxString_less_than>  STRINGSET;
typedef std::set<std::string>  STRINGSET;
typedef std::pair<STRINGSET::iterator, bool> STRINGSET_PAIR;


@@ -785,7 +795,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
            }

            // if we cannot insert OK, that means the reference has been seen before.
            STRINGSET_PAIR refpair = refs.insert( module->GetReference() );
            STRINGSET_PAIR refpair = refs.insert( CONV_TO_UTF8( module->GetReference() ) );
            if( !refpair.second )      // insert failed
            {
                ThrowIOError( _("Multiple components have identical reference IDs of \"%s\"."),
@@ -797,11 +807,6 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
    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.
    flipMODULEs( aBoard );

    //-----<layer_descriptor>-----------------------------------------------
    {
        // specctra wants top physical layer first, then going down to the
@@ -938,10 +943,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
        int     curTrackWidth = aBoard->m_BoardSettings->m_CurrentTrackWidth;
        int     curTrackClear = aBoard->m_BoardSettings->m_TrackClearence;

        // The +5 is to give freerouter a little extra room, this is 0.5 mils.
        // The +1 is to give freerouter a little extra room, this is 0.1 mils.
        // If we export without this, then on import freerouter violates our
        // DRC checks with track to via spacing.
        double  clearance = scale(curTrackClear+5);
        // DRC checks with track to via spacing, although this could be a
        // result of > testing vs. >= testing in PCBNEW's DRC.
        double  clearance = scale(curTrackClear+1);

        STRINGS& rules = pcb->structure->rules->rules;

@@ -996,15 +1002,14 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

            plane->name = CONV_TO_UTF8( item->m_Netname );

            wxString        layerName = aBoard->GetLayerName( item->GetLayer() );
            polygon->layer_id = CONV_TO_UTF8( layerName );
            polygon->layer_id = layerIds[ kicadLayer2pcb[ item->GetLayer() ] ];

            int count = item->m_Poly->corner.size();
            for( int j=0; j<count; ++j )
            {
                wxPoint   point( item->m_Poly->corner[j].x,
                                 item->m_Poly->corner[j].y );
                polygon->points.push_back( mapPt(point) );
                polygon->AppendPoint( mapPt(point) );
            }

            pcb->structure->planes.push_back( plane );
@@ -1015,6 +1020,9 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

    //-----<build the images, components, and netlist>-----------------------
    {
        PIN_REF     empty( pcb->network );
        std::string componentId;

        // find the highest numbered netCode within the board.
        int highestNetCode = -1;
        for( EQUIPOT* equipot = aBoard->m_Equipots;  equipot;  equipot = equipot->Next() )
@@ -1046,15 +1054,17 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

            IMAGE*  image  = makeIMAGE( aBoard, module );

            componentId = CONV_TO_UTF8( module->GetReference() );

            // 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
            // of pin names within a module, do not move this code because
            // the life of this 'IMAGE* image' is not necessarily long.  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];
@@ -1068,7 +1078,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

                    PIN_REF& pin_ref = net->pins.back();

                    pin_ref.component_id = CONV_TO_UTF8( module->GetReference() );
                    pin_ref.component_id = componentId;
                    pin_ref.pin_id = pin->pin_id;
                }
            }
@@ -1090,7 +1100,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

            place->SetRotation( module->m_Orient/10.0 );
            place->SetVertex( mapPt( module->m_Pos ) );
            place->component_id = CONV_TO_UTF8( module->GetReference() );
            place->component_id = componentId;
            place->part_number  = CONV_TO_UTF8( module->GetValue() );

            // module is flipped from bottom side, set side to T_back
@@ -1115,21 +1125,11 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
            pcb->library->AddPadstack( padstack );
        }

        D(std::string component = "U1";)

        // copy our SPECCTRA_DB::nets to the pcb->network
        for( unsigned n=1;  n<nets.size();  ++n )
        {
            NET* net = nets[n];
            if( net->pins.size()

#if defined(DEBUG)
                // experimenting with exporting a subset of all the nets
                // and with incremental, iterative autorouting.
                &&  net->FindPIN_REF( component ) >= 0
#endif

              )
            if( net->pins.size() )
            {
                // give ownership to pcb->network
                pcb->network->nets.push_back( net );
@@ -1146,7 +1146,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
        // Next we add the via's which may be used.

        int defaultViaSize = aBoard->m_BoardSettings->m_CurrentViaSize;

        /* I need at least one via for the (class...) scope below
        if( defaultViaSize )
        */
        {
            PADSTACK*   padstack = makeVia( defaultViaSize, g_DesignSettings.m_ViaDrill,
                                           0, aBoard->GetCopperLayerCount()-1 );
@@ -1196,10 +1199,12 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
        {
            TRACK*  track = (TRACK*) items[i];

            if( track->GetNet() == 0 )
            int     netcode = track->GetNet();

            if( netcode == 0 )
                continue;

            if( old_netcode != track->GetNet()
            if( old_netcode != netcode
            ||  old_width   != track->m_Width
            ||  old_layer   != track->GetLayer()
            ||  (path && path->points.back() != mapPt(track->m_Start) )
@@ -1208,10 +1213,10 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )
                old_width   = track->m_Width;
                old_layer   = track->GetLayer();

                if( old_netcode != track->GetNet() )
                if( old_netcode != netcode )
                {
                    old_netcode = track->GetNet();
                    EQUIPOT* equipot = aBoard->FindNet( track->GetNet() );
                    old_netcode = netcode;
                    EQUIPOT* equipot = aBoard->FindNet( netcode );
                    wxASSERT( equipot );
                    netname = CONV_TO_UTF8( equipot->m_Netname );
                }
@@ -1290,21 +1295,65 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard ) throw( IOError )

        if( viaNdx != -1 )
        {
#if 1
            for(  ; viaNdx < (int)padstacks.size();  ++viaNdx )
            {
                vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() );
            }
#else
            // output only the default via.   Then use class_descriptors to
            // override the default.  No, this causes free router not to
            // output the unmentioned vias into the session file.
            vias->AppendVia( padstacks[viaNdx].padstack_id.c_str() );
#endif
        }
    }


    //-----<flip modules back>----------------------------------------------
    //-----<output a default class with all nets and the via and track size>--
    {
        char        text[80];
        STRINGSET   netIds;       // sort the net names in here

        CLASS*  clazz = new CLASS( pcb->network );
        pcb->network->classes.push_back( clazz );

        // freerouter creates a class named 'default' anyway, and if we
        // try and use that, we end up with two 'default' via rules so use
        // something else as the name of our default class.   Someday we may support
        // additional classes.  Until then the user can text edit the exported
        // DSN file and use this class as a template, copying it and giving the
        // copy a different class_id and splitting out some of the nets.
        clazz->class_id = "kicad_default";

        // Insert all the net_ids into the set.  They are unique, but even if
        // they were not the duplicated name is not our error, but the BOARD's.
        // A duplicate would be removed here.
        NETS& nets = pcb->network->nets;
        for( NETS::iterator i=nets.begin();  i!=nets.end();  ++i )
            netIds.insert( i->net_id );

        // netIds is now sorted, put them into clazz->net_ids
        for( STRINGSET::iterator i=netIds.begin();  i!=netIds.end();  ++i )
            clazz->net_ids.push_back( *i );

        // output the via and track dimensions, the whole reason for this scope.
        int     curTrackWidth = aBoard->m_BoardSettings->m_CurrentTrackWidth;

        clazz->rules = new RULE( clazz, T_rule );

        sprintf( text, "(width %.6g)", scale( curTrackWidth ) );
        clazz->rules->rules.push_back( text );

    RevertMODULEs( aBoard );
        int         viaNdx = pcb->library->via_start_index;

        sprintf( text, "(use_via %s)", pcb->library->padstacks[viaNdx].padstack_id.c_str() );
        clazz->circuit.push_back( text );
    }
}


void SPECCTRA_DB::flipMODULEs( BOARD* aBoard )
void SPECCTRA_DB::FlipMODULEs( BOARD* aBoard )
{
    for( MODULE* module = aBoard->m_Modules;  module;  module = module->Next() )
    {
+31 −8
Original line number Diff line number Diff line
@@ -347,15 +347,18 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
    if( !session->route->library )
        ThrowIOError( _("Session file is missing the \"library_out\" section") );

#if 1
    // delete all the old tracks and vias
    aBoard->m_Track->DeleteStructList();
    aBoard->m_Track = NULL;
    aBoard->m_NbSegmTrack = 0;
#endif

    aBoard->DeleteMARKERs();

    buildLayerMaps( aBoard );

#if 1
    // Walk the PLACEMENT object's COMPONENTs list, and for each PLACE within
    // each COMPONENT, reposition and re-orient each component and put on
    // correct side of the board.
@@ -413,6 +416,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
            }
        }
    }
#endif

    routeResolution = session->route->GetUnits();

@@ -430,8 +434,10 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
            EQUIPOT* equipot = aBoard->FindNet( netName );
            if( equipot )
                netCode = equipot->GetNet();

            // else netCode remains 0
            else  // else netCode remains 0
            {
                // int breakhere = 1;
            }
        }

        WIRES& wires = net->wires;
@@ -442,21 +448,38 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )

            if( shape != T_path )
            {
                /*  shape == T_polygon is expected from freerouter if you have
                    a zone on a non "power" type layer, i.e. a T_signal layer
                    and the design does a round trip back in as session here.
                    We kept our own zones in the BOARD, so ignore this so called
                    'wire'.

                wxString netId = CONV_FROM_UTF8( wire->net_id.c_str() );
                ThrowIOError(
                    _("Unsupported wire shape: \"%s\" for net: \"%s\""),
                    LEXER::GetTokenString(shape).GetData(),
                    netId.GetData()
                    );
                */
            }

            else
            {
                PATH*   path = (PATH*) wire->shape;
                for( unsigned pt=0;  pt<path->points.size()-1;  ++pt )
                {
                    /* a debugging aid, may come in handy
                    if( path->points[pt].x == 547800
                    &&  path->points[pt].y == -380250 )
                    {
                        int breakhere = 1;
                    }
                    */

                    TRACK* track = makeTRACK( path, pt, netCode );
                    aBoard->Add( track );
                }
            }
        }

        WIRE_VIAS& wire_vias = net->wire_vias;
        LIBRARY& library = *session->route->library;