int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel )
{
    wxString msg;

    RoutingMatrix.UnInitRoutingMatrix();

    EDA_RECT bbox = aBrd->ComputeBoundingBox( true );

    if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
    {
        DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
        return 0;
    }

    RoutingMatrix.ComputeMatrixSize( aBrd, true );
    int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows;

    messagePanel->EraseMsgBox();
    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols );
    messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN );
    msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows );
    messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN );
    msg.Printf( wxT( "%d" ), nbCells );
    messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW );

    // Choose the number of board sides.
    RoutingMatrix.m_RoutingLayersCount = 2;

    RoutingMatrix.InitRoutingMatrix();

    // Display memory usage.
    msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 );
    messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN );

    g_Route_Layer_BOTTOM = F_Cu;

    if( RoutingMatrix.m_RoutingLayersCount > 1 )
        g_Route_Layer_BOTTOM = B_Cu;

    g_Route_Layer_TOP = F_Cu;

    // Place the edge layer segments
    TRACK TmpSegm( NULL );

    TmpSegm.SetLayer( UNDEFINED_LAYER );
    TmpSegm.SetNetCode( -1 );
    TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 );

    EDA_ITEM* PtStruct = aBrd->m_Drawings;

    for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
    {
        DRAWSEGMENT* DrawSegm;

        switch( PtStruct->Type() )
        {
        case PCB_LINE_T:
            DrawSegm = (DRAWSEGMENT*) PtStruct;

            if( DrawSegm->GetLayer() != Edge_Cuts )
                break;

            TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
                             RoutingMatrix.m_GridRouting, WRITE_CELL );
            break;

        case PCB_TEXT_T:
        default:
            break;
        }
    }

    // Mark cells of the routing matrix to CELL_is_ZONE
    // (i.e. availlable cell to place a module )
    // Init a starting point of attachment to the area.
    RoutingMatrix.OrCell( RoutingMatrix.m_Nrows / 2, RoutingMatrix.m_Ncols / 2,
                          BOTTOM, CELL_is_ZONE );

    // find and mark all other availlable cells:
    for( int ii = 1; ii != 0; )
        ii = propagate();

    // Initialize top layer. to the same value as the bottom layer
    if( RoutingMatrix.m_BoardSide[TOP] )
        memcpy( RoutingMatrix.m_BoardSide[TOP], RoutingMatrix.m_BoardSide[BOTTOM],
                nbCells * sizeof(MATRIX_CELL) );

    return 1;
}
Beispiel #2
0
/* Initialise les cellules du board a la valeur HOLE et VIA_IMPOSSIBLE
	selon les marges d'isolement
	les elements de net_code = net_code ne seront pas places comme occupe
	mais en VIA_IMPOSSIBLE uniquement
	Pour Routage 1 seule face:
		le plan BOTTOM est utilise
		et Route_Layer_BOTTOM = Route_Layer_TOP

	Selon les bits = 1 du parametre flag:
		si FORCE_PADS : tous les pads seront places meme ceux de meme net_code
*/
void PlaceCells(BOARD * Pcb, int net_code, int flag)
{
int ii;
LISTE_PAD* ptr;
TRACK * pt_segm;
TEXTE_PCB * PtText;
DRAWSEGMENT * DrawSegm;
EDA_BaseStruct * PtStruct;
int ux0 = 0 , uy0 = 0, ux1, uy1, dx, dy;
int marge, via_marge;
int masque_layer;

	marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth /2);
	via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize /2);

	/////////////////////////////////////
	// Placement des PADS sur le board //
	/////////////////////////////////////
	ptr = (LISTE_PAD*)Pcb->m_Pads; ii = Pcb->m_NbPads;
	for( ; ii > 0 ; ii-- , ptr++)
		{
		if( (net_code != (*ptr)->m_NetCode ) || (flag & FORCE_PADS) )
			{
			Place_1_Pad_Board(Pcb, *ptr, HOLE, marge, WRITE_CELL);
			}
		Place_1_Pad_Board(Pcb, *ptr, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL);
		}

	///////////////////////////////////////////////
	// Placement des elements de modules sur PCB //
	///////////////////////////////////////////////
	PtStruct = Pcb->m_Modules;
	for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
		{
		EDA_BaseStruct * PtModStruct = ((MODULE*)PtStruct)->m_Drawings;
		for( ;PtModStruct != NULL; PtModStruct = PtModStruct->Pnext )
			{
			switch( PtModStruct->m_StructType )
				{
				case TYPEEDGEMODULE:
					{
					TRACK * TmpSegm = new TRACK(NULL);
					TmpSegm->m_Layer = ((EDGE_MODULE *) PtModStruct)->m_Layer;
					if(TmpSegm->m_Layer == EDGE_N) TmpSegm->m_Layer = -1;

					TmpSegm->m_Start = ((EDGE_MODULE *) PtModStruct)->m_Start;
					TmpSegm->m_End = ((EDGE_MODULE *) PtModStruct)->m_End;
					TmpSegm->m_Shape = ((EDGE_MODULE *) PtModStruct)->m_Shape;
					TmpSegm->m_Width = ((EDGE_MODULE *) PtModStruct)->m_Width;
					TmpSegm->m_Param = ((EDGE_MODULE *) PtModStruct)->m_Angle;
					TmpSegm->m_NetCode = -1;

					TraceSegmentPcb(Pcb, TmpSegm, HOLE, marge,WRITE_CELL );
					TraceSegmentPcb(Pcb, TmpSegm, VIA_IMPOSSIBLE, via_marge,
									WRITE_OR_CELL );
					delete TmpSegm;
					break;
					}

				default: break;
				}
			}
		}

	////////////////////////////////////////////
	// Placement des contours et segments PCB //
	////////////////////////////////////////////
	PtStruct = Pcb->m_Drawings;
	for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext )
		{
		switch( PtStruct->m_StructType)
			{
			case TYPEDRAWSEGMENT:
				{
				int type_cell = HOLE;
				TRACK * TmpSegm = new TRACK(NULL);
				DrawSegm = (DRAWSEGMENT *) PtStruct;
				TmpSegm->m_Layer = DrawSegm->m_Layer;
				if(DrawSegm->m_Layer == EDGE_N)
					{
					TmpSegm->m_Layer = -1;
					type_cell |= CELL_is_EDGE;
					}

				TmpSegm->m_Start = DrawSegm->m_Start;
				TmpSegm->m_End = DrawSegm->m_End;
				TmpSegm->m_Shape = DrawSegm->m_Shape;
				TmpSegm->m_Width = DrawSegm->m_Width;
				TmpSegm->m_Param = DrawSegm->m_Angle;
				TmpSegm->m_NetCode = -1;

				TraceSegmentPcb(Pcb, TmpSegm, type_cell, marge,WRITE_CELL );
//				TraceSegmentPcb(Pcb, TmpSegm, VIA_IMPOSSIBLE, via_marge,WRITE_OR_CELL );
				delete TmpSegm;
				break;
				}

			case TYPETEXTE:
				PtText = (TEXTE_PCB*) PtStruct;
				if(PtText->GetLength() == 0 ) break;
				ux0 = PtText->m_Pos.x; uy0 = PtText->m_Pos.y;

				dx = PtText->Pitch()* PtText->GetLength();
				dy = PtText->m_Size.y + PtText->m_Width;

				/* Calcul du rectangle d'encadrement */
				dx /= 2; dy /= 2; /* dx et dy = demi dimensionx X et Y */
				ux1 = ux0 + dx; uy1 = uy0 + dy;
				ux0 -= dx; uy0 -= dy;

				masque_layer = g_TabOneLayerMask[PtText->m_Layer];

				TraceFilledRectangle(Pcb, ux0-marge, uy0-marge, ux1+marge, uy1+marge,
								(int)(PtText->m_Orient),
								masque_layer, HOLE, WRITE_CELL);
				TraceFilledRectangle(Pcb, ux0-via_marge, uy0-via_marge,
								ux1+via_marge, uy1+via_marge,
								(int)(PtText->m_Orient),
								masque_layer, VIA_IMPOSSIBLE, WRITE_OR_CELL);
				break;

			default: break;
			}
		}

	/* Placement des PISTES */
	pt_segm = Pcb->m_Track;
	for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext)
		{
		if(net_code == pt_segm->m_NetCode) continue;
		TraceSegmentPcb(Pcb, pt_segm, HOLE, marge, WRITE_CELL );
		TraceSegmentPcb(Pcb, pt_segm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
		}

	/* Placement des ZONES */
	pt_segm = (TRACK*) Pcb->m_Zone;
	for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext)
		{
		if(net_code == pt_segm->m_NetCode) continue;
		TraceSegmentPcb(Pcb, pt_segm, HOLE, marge, WRITE_CELL );
		TraceSegmentPcb(Pcb, pt_segm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
		}
}
Beispiel #3
0
/**
 * Function PlaceCells
 * Initialize the matrix routing by setting obstacles for each occupied cell
 * a cell set to HOLE is an obstacle for tracks and vias
 * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only.
 * a cell set to CELL_is_EDGE is a frontier.
 * Tracks and vias having the same net code as net_code are skipped
 * (htey do not are obstacles)
 *
 * For single-sided Routing 1:
 * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP
 *
 * If flag == FORCE_PADS: all pads will be put in matrix as obstacles.
 */
