/********************************************************/ /**** Routine de lecture et visu d'un fichier GERBER ****/ /********************************************************/ #include "fctsys.h" #include "common.h" #include "gerbview.h" #include "pcbplot.h" #include "protos.h" #define DEFAULT_SIZE 100 /* Format Gerber : NOTES : Fonctions preparatoires: Gn = G01 interpolation lineaire ( trace de droites ) G02,G20,G21 Interpolation circulaire , sens trigo < 0 G03,G30,G31 Interpolation circulaire , sens trigo > 0 G04 commentaire G06 Interpolation parabolique G07 Interpolation cubique G10 interpolation lineaire ( echelle 10x ) G11 interpolation lineaire ( echelle 0.1x ) G12 interpolation lineaire ( echelle 0.01x ) G52 plot symbole reference par Dnn code G53 plot symbole reference par Dnn ; symbole tourne de -90 degres G54 Selection d'outil G55 Mode exposition photo G56 plot symbole reference par Dnn A code G57 affiche le symbole reference sur la console G58 plot et affiche le symbole reference sur la console G60 interpolation lineaire ( echelle 100x ) G70 Unites = Inches G71 Unites = Millimetres G74 supprime interpolation circulaire sur 360 degre, revient a G01 G75 Active interpolation circulaire sur 360 degre G90 Mode Coordonnees absolues G91 Mode Coordonnees Relatives Coordonnees X,Y X,Y sont suivies de + ou - et de m+n chiffres (non separes) m = partie entiere n = partie apres la virgule formats classiques : m = 2, n = 3 (format 2.3) m = 3, n = 4 (format 3.4) ex: G__ X00345Y-06123 D__* Outils et D_CODES numero d'outil ( identification des formes ) 1 a 99 (classique) 1 a 999 D_CODES: D01 ... D9 = codes d'action: D01 = activation de lumiere (baisser de plume) lors du déplacement D02 = extinction de lumiere (lever de plume) lors du déplacement D03 = Flash D09 = VAPE Flash D10 ... = Indentification d'outils ( d'ouvertures ) */ /*********************************/ /* class GERBER_Descr : Methodes */ /*********************************/ GERBER_Descr::GERBER_Descr(int layer) { int ii; m_Layer = layer; // Layer Number m_Selected_Tool = FIRST_DCODE; ResetDefaultValues(); for ( ii = 0; ii <= MAX_TOOLS; ii++ ) m_Aperture_List[ii] = new D_CODE(ii + FIRST_DCODE); } GERBER_Descr::~GERBER_Descr(void) { int ii; if (m_Aperture_List ) { for ( ii = 0; ii < MAX_TOOLS; ii++) { delete m_Aperture_List[ii]; m_Aperture_List[ii] = NULL; } } } /******************************************/ void GERBER_Descr::ResetDefaultValues(void) /******************************************/ { m_Parent = NULL; m_Pback = NULL; m_Pnext = NULL; m_FileName.Empty(); m_Name = wxT("no name"); // Layer name m_LayerNegative = FALSE; // TRUE = Negative Layer m_ImageNegative = FALSE; // TRUE = Negative image m_GerbMetric = FALSE; // FALSE = Inches, TRUE = metric m_Relative = FALSE; // FALSE = absolute Coord, RUE = relative Coord m_NoTrailingZeros = FALSE; // True: zeros a droite supprimés m_MirorA = FALSE; // True: miror / axe A (X) m_MirorB = FALSE; // True: miror / axe B (Y) m_As_DCode = FALSE; // TRUE = DCodes in file (FALSE = no DCode-> // separate DCode file m_Offset.x = m_Offset.y = 0; // Coord Offset m_FmtScale.x = m_FmtScale.y = g_Default_GERBER_Format % 10; m_FmtLen.x = m_FmtLen.y = m_FmtScale.x + (g_Default_GERBER_Format / 10); m_LayerScale.x = m_LayerScale.y = 1.0; // scale (X et Y) pour cette layer m_Rotation = 0; m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ. m_360Arc_enbl = FALSE; // 360 deg circular interpolation disable m_Current_Tool = 0; // Current Tool (Dcode) number selected m_CommandState = 0; // donne l'etat de l'analyse des commandes gerber m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord for plot m_PreviousPos.x = m_PreviousPos.y = 0; // old current specified coord for plot m_IJPos.x = m_IJPos.y = 0; // current centre coord for plot arcs & circles m_Current_File = NULL; // File to read m_FilesPtr = 0; m_Transform[0][0] = m_Transform[1][1] = 1; m_Transform[0][1] = m_Transform[1][0] = 0; // Rotation/mirror = Normal m_PolygonFillMode = FALSE; m_PolygonFillModeState = 0; } /********************************************/ int GERBER_Descr::ReturnUsedDcodeNumber(void) /********************************************/ { int ii, jj; jj = 0; if (m_Aperture_List ) { for ( ii = 0; ii < MAX_TOOLS; ii++) { if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined ) jj++; } } return jj; } /******************************/ void GERBER_Descr::InitToolTable(void) /******************************/ /* Creation du tableau des MAX_TOOLS DCodes utilisables, si il n'existe pas, et Init des DCodes à une valeur raisonnable */ { int count; /* Init du buffer des D_CODES a des valeurs raisonnables */ for (count = 0 ; count < MAX_TOOLS ; count++) { if (m_Aperture_List[count] == NULL ) continue; m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE; m_Aperture_List[count]->Clear_D_CODE_Data(); } } /*************************/ /* Class DCODE: methodes */ /*************************/ /* Variables locales : */ /* Routines Locales */ D_CODE::D_CODE(int num_dcode) { m_Num_Dcode = num_dcode; Clear_D_CODE_Data(); } D_CODE::~D_CODE(void) { } void D_CODE::Clear_D_CODE_Data(void) { m_Size.x = DEFAULT_SIZE; m_Size.y = DEFAULT_SIZE; m_Shape= GERB_CIRCLE; m_Drill.x = m_Drill.y = 0; m_DrillShape = 0; m_InUse = FALSE; m_Defined = FALSE; } /******************************************************************************/ int WinEDA_GerberFrame::Read_D_Code_File( const wxString & D_Code_FullFileName) /******************************************************************************/ /* Routine de Lecture d'un fichier de D Codes. Accepte format standard ou ALSPCB un ';' demarre un commentaire. Format Standard: tool, Horiz, Vert, drill, vitesse, acc. ,Type ; [DCODE (commentaire)] ex: 1, 12, 12, 0, 0, 0, 3 ; D10 Format: Ver , Hor , Type , Tool [,Drill] ex: 0.012, 0.012, L , D10 Classe les caract en buf_tmp sous forme de tableau de structures D_CODE. Retourne: < 0 si erreur: -1 = Fichier non trouve -2 = Erreur lecture fichier 0 si pas de nom de fichier (inits seules) 1 si OK */ { int current_Dcode, ii, dcode_scale; char* ptcar; int dimH, dimV, drill, type_outil, dummy; float fdimH, fdimV, fdrill; char c_type_outil[256]; char Line[1024]; wxString msg; D_CODE * pt_Dcode; FILE * dest; int layer = GetScreen()->m_Active_Layer; D_CODE ** ListeDCode; if ( g_GERBER_Descr_List[layer] == NULL ) { g_GERBER_Descr_List[layer] = new GERBER_Descr(layer); } /* Mise a jour de l'echelle gerber : */ dcode_scale = 10; /* ici unit dcode = mil, unit interne = 0.1 mil -> 1 unite dcode = 10 unit PCB */ current_Dcode = 0; if ( D_Code_FullFileName.IsEmpty() ) return 0; dest = wxFopen(D_Code_FullFileName, wxT("rt") ); if (dest == 0) { msg = _("File ") + D_Code_FullFileName + _(" not found"); DisplayError(this, msg, 10); return -1; } g_GERBER_Descr_List[layer]->InitToolTable(); ListeDCode = g_GERBER_Descr_List[layer]->m_Aperture_List; while( fgets(Line,255,dest) != NULL) { if (*Line == ';') continue; /* Commentaire */ if (strlen(Line) < 10 ) continue ; /* Probablemant ligne vide */ pt_Dcode = NULL; current_Dcode = 0; /* Determination du type de fichier D_Code */ ptcar = Line ; ii = 0 ; while( *ptcar ) if (*(ptcar++) == ',') ii++ ; if (ii >= 6 ) /* valeurs en mils */ { sscanf(Line,"%d,%d,%d,%d,%d,%d,%d",&ii, &dimH, &dimV, &drill, &dummy,&dummy, &type_outil); dimH = (int)( (dimH * dcode_scale) + 0.5) ; dimV = (int)( (dimV * dcode_scale) + 0.5) ; drill = (int)( (drill * dcode_scale) + 0.5); if ( ii < 1 ) ii = 1; current_Dcode = ii-1 + FIRST_DCODE; } else /* valeurs en inches a convertir en mils */ { fdrill = 0 ; current_Dcode = 0 ; fdrill = 0 ; sscanf(Line,"%f,%f,%1s",&fdimV, &fdimH, c_type_outil); ptcar = Line ; while( *ptcar ) { if (*ptcar == 'D') { sscanf(ptcar+1,"%d,%f", ¤t_Dcode,&fdrill); break ; } else ptcar++ ; } dimH = (int)( (fdimH * dcode_scale * 1000) + 0.5); dimV = (int)( (fdimV * dcode_scale * 1000) + 0.5); drill = (int)( (fdrill * dcode_scale * 1000) + 0.5); type_outil = -1 ; if(c_type_outil[0] == 'L') type_outil = GERB_LINE; if(c_type_outil[0] == 'R') type_outil = GERB_RECT; if(c_type_outil[0] == 'C') type_outil = GERB_CIRCLE; if(c_type_outil[0] == 'O') type_outil = GERB_OVALE; if(type_outil == -1) {fclose(dest); return(-2);} } /* Mise a jour de la liste des d_codes si valeurs lues coherentes*/ if (current_Dcode < FIRST_DCODE ) continue; if (current_Dcode >= MAX_TOOLS ) continue; pt_Dcode = ReturnToolDescr(layer, current_Dcode); pt_Dcode->m_Size.x = dimH; pt_Dcode->m_Size.y = dimV; pt_Dcode->m_Shape = type_outil; pt_Dcode->m_Drill.x = pt_Dcode->m_Drill.y = drill; pt_Dcode->m_Defined = TRUE; } fclose(dest) ; return(1); } /***************************************************/ void WinEDA_GerberFrame::CopyDCodesSizeToItems(void) /***************************************************/ /* Set Size Items (Lines, Flashes) from DCodes List */ { TRACK * track; D_CODE * pt_Dcode; /* Pointeur sur le D code*/ track = m_Pcb->m_Track; for ( ; track != NULL ; track = (TRACK*) track->Pnext ) { pt_Dcode = ReturnToolDescr(track->GetLayer(), track->m_NetCode); pt_Dcode->m_InUse = TRUE; if ( // Line Item (track->m_Shape == S_SEGMENT ) || /* segment rectiligne */ (track->m_Shape == S_RECT ) || /* segment forme rect (i.e. bouts non arrondis) */ (track->m_Shape == S_ARC ) || /* segment en arc de cercle (bouts arrondis)*/ (track->m_Shape == S_CIRCLE ) || /* segment en cercle (anneau)*/ (track->m_Shape == S_ARC_RECT ) /* segment en arc de cercle (bouts droits) (GERBER)*/ ) { track->m_Width = pt_Dcode->m_Size.x; } else // Spots ( Flashed Items ) { int width, len; wxSize size = pt_Dcode->m_Size; width = MIN( size.x, size.y ); len = MAX( size.x, size.y ) - width; track->m_Width = width; track->m_Start.x = (track->m_Start.x + track->m_End.x) / 2; track->m_Start.y = (track->m_Start.y + track->m_End.y) / 2; track->m_End = track->m_Start; // m_Start = m_End = Spot center switch (pt_Dcode->m_Shape) { case GERB_LINE : // ne devrait pas etre utilisé ici case GERB_CIRCLE : /* spot rond (for GERBER)*/ track->m_Shape = S_SPOT_CIRCLE; break ; case GERB_OVALE : /* spot ovale (for GERBER)*/ track->m_Shape = S_SPOT_OVALE; break ; default: /* spot rect (for GERBER)*/ track->m_Shape = S_SPOT_RECT; break ; } len >>= 1; if ( size.x > size.y ) { track->m_Start.x -= len; track->m_End.x += len; } else { track->m_Start.y -= len; track->m_End.y += len; } } } } /*********************************************************/ D_CODE * ReturnToolDescr(int layer, int Dcode, int * index) /*********************************************************/ /* Retourne un pointeur sur la description de l'outil DCode de reference Dcode (rappel : Dcode >= 10) */ { GERBER_Descr * DcodeList = g_GERBER_Descr_List[layer]; D_CODE * pt_dcode = NULL; if (index) *index = 0; if ( DcodeList && Dcode >= FIRST_DCODE && Dcode < MAX_TOOLS) { pt_dcode = DcodeList->m_Aperture_List[Dcode - FIRST_DCODE]; if ( index ) *index = Dcode - FIRST_DCODE + 1; } return pt_dcode; } /************************************************/ void WinEDA_GerberFrame::Liste_D_Codes(wxDC * DC) /************************************************/ { int ii, jj; D_CODE * pt_D_code ; wxString Line; WinEDA_TextFrame * List; int scale = 10000; int curr_layer = GetScreen()->m_Active_Layer; int layer; GERBER_Descr * DcodeList; /* Construction de la liste des messages */ List = new WinEDA_TextFrame(this, _("List D-Codes")); for (layer = 0; layer < 32; layer++ ) { DcodeList = g_GERBER_Descr_List[layer]; if ( DcodeList == NULL ) continue; if ( DcodeList->ReturnUsedDcodeNumber() == 0 ) continue; if (layer == curr_layer ) Line.Printf( wxT("*** Active layer (%2.2d) ***"), layer+1); else Line.Printf( wxT("*** layer %2.2d ***"), layer+1); List->Append(Line); for ( ii = 0, jj = 1 ; ii < MAX_TOOLS ; ii++ ) { pt_D_code = DcodeList->m_Aperture_List[ii] ; if ( pt_D_code == NULL ) continue; if ( !pt_D_code->m_InUse && !pt_D_code->m_Defined ) continue; Line.Printf( wxT( "tool %2.2d: D%2.2d V %2.4f H %2.4f %s"), jj, pt_D_code->m_Num_Dcode, (float)pt_D_code->m_Size.y /scale, (float)pt_D_code->m_Size.x /scale, g_GERBER_Tool_Type[pt_D_code->m_Shape] ); if ( ! pt_D_code->m_Defined ) Line += wxT(" ?"); if ( ! pt_D_code->m_InUse ) Line += wxT(" *"); List->Append(Line); jj++; } } ii = List->ShowModal(); List->Destroy(); if (ii < 0) return; #if 0 // Mise en surbrillance des éléments correspondant au DCode sélectionné if(Etat_Surbrillance) Hight_Light(DrawPanel, DC); net_code_Surbrillance = (GetScreen()->m_Active_Layer<< 16) + ii; Hight_Light(DrawPanel, DC); #endif }