/********************************************************/ /**** Routine de lecture et visu d'un fichier GERBER ****/ /********************************************************/ #include "fctsys.h" #include "common.h" #include "gerbview.h" #include "pcbplot.h" #include "protos.h" /* 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 * D51 = precede par G54 -> Select VAPE * * D10 ... D255 = Indentification d'outils ( d'ouvertures ) * Ne sont pas tj dans l'ordre ( voir tableau dans PCBPLOT.H) */ /* Variables locales : */ /* Routines Locales */ /* 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 ALSPCB: * 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 * Rang de D_code maxi lu ( nbr de dcodes ) * * * Representation interne: * * Les lignes sont représentées par des TRACKS standards * Les Flash sont représentées par des DRAWSEGMENTS * - ronds ou ovales: DRAWSEGMENTS * - rectangles: DRAWSEGMENTS * la reference aux D-CODES est placée dans le membre GetNet() */ /********************************************************/ bool WinEDA_GerberFrame::Read_GERBER_File( wxDC* DC, const wxString& GERBER_FullFileName, const wxString& D_Code_FullFileName ) /********************************************************/ /* Read a gerber file (RS274D or RS274X format). * Normal format: * Imperial * Absolute * end of block = * * CrLf after each command * G codes repetes */ { int G_commande = 0, D_commande = 0; /* command number for G et D commands (like G04 or D02) */ char Line[4000]; /* Buffer to read 1 line of the gerber file * warning: some files can have very long lines, so the buffer must be large */ wxString msg; char* text; int layer; /* current layer used in gerbview */ GERBER_Descr* gerber_layer; wxPoint pos; int error = 0; layer = GetScreen()->m_Active_Layer; if( g_GERBER_Descr_List[layer] == NULL ) { g_GERBER_Descr_List[layer] = new GERBER_Descr( layer ); } gerber_layer = g_GERBER_Descr_List[layer]; /* Set the gerber scale: */ gerber_layer->ResetDefaultValues(); /* Read the gerber file */ gerber_layer->m_Current_File = wxFopen( GERBER_FullFileName, wxT( "rt" ) ); if( gerber_layer->m_Current_File == 0 ) { msg = _( "File " ) + GERBER_FullFileName + _( " not found" ); DisplayError( this, msg, 10 ); return FALSE; } gerber_layer->m_FileName = GERBER_FullFileName; wxSetWorkingDirectory( wxPathOnly( GERBER_FullFileName ) ); wxBusyCursor show_wait; setlocale( LC_NUMERIC, "C" ); while( TRUE ) { if( fgets( Line, sizeof(Line) - 1, gerber_layer->m_Current_File ) == NULL ) // E.O.F { if( gerber_layer->m_FilesPtr == 0 ) break; fclose( gerber_layer->m_Current_File ); gerber_layer->m_FilesPtr--; gerber_layer->m_Current_File = gerber_layer->m_FilesList[gerber_layer->m_FilesPtr]; continue; } text = StrPurge( Line ); while( text && *text ) { switch( *text ) { case ' ': case '\r': case '\n': text++; break; case '*': // End commande gerber_layer->m_CommandState = END_BLOCK; text++; break; case 'M': // End file gerber_layer->m_CommandState = CMD_IDLE; while( *text ) text++; break; case 'G': /* Line type Gxx : command */ G_commande = gerber_layer->ReturnGCodeNumber( text ); gerber_layer->Execute_G_Command( text, G_commande ); break; case 'D': /* Line type Dxx : Tool selection (xx > 0) or command if xx = 0..9*/ D_commande = gerber_layer->ReturnDCodeNumber( text ); gerber_layer->Execute_DCODE_Command( this, DC, text, D_commande ); break; case 'X': case 'Y': /* Move or draw command */ pos = gerber_layer->ReadXYCoord( text ); if( *text == '*' ) // command like X12550Y19250* { gerber_layer->Execute_DCODE_Command( this, DC, text, gerber_layer->m_Last_Pen_Command ); } break; case 'I': case 'J': /* Auxiliary Move command */ pos = gerber_layer->ReadIJCoord( text ); break; case '%': if( gerber_layer->m_CommandState != ENTER_RS274X_CMD ) { gerber_layer->m_CommandState = ENTER_RS274X_CMD; if( !gerber_layer->ReadRS274XCommand( this, DC, Line, text ) ) { error++; } } else //Error { error++; gerber_layer->m_CommandState = CMD_IDLE; text++; } break; default: text++; error++; break; } } } if( error ) { msg.Printf( _( "%d errors while reading Gerber file [%s]" ), error, GERBER_FullFileName.GetData() ); DisplayError( this, msg ); } fclose( gerber_layer->m_Current_File ); setlocale( LC_NUMERIC, "" ); /* Init DCodes list and perhaps read a DCODES file, * if the gerber file is only a RS274D file (without any aperture information) */ if( !gerber_layer->m_As_DCode ) { wxString DCodeFileName; if( D_Code_FullFileName.IsEmpty() ) { wxString mask; DCodeFileName = GERBER_FullFileName; ChangeFileNameExt( DCodeFileName, g_PenFilenameExt ); mask = wxT( "*" ) + g_PenFilenameExt; DCodeFileName = EDA_FileSelector( _( "D codes files:" ), wxEmptyString, /* Chemin par defaut */ DCodeFileName, /* nom fichier par defaut */ g_PenFilenameExt, /* extension par defaut */ mask, /* Masque d'affichage */ this, 0, TRUE ); } else DCodeFileName = D_Code_FullFileName; if( !DCodeFileName.IsEmpty() ) { Read_D_Code_File( DCodeFileName ); CopyDCodesSizeToItems(); } } return TRUE; }