void PlaceCells( BOARD* aPcb, int net_code, int flag )
{
    int       ux0 = 0, uy0 = 0, ux1, uy1, dx, dy;
    int       marge, via_marge;
    LAYER_MSK layerMask;

    // use the default NETCLASS?
    NETCLASS* nc = aPcb->m_NetClasses.GetDefault();

    int       trackWidth = nc->GetTrackWidth();
    int       clearance  = nc->GetClearance();
    int       viaSize    = nc->GetViaDiameter();

    marge     = clearance + (trackWidth / 2);
    via_marge = clearance + (viaSize / 2);

    // Place PADS on matrix routing:
    for( unsigned i = 0; i < aPcb->GetPadCount(); ++i )
    {
        D_PAD* pad = aPcb->GetPad( i );

        if( net_code != pad->GetNet() || (flag & FORCE_PADS) )
        {
            ::PlacePad( pad, HOLE, marge, WRITE_CELL );
        }

        ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }

    // Place outlines of modules on matrix routing, if they are on a copper layer
    // or on the edge layer
    TRACK tmpSegm( NULL );  // A dummy track used to create segments.

    for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
    {
        for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
        {
            switch( item->Type() )
            {
            case PCB_MODULE_EDGE_T:
            {
                EDGE_MODULE* edge = (EDGE_MODULE*) item;

                tmpSegm.SetLayer( edge->GetLayer() );

                if( tmpSegm.GetLayer() == EDGE_N )
                    tmpSegm.SetLayer( UNDEFINED_LAYER );

                tmpSegm.SetStart( edge->GetStart() );
                tmpSegm.SetEnd(   edge->GetEnd() );
                tmpSegm.SetShape( edge->GetShape() );
                tmpSegm.SetWidth( edge->GetWidth() );
                tmpSegm.m_Param = edge->GetAngle();
                tmpSegm.SetNet( -1 );

                TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL );
                TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
            }
            break;

            default:
                break;
            }
        }
    }

    // Place board outlines and texts on copper layers:
    for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() )
    {
        switch( item->Type() )
        {
        case PCB_LINE_T:
        {
            DRAWSEGMENT* DrawSegm;

            int          type_cell = HOLE;
            DrawSegm = (DRAWSEGMENT*) item;
            tmpSegm.SetLayer( DrawSegm->GetLayer() );

            if( DrawSegm->GetLayer() == EDGE_N )
            {
                tmpSegm.SetLayer( UNDEFINED_LAYER );
                type_cell |= CELL_is_EDGE;
            }

            tmpSegm.SetStart( DrawSegm->GetStart() );
            tmpSegm.SetEnd(   DrawSegm->GetEnd() );
            tmpSegm.SetShape( DrawSegm->GetShape() );
            tmpSegm.SetWidth( DrawSegm->GetWidth() );
            tmpSegm.m_Param = DrawSegm->GetAngle();
            tmpSegm.SetNet( -1 );

            TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL );
        }
        break;

        case PCB_TEXT_T:
        {
            TEXTE_PCB* PtText;
            PtText = (TEXTE_PCB*) item;

            if( PtText->GetText().Length() == 0 )
                break;

            EDA_RECT textbox = PtText->GetTextBox( -1 );
            ux0 = textbox.GetX();
            uy0 = textbox.GetY();
            dx  = textbox.GetWidth();
            dy  = textbox.GetHeight();

            /* Put bounding box (rectangle) on matrix */
            dx /= 2;
            dy /= 2;

            ux1 = ux0 + dx;
            uy1 = uy0 + dy;

            ux0 -= dx;
            uy0 -= dy;

            layerMask = GetLayerMask( PtText->GetLayer() );

            TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge,
                                  uy1 + marge, PtText->GetOrientation(),
                                  layerMask, HOLE, WRITE_CELL );

            TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge,
                                  ux1 + via_marge, uy1 + via_marge,
                                  PtText->GetOrientation(),
                                  layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL );
        }
        break;

        default:
            break;
        }
    }

    /* Put tracks and vias on matrix */
    for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
    {
        if( net_code == track->GetNet() )
            continue;

        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }
}
Beispiel #4
0
/* Insert the new track created in the list of tracks.
 * amend the points of beginning and end of the track so that they are
 * connected
 * Center on pads even if they are off grid.
 */
