/* Fichier BOARD.CPP : functions for autorouting */ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "confirm.h" #include "pcbnew.h" #include "autorout.h" #include "zones.h" #include "cell.h" #include "protos.h" /* routines externes : */ /* Routines definies ici: */ int Build_Work( BOARD* Pcb ); void PlaceCells( BOARD* Pcb, int net_code, int flag ); int InitBoard(); BoardCell GetCell( int, int, int ); void SetCell( int row, int col, int side, BoardCell x ); void OrCell( int, int, int, BoardCell ); void AndCell( int, int, int, BoardCell ); void AddCell( int, int, int, BoardCell ); void XorCell( int, int, int, BoardCell ); void AddCell( int, int, int, BoardCell ); DistCell GetDist( int, int, int ); void SetDist( int, int, int, DistCell ); int GetDir( int, int, int ); void SetDir( int, int, int, int ); /*****************************************************************/ bool ComputeMatriceSize( WinEDA_BasePcbFrame* frame, int g_GridRoutingSize ) /*****************************************************************/ /* * Calcule Nrows et Ncols, dimensions de la matrice de representation du BOARD * pour les routages automatiques et calculs de zone */ { BOARD* pcb = frame->GetBoard(); pcb->ComputeBoundaryBox(); /* The boundary box must have its start point on routing grid: */ pcb->m_BoundaryBox.m_Pos.x -= pcb->m_BoundaryBox.m_Pos.x % g_GridRoutingSize; pcb->m_BoundaryBox.m_Pos.y -= pcb->m_BoundaryBox.m_Pos.y % g_GridRoutingSize; /* The boundary box must have its end point on routing grid: */ wxPoint end = pcb->m_BoundaryBox.GetEnd(); end.x -= end.x % g_GridRoutingSize; end.x += g_GridRoutingSize; end.y -= end.y % g_GridRoutingSize; end.y += g_GridRoutingSize; pcb->m_BoundaryBox.SetEnd( end ); Nrows = pcb->m_BoundaryBox.m_Size.y / g_GridRoutingSize; Ncols = pcb->m_BoundaryBox.m_Size.x / g_GridRoutingSize; /* get a small margin for memory allocation: */ Ncols += 2; Nrows += 2; return TRUE; } /*******************/ /* class BOARDHEAD */ /*******************/ BOARDHEAD::BOARDHEAD() { m_BoardSide[0] = m_BoardSide[1] = NULL; m_DistSide[0] = m_DistSide[1] = NULL; m_DirSide[0] = m_DirSide[1] = NULL; m_InitBoardDone = FALSE; m_Layers = 2; m_Nrows = m_Ncols = 0; m_MemSize = 0; } BOARDHEAD::~BOARDHEAD() { } /******************************/ int BOARDHEAD::InitBoard() /*****************************/ /* initialize the data structures * retourne la taille RAM utilisee, ou -1 si defaut */ { int ii, kk; if( Nrows <= 0 || Ncols <= 0 ) return 0; m_Nrows = Nrows; m_Ncols = Ncols; m_InitBoardDone = TRUE; /* we have been called */ ii = (Nrows + 1) * (Ncols + 1); for( kk = 0; kk < m_Layers; kk++ ) { m_BoardSide[kk] = NULL; m_DistSide[kk] = NULL; m_DirSide[kk] = NULL; /* allocate Board & initialize everything to empty */ m_BoardSide[kk] = (BoardCell*) MyZMalloc( ii * sizeof(BoardCell) ); if( m_BoardSide[kk] == NULL ) return -1; /***** allocate Distances *****/ m_DistSide[kk] = (DistCell*) MyZMalloc( ii * sizeof(DistCell) ); if( m_DistSide[kk] == NULL ) return -1; /***** allocate Dir (chars) *****/ m_DirSide[kk] = (char*) MyZMalloc( ii ); if( m_DirSide[kk] == NULL ) return -1; } m_MemSize = m_Layers * ii * ( sizeof(BoardCell) + sizeof(DistCell) + sizeof(char) ); return m_MemSize; } /*********************************/ void BOARDHEAD::UnInitBoard() /*********************************/ /* deallocation de la memoire */ { int ii; m_InitBoardDone = FALSE; for( ii = 0; ii < 2; ii++ ) { /***** de-allocate Dir (chars) *****/ if( m_DirSide[ii] ) { MyFree( m_DirSide[ii] ); m_DirSide[ii] = NULL; } /***** de-allocate Distances *****/ if( m_DistSide[ii] ) { MyFree( m_DistSide[ii] ); m_DistSide[ii] = NULL; } /**** de-allocate Board *****/ if( m_BoardSide[ii] ) { MyFree( m_BoardSide[ii] ); m_BoardSide[ii] = NULL; } } m_Nrows = m_Ncols = 0; } /*****************************************************/ void PlaceCells( BOARD* aPcb, int net_code, int flag ) /*****************************************************/ /* 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 */ { 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 // ///////////////////////////////////// for( unsigned i=0; i < aPcb->GetPadsCount(); ++i ) { D_PAD* pad = aPcb->m_NetInfo->GetPad(i); if( net_code != pad->GetNet() || (flag & FORCE_PADS) ) { Place_1_Pad_Board( aPcb, pad, HOLE, marge, WRITE_CELL ); } Place_1_Pad_Board( aPcb, pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } /////////////////////////////////////////////// // Placement des elements de modules sur PCB // /////////////////////////////////////////////// for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( BOARD_ITEM* item = module->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case TYPE_EDGE_MODULE: { EDGE_MODULE* edge = (EDGE_MODULE*) item; TRACK* TmpSegm = new TRACK( NULL ); TmpSegm->SetLayer( edge->GetLayer() ); if( TmpSegm->GetLayer() == EDGE_N ) TmpSegm->SetLayer( -1 ); TmpSegm->m_Start = edge->m_Start; TmpSegm->m_End = edge->m_End; TmpSegm->m_Shape = edge->m_Shape; TmpSegm->m_Width = edge->m_Width; TmpSegm->m_Param = edge->m_Angle; TmpSegm->SetNet( -1 ); TraceSegmentPcb( aPcb, TmpSegm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( aPcb, TmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); delete TmpSegm; } break; default: break; } } } //////////////////////////////////////////// // Placement des contours et segments PCB // //////////////////////////////////////////// for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case TYPE_DRAWSEGMENT: { DRAWSEGMENT* DrawSegm; int type_cell = HOLE; TRACK* TmpSegm = new TRACK( NULL ); DrawSegm = (DRAWSEGMENT*) item; TmpSegm->SetLayer( DrawSegm->GetLayer() ); if( DrawSegm->GetLayer() == EDGE_N ) { TmpSegm->SetLayer( -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->SetNet( -1 ); TraceSegmentPcb( aPcb, TmpSegm, type_cell, marge, WRITE_CELL ); // TraceSegmentPcb(Pcb, TmpSegm, VIA_IMPOSSIBLE, via_marge,WRITE_OR_CELL ); delete TmpSegm; } break; case TYPE_TEXTE: { TEXTE_PCB* PtText; PtText = (TEXTE_PCB*) item; if( PtText->GetLength() == 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; /* dx et dy = demi dimensionx X et Y */ ux1 = ux0 + dx; uy1 = uy0 + dy; ux0 -= dx; uy0 -= dy; masque_layer = g_TabOneLayerMask[PtText->GetLayer()]; TraceFilledRectangle( aPcb, ux0 - marge, uy0 - marge, ux1 + marge, uy1 + marge, (int) (PtText->m_Orient), masque_layer, HOLE, WRITE_CELL ); TraceFilledRectangle( aPcb, 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; } } /* Put tracks and vias on matrix */ for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) { if( net_code == track->GetNet() ) continue; TraceSegmentPcb( aPcb, track, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( aPcb, track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Put zone filling on matrix for( SEGZONE* zone = aPcb->m_Zone; zone; zone = zone->Next() ) { if( net_code == zone->GetNet() ) continue; TraceSegmentPcb( aPcb, zone, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( aPcb, zone, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } } /******************************************************/ int Build_Work( BOARD* Pcb ) /*****************************************************/ /* Build liste conn */ { RATSNEST_ITEM* pt_rats; D_PAD* pt_pad; int r1, r2, c1, c2, current_net_code; RATSNEST_ITEM* pt_ch; int demi_pas = g_GridRoutingSize / 2; wxString msg; InitWork(); /* clear work list */ Ntotal = 0; for( unsigned ii = 0; ii < Pcb->GetRatsnestsCount(); ii++ ) { pt_rats = &Pcb->m_FullRatsnest[ii]; /* On ne route que les chevelus actifs et routables */ if( (pt_rats->m_Status & CH_ACTIF) == 0 ) continue; if( pt_rats->m_Status & CH_UNROUTABLE ) continue; if( (pt_rats->m_Status & CH_ROUTE_REQ) == 0 ) continue; pt_pad = pt_rats->m_PadStart; current_net_code = pt_pad->GetNet(); pt_ch = pt_rats; r1 = (pt_pad->GetPosition().y - Pcb->m_BoundaryBox.m_Pos.y + demi_pas ) / g_GridRoutingSize; if( r1 < 0 || r1 >= Nrows ) { msg.Printf( wxT( "erreur : row = %d ( padY %d pcbY %d) " ), r1, pt_pad->GetPosition().y, Pcb->m_BoundaryBox.m_Pos.y ); DisplayError( NULL, msg ); return 0; } c1 = (pt_pad->GetPosition().x - Pcb->m_BoundaryBox.m_Pos.x + demi_pas ) / g_GridRoutingSize; if( c1 < 0 || c1 >= Ncols ) { msg.Printf( wxT( "erreur : col = %d ( padX %d pcbX %d) " ), c1, pt_pad->GetPosition().x, Pcb->m_BoundaryBox.m_Pos.x ); DisplayError( NULL, msg ); return 0; } pt_pad = pt_rats->m_PadEnd; r2 = (pt_pad->GetPosition().y - Pcb->m_BoundaryBox.m_Pos.y + demi_pas ) / g_GridRoutingSize; if( r2 < 0 || r2 >= Nrows ) { msg.Printf( wxT( "erreur : row = %d ( padY %d pcbY %d) " ), r2, pt_pad->GetPosition().y, Pcb->m_BoundaryBox.m_Pos.y ); DisplayError( NULL, msg ); return 0; } c2 = (pt_pad->GetPosition().x - Pcb->m_BoundaryBox.m_Pos.x + demi_pas ) / g_GridRoutingSize; if( c2 < 0 || c2 >= Ncols ) { msg.Printf( wxT( "erreur : col = %d ( padX %d pcbX %d) " ), c2, pt_pad->GetPosition().x, Pcb->m_BoundaryBox.m_Pos.x ); DisplayError( NULL, msg ); return 0; } SetWork( r1, c1, current_net_code, r2, c2, pt_ch, 0 ); Ntotal++; } SortWork(); return Ntotal; } /*******************************************/ BoardCell GetCell( int row, int col, int side ) /*******************************************/ /* fetch board cell : */ { BoardCell* p; p = Board.m_BoardSide[side]; return p[row * Ncols + col]; } /************************************************/ /* void SetCell(int r,int c,int s,BoardCell x ) */ /************************************************/ /* store board cell */ void SetCell( int row, int col, int side, BoardCell x ) { BoardCell* p; p = Board.m_BoardSide[side]; p[row * Ncols + col] = x; } /******************************************/ /* void OrCell(int r,int c,int s,BoardCell x ) */ /******************************************/ void OrCell( int r, int c, int s, BoardCell x ) { BoardCell* p; p = Board.m_BoardSide[s]; p[r * Ncols + c] |= x; } /******************************************/ /* void XorCell(int r,int c,int s,BoardCell x ) */ /******************************************/ void XorCell( int r, int c, int s, BoardCell x ) { BoardCell* p; p = Board.m_BoardSide[s]; p[r * Ncols + c] ^= x; } /************************************************/ /* void AndCell(int r,int c,int s,BoardCell x ) */ /************************************************/ void AndCell( int r, int c, int s, BoardCell x ) { BoardCell* p; p = Board.m_BoardSide[s]; p[r * Ncols + c] &= x; } /************************************************/ /* void AddCell(int r,int c,int s,BoardCell x ) */ /************************************************/ void AddCell( int r, int c, int s, BoardCell x ) { BoardCell* p; p = Board.m_BoardSide[s]; p[r * Ncols + c] += x; } /****************************************/ /* DistCell GetDist(int r,int c,int s ) */ /****************************************/ /* fetch distance cell */ DistCell GetDist( int r, int c, int s ) /* fetch distance cell */ { DistCell* p; p = Board.m_DistSide[s]; return p[r * Ncols + c]; } /***********************************************/ /* void SetDist(int r,int c,int s,DistCell x ) */ /***********************************************/ /* store distance cell */ void SetDist( int r, int c, int s, DistCell x ) { DistCell* p; p = Board.m_DistSide[s]; p[r * Ncols + c] = x; } /**********************************/ /* int GetDir(int r,int c,int s ) */ /**********************************/ /* fetch direction cell */ int GetDir( int r, int c, int s ) { char* p; p = Board.m_DirSide[s]; return (int) (p[r * Ncols + c]); } /*****************************************/ /* void SetDir(int r,int c,int s,int x ) */ /*****************************************/ /* store direction cell */ void SetDir( int r, int c, int s, int x ) { char* p; p = Board.m_DirSide[s]; p[r * Ncols + c] = (char) x; }