static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
{
    if( g_FirstTrackSegment == NULL )
        return;

    int dx0, dy0, dx1, dy1;
    int marge, via_marge;
    EDA_DRAW_PANEL* panel = pcbframe->GetCanvas();
    PCB_SCREEN* screen = pcbframe->GetScreen();

    marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );
    via_marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentViaSize() / 2 );

    dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x;
    dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y;

    // Place on center of pad if off grid.
    dx0 = pt_cur_ch->m_PadStart->GetPosition().x - g_CurrentTrackSegment->GetStart().x;
    dy0 = pt_cur_ch->m_PadStart->GetPosition().y - g_CurrentTrackSegment->GetStart().y;

    // If aligned, change the origin point.
    if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
    {
        g_CurrentTrackSegment->SetEnd( pt_cur_ch->m_PadStart->GetPosition() );
    }
    else
    {
        TRACK* newTrack = (TRACK*)g_CurrentTrackSegment->Clone();

        newTrack->SetEnd( pt_cur_ch->m_PadStart->GetPosition() );
        newTrack->SetStart( g_CurrentTrackSegment->GetEnd() );

        g_CurrentTrackList.PushBack( newTrack );
    }

    g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment,
            ENDPOINT_START );

    if( g_FirstTrackSegment->start )
        g_FirstTrackSegment->SetState( BEGIN_ONPAD, true );

    g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment,
            ENDPOINT_END );

    if( g_CurrentTrackSegment->end )
        g_CurrentTrackSegment->SetState( END_ONPAD, true );

    // Out the new track on the matrix board
    for( TRACK* track = g_FirstTrackSegment; track; track = track->Next() )
    {
        TraceSegmentPcb( track, HOLE, marge, WRITE_CELL );
        TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL );
    }

    // Insert new segments in  real board
    int    netcode    = g_FirstTrackSegment->GetNetCode();
    TRACK* firstTrack = g_FirstTrackSegment;
    int    newCount   = g_CurrentTrackList.GetCount();

    // Put entire new current segment list in BOARD
    TRACK* track;
    TRACK* insertBeforeMe = g_CurrentTrackSegment->GetBestInsertPoint( pcbframe->GetBoard() );

    while( ( track = g_CurrentTrackList.PopFront() ) != NULL )
    {
        ITEM_PICKER picker( track, UR_NEW );
        s_ItemsListPicker.PushItem( picker );
        pcbframe->GetBoard()->m_Track.Insert( track, insertBeforeMe );
    }

    DrawTraces( panel, DC, firstTrack, newCount, GR_OR );

    pcbframe->TestNetConnection( DC, netcode );

    screen->SetModify();
}
Beispiel #5
0
/* Insere la nouvelle piste creee dans la liste standard des pistes.
	Modifie les points de debut et fin de piste pour qu'ils soient relies
	au centre des pads corresponadants, meme hors grille
*/
static void Place_Piste_en_Buffer(WinEDA_PcbFrame * pcbframe, wxDC * DC)
{
TRACK* pt_track;
int dx0, dy0, dx1,dy1;
int marge, via_marge;
WinEDA_DrawPanel * panel = pcbframe->DrawPanel;

	marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth /2);
	via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize /2);

	/* tst point d'arrivee : doit etre sur pad start */

	dx1 = g_CurrentTrackSegment->m_End.x - g_CurrentTrackSegment->m_Start.x;
	dy1 = g_CurrentTrackSegment->m_End.y - g_CurrentTrackSegment->m_Start.y;
	/* Replacement sur le centre du pad si hors grille */

	dx0 = pt_cur_ch->pad_start->m_Pos.x - g_CurrentTrackSegment->m_Start.x;
	dy0 = pt_cur_ch->pad_start->m_Pos.y - g_CurrentTrackSegment->m_Start.y;

	/* si aligne: modif du point origine */
	if(abs(dx0*dy1) == abs(dx1*dy0) ) /* Alignes ! */
		{
		g_CurrentTrackSegment->m_End.x = pt_cur_ch->pad_start->m_Pos.x;
		g_CurrentTrackSegment->m_End.y = pt_cur_ch->pad_start->m_Pos.y;
		}
	else /* Creation d'un segment suppl raccord */
		{
		TRACK * NewTrack = g_CurrentTrackSegment->Copy();
		NewTrack->Insert(pcbframe->m_Pcb, g_CurrentTrackSegment);

		NewTrack->m_End.x = pt_cur_ch->pad_start->m_Pos.x;
		NewTrack->m_End.y = pt_cur_ch->pad_start->m_Pos.y;
		NewTrack->m_Start.x = g_CurrentTrackSegment->m_End.x;
		NewTrack->m_Start.y = g_CurrentTrackSegment->m_End.y;

		g_CurrentTrackSegment = NewTrack; g_TrackSegmentCount++;
		}


	g_FirstTrackSegment->start = Locate_Pad_Connecte(pcbframe->m_Pcb, g_FirstTrackSegment,START);
	if(g_FirstTrackSegment->start) g_FirstTrackSegment->SetState(BEGIN_ONPAD,ON);

	g_CurrentTrackSegment->end = Locate_Pad_Connecte(pcbframe->m_Pcb, g_CurrentTrackSegment,END);
	if(g_CurrentTrackSegment->end) g_CurrentTrackSegment->SetState(END_ONPAD,ON);

	/* recherche de la zone de rangement et insertion de la nouvelle piste */
	pt_track = g_FirstTrackSegment->GetBestInsertPoint(pcbframe->m_Pcb);
	g_FirstTrackSegment->Insert(pcbframe->m_Pcb, pt_track);

	Trace_Une_Piste(panel, DC, g_FirstTrackSegment,g_TrackSegmentCount,GR_OR) ;

	pcbframe->test_1_net_connexion(DC, g_FirstTrackSegment->m_NetCode );

	/* Trace de la forme exacte de la piste en BOARD */
	for ( pt_track = g_FirstTrackSegment; ; pt_track = (TRACK*)pt_track->Pnext)
		{
		TraceSegmentPcb(pcbframe->m_Pcb,pt_track,HOLE,marge,WRITE_CELL);
		TraceSegmentPcb(pcbframe->m_Pcb,pt_track,VIA_IMPOSSIBLE,via_marge,WRITE_OR_CELL);
		if(pt_track == g_CurrentTrackSegment ) break;
		}

	ActiveScreen->SetModify();
}