Gerbview: Added: read Excellon files created by Pcbnew. The full Excellon command set is not supported, but drill files created by Pcbnew are supported.
This commit is contained in:
parent
0d740e45e3
commit
ffbce6de84
|
@ -4,6 +4,12 @@ KiCad ChangeLog 2010
|
||||||
Please add newer entries at the top, list the date and your name with
|
Please add newer entries at the top, list the date and your name with
|
||||||
email address.
|
email address.
|
||||||
|
|
||||||
|
2011-Mar-16, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
||||||
|
================================================================================
|
||||||
|
Gerbview:
|
||||||
|
Added: read Excellon files created by Pcbnew.
|
||||||
|
The full Excellon command set is not supported, but drill files created by Pcbnew are supported.
|
||||||
|
|
||||||
2011-Feb-05, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
2011-Feb-05, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
|
||||||
================================================================================
|
================================================================================
|
||||||
CvPcb:
|
CvPcb:
|
||||||
|
|
|
@ -34,6 +34,7 @@ set(GERBVIEW_SRCS
|
||||||
dummy_functions.cpp
|
dummy_functions.cpp
|
||||||
draw_gerber_screen.cpp
|
draw_gerber_screen.cpp
|
||||||
events_called_functions.cpp
|
events_called_functions.cpp
|
||||||
|
excellon_read_drill_file.cpp
|
||||||
export_to_pcbnew.cpp
|
export_to_pcbnew.cpp
|
||||||
files.cpp
|
files.cpp
|
||||||
gerbview.cpp
|
gerbview.cpp
|
||||||
|
|
|
@ -142,7 +142,16 @@ public:
|
||||||
~GERBER_IMAGE();
|
~GERBER_IMAGE();
|
||||||
void Clear_GERBER_IMAGE();
|
void Clear_GERBER_IMAGE();
|
||||||
int ReturnUsedDcodeNumber();
|
int ReturnUsedDcodeNumber();
|
||||||
void ResetDefaultValues();
|
virtual void ResetDefaultValues();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetParent
|
||||||
|
* @return the GERBVIEW_FRAME parent of this GERBER_IMAGE
|
||||||
|
*/
|
||||||
|
GERBVIEW_FRAME* GetParent()
|
||||||
|
{
|
||||||
|
return m_Parent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function GetLayerParams
|
* Function GetLayerParams
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
/********************/
|
||||||
|
/* class_excellon.h */
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
#ifndef CLASS_EXCELLON_H
|
||||||
|
#define CLASS_EXCELLON_H
|
||||||
|
|
||||||
|
|
||||||
|
enum drill_M_code_t {
|
||||||
|
DRILL_M_UNKNOWN,
|
||||||
|
DRILL_M_END,
|
||||||
|
DRILL_M_ENDREWIND,
|
||||||
|
DRILL_M_MESSAGE,
|
||||||
|
DRILL_M_LONGMESSAGE,
|
||||||
|
DRILL_M_HEADER,
|
||||||
|
DRILL_M_ENDHEADER,
|
||||||
|
DRILL_M_BEGINPATTERN,
|
||||||
|
DRILL_M_ENDPATTERN,
|
||||||
|
DRILL_M_CANNEDTEXT,
|
||||||
|
DRILL_M_TIPCHECK,
|
||||||
|
DRILL_M_METRIC,
|
||||||
|
DRILL_M_IMPERIAL,
|
||||||
|
DRILL_METRICHEADER,
|
||||||
|
DRILL_IMPERIALHEADER,
|
||||||
|
DRILL_DETECT_BROKEN,
|
||||||
|
DRILL_INCREMENTALHEADER,
|
||||||
|
DRILL_REWIND_STOP,
|
||||||
|
DRILL_TOOL_CHANGE_STOP,
|
||||||
|
DRILL_AUTOMATIC_SPEED,
|
||||||
|
DRILL_AXIS_VERSION,
|
||||||
|
DRILL_RESET_CMD,
|
||||||
|
DRILL_AUTOMATIC_TOOL_CHANGE,
|
||||||
|
DRILL_FMT,
|
||||||
|
DRILL_SKIP,
|
||||||
|
DRILL_TOOL_INFORMATION
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum drill_G_code_t {
|
||||||
|
DRILL_G_UNKNOWN,
|
||||||
|
DRILL_G_ABSOLUTE,
|
||||||
|
DRILL_G_INCREMENTAL,
|
||||||
|
DRILL_G_ZEROSET,
|
||||||
|
DRILL_G_ROUT,
|
||||||
|
DRILL_G_DRILL,
|
||||||
|
DRILL_G_SLOT,
|
||||||
|
DRILL_G_ZERO_SET,
|
||||||
|
DRILL_G_LINEARMOVE,
|
||||||
|
DRILL_G_CWMOVE,
|
||||||
|
DRILL_G_CCWMOVE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper struct to analyse Excellon commands
|
||||||
|
struct EXCELLON_CMD
|
||||||
|
{
|
||||||
|
string m_Name; // key string
|
||||||
|
int m_Code; // internal code, used as id in functions
|
||||||
|
int m_asParams; // 0 = no param, -1 = skip params, 1 = read params
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* EXCELLON_IMAGE handle a drill image
|
||||||
|
* It is derived from GERBER_IMAGE because there is a lot of likeness
|
||||||
|
* between EXCELLON files and GERBER files
|
||||||
|
* DCode aperture are also similat to T Codes.
|
||||||
|
* So we can reuse GERBER_IMAGE to handle EXCELLON_IMAGE with very few new functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
class EXCELLON_IMAGE : public GERBER_IMAGE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
enum excellon_state {
|
||||||
|
READ_HEADER_STATE, // When we are in this state, we are reading header
|
||||||
|
READ_PROGRAM_STATE // When we are in this state, we are reading drill data
|
||||||
|
};
|
||||||
|
excellon_state m_State; // state of excellon file analysis
|
||||||
|
bool m_SlotOn; // true during an oval driil definition
|
||||||
|
|
||||||
|
public: EXCELLON_IMAGE( GERBVIEW_FRAME* aParent, int layer ) :
|
||||||
|
GERBER_IMAGE( aParent, layer )
|
||||||
|
{
|
||||||
|
m_State = READ_HEADER_STATE;
|
||||||
|
m_SlotOn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~EXCELLON_IMAGE() {};
|
||||||
|
|
||||||
|
virtual void ResetDefaultValues()
|
||||||
|
{
|
||||||
|
GERBER_IMAGE::ResetDefaultValues();
|
||||||
|
SelectUnits( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Read_EXCELLON_File( FILE* aFile, const wxString& aFullFileName );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Execute_HEADER_Command( char*& text );
|
||||||
|
bool Select_Tool( char*& text );
|
||||||
|
bool Execute_EXCELLON_G_Command( char*& text );
|
||||||
|
bool Execute_Drill_Command( char*& text );
|
||||||
|
|
||||||
|
int ReturnTCodeNumber( char*& Text )
|
||||||
|
{
|
||||||
|
return ReturnDCodeNumber( Text );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SelectUnits( bool aMetric );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXCELLON commands are given here.
|
||||||
|
* Pcbnew uses only few excellon commands
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see http://www.excellon.com/manuals/program.htm
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* coordintes units:
|
||||||
|
* Coordinates are measured either in inch or metric (millimeters).
|
||||||
|
* Inch coordinates are in six digits (00.0000) with increments as small as 0.0001 (1/10,000).
|
||||||
|
* Metric coordinates can be measured in microns (thousandths of a millimeter)
|
||||||
|
* in one of the following three ways:
|
||||||
|
* Five digit 10 micron resolution (000.00)
|
||||||
|
* Six digit 10 micron resolution (0000.00)
|
||||||
|
* Six digit micron resolution (000.000)
|
||||||
|
*
|
||||||
|
* Leading and trailing zeros:
|
||||||
|
* Excellon (CNC-7) uses inches in six digits and metric in five or six digits.
|
||||||
|
* The zeros to the left of the coordinate are called leading zeros (LZ).
|
||||||
|
* The zeros to right of the coordinate are called trailing zeros (TZ).
|
||||||
|
* The CNC-7 uses leading zeros unless you specify otherwise through a part program.
|
||||||
|
* You can do so with the INCH/METRIC command.
|
||||||
|
* With leading zeros, the leading zeros must always be included.
|
||||||
|
* Trailing zeros are unneeded and may be left off.
|
||||||
|
* For trailing zeros, the reverse of the above is true.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EXCELLON Commands Used in a Header
|
||||||
|
* The following table provides you with a list of commands which
|
||||||
|
* are the most used in a part program header.
|
||||||
|
* COMMAND DESCRIPTION
|
||||||
|
* AFS Automatic Feeds and Speeds
|
||||||
|
* ATC Automatic Tool Change
|
||||||
|
* BLKD Delete all Blocks starting with a slash (/)
|
||||||
|
* CCW Clockwise or Counter-clockwise Routing
|
||||||
|
* CP Cutter Compensation
|
||||||
|
* DETECT Broken Tool Detection
|
||||||
|
* DN Down Limit Set
|
||||||
|
* DTMDIST Maximum Rout Distance Before Toolchange
|
||||||
|
* EXDA Extended Drill Area
|
||||||
|
* FMAT Format 1 or 2
|
||||||
|
* FSB Turns the Feed/Speed Buttons off
|
||||||
|
* HPCK Home Pulse Check
|
||||||
|
* ICI Incremental Input of Part Program Coordinates
|
||||||
|
* INCH Measure Everything in Inches
|
||||||
|
* METRIC Measure Everything in Metric
|
||||||
|
* M48 Beginning of Part Program Header
|
||||||
|
* M95 End of Header
|
||||||
|
* NCSL NC Slope Enable/Disable
|
||||||
|
* OM48 Override Part Program Header
|
||||||
|
* OSTOP Optional Stop Switch
|
||||||
|
* OTCLMP Override Table Clamp
|
||||||
|
* PCKPARAM Set up pecking tool,depth,infeed and retract parameters
|
||||||
|
* PF Floating Pressure Foot Switch
|
||||||
|
* PPR Programmable Plunge Rate Enable
|
||||||
|
* PVS Pre-vacuum Shut-off Switch
|
||||||
|
* R,C Reset Clocks
|
||||||
|
* R,CP Reset Program Clocks
|
||||||
|
* R,CR Reset Run Clocks
|
||||||
|
* R,D Reset All Cutter Distances
|
||||||
|
* R,H Reset All Hit Counters
|
||||||
|
* R,T Reset Tool Data
|
||||||
|
* SBK Single Block Mode Switch
|
||||||
|
* SG Spindle Group Mode
|
||||||
|
* SIXM Input From External Source
|
||||||
|
* T Tool Information
|
||||||
|
* TCST Tool Change Stop
|
||||||
|
* UP Upper Limit Set
|
||||||
|
* VER Selection of X and Y Axis Version
|
||||||
|
* Z Zero Set
|
||||||
|
* ZA Auxiliary Zero
|
||||||
|
* ZC Zero Correction
|
||||||
|
* ZS Zero Preset
|
||||||
|
* Z+# or Z-# Set Depth Offset
|
||||||
|
* % Rewind Stop
|
||||||
|
* #/#/# Link Tool for Automatic Tool Change
|
||||||
|
* / Clear Tool Linking
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Beyond The Header: The Part Program Body
|
||||||
|
* COMMAND DESCRIPTION
|
||||||
|
* A# Arc Radius
|
||||||
|
* B# Retract Rate
|
||||||
|
* C# Tool Diameter
|
||||||
|
* F# Table Feed Rate;Z Axis Infeed Rate
|
||||||
|
* G00X#Y# Route Mode
|
||||||
|
* G01 Linear (Straight Line) Mode
|
||||||
|
* G02 Circular CW Mode
|
||||||
|
* G03 Circular CCW Mode
|
||||||
|
* G04 X# Variable Dwell
|
||||||
|
* G05 Drill Mode
|
||||||
|
* G07 Override current tool feed or speed
|
||||||
|
* G32X#Y#A# Routed Circle Canned Cycle
|
||||||
|
* CW G33X#Y#A# Routed Circle Canned Cycle
|
||||||
|
* CCW G34,#(,#) Select Vision Tool
|
||||||
|
* G35(X#Y#) Single Point Vision Offset (Relative to Work Zero)
|
||||||
|
* G36(X#Y#) Multipoint Vision Translation (Relative to Work Zero)
|
||||||
|
* G37 Cancel Vision Translation or Offset (From G35 or G36)
|
||||||
|
* G38(X#Y#) Vision Corrected Single Hole Drilling (Relative to Work Zero)
|
||||||
|
* G39(X#Y#) Vision System Autocalibration
|
||||||
|
* G40 Cutter Compensation Off
|
||||||
|
* G41 Cutter Compensation Left
|
||||||
|
* G42 Cutter Compensation Right
|
||||||
|
* G45(X#Y#) Single Point Vision Offset (Relative to G35 or G36)
|
||||||
|
* G46(X#Y#) Multipoint Vision Translation (Relative to G35 or G36)
|
||||||
|
* G47 Cancel Vision Translation or Offset (From G45 or G46)
|
||||||
|
* G48(X#Y#) Vision Corrected Single Hole Drilling (Relative to G35 or G36)
|
||||||
|
* G82(G81) Dual In Line Package
|
||||||
|
* G83 Eight Pin L Pack
|
||||||
|
* G84 Circle
|
||||||
|
* G85 Slot
|
||||||
|
* G87 Routed Step Slot Canned Cycle
|
||||||
|
* G90 Absolute Mode
|
||||||
|
* G91 Incremental Input Mode
|
||||||
|
* G93X#Y# Zero Set
|
||||||
|
* H# Maximum hit count
|
||||||
|
* I#J# Arc Center Offset
|
||||||
|
* M00(X#Y#) End of Program - No Rewind
|
||||||
|
* M01 End of Pattern
|
||||||
|
* M02X#Y# Repeat Pattern Offset
|
||||||
|
* M06(X#Y#) Optional Stop
|
||||||
|
* M08 End of Step and Repeat
|
||||||
|
* M09(X#Y#) Stop for Inspection
|
||||||
|
* M14 Z Axis Route Position With Depth Controlled Contouring
|
||||||
|
* M15 Z Axis Route Position
|
||||||
|
* M16 Retract With Clamping
|
||||||
|
* M17 Retract Without Clamping
|
||||||
|
* M18 Command tool tip check
|
||||||
|
* M25 Beginning of Pattern
|
||||||
|
* M30(X#Y#) End of Program Rewind
|
||||||
|
* M45,long message\ Long Operator message on multiple\ part program lines
|
||||||
|
* M47,text Operator Message
|
||||||
|
* M50,# Vision Step and Repeat Pattern Start
|
||||||
|
* M51,# Vision Step and Repeat Rewind
|
||||||
|
* M52(#) Vision Step and Repeat Offset Counter Control
|
||||||
|
* M02XYM70 Swap Axes
|
||||||
|
* M60 Reference Scaling enable
|
||||||
|
* M61 Reference Scaling disable
|
||||||
|
* M62 Turn on peck drilling
|
||||||
|
* M63 Turn off peck drilling
|
||||||
|
* M71 Metric Measuring Mode
|
||||||
|
* M72 Inch Measuring Mode
|
||||||
|
* M02XYM80 Mirror Image X Axis
|
||||||
|
* M02XYM90 Mirror Image Y Axis
|
||||||
|
* M97,text Canned Text
|
||||||
|
* M98,text Canned Text
|
||||||
|
* M99,subprogram User Defined Stored Pattern
|
||||||
|
* P#X#(Y#) Repeat Stored Pattern
|
||||||
|
* R#M02X#Y# Repeat Pattern (S&R)
|
||||||
|
* R#(X#Y#) Repeat Hole
|
||||||
|
* S# Spindle RPM
|
||||||
|
* T# Tool Selection; Cutter Index
|
||||||
|
* Z+# or Z-# Depth Offset
|
||||||
|
* % Beginning of Pattern (see M25 command)
|
||||||
|
* / Block Delete
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Example of a Header
|
||||||
|
* COMMAND PURPOSE
|
||||||
|
* M48 The beginning of a header
|
||||||
|
* INCH,LZ Use the inch measuring system with leading zeros
|
||||||
|
* VER,1 Use Version 1 X and Y axis layout
|
||||||
|
* FMAT,2 Use Format 2 commands
|
||||||
|
* 1/2/3 Link tools 1, 2, and 3
|
||||||
|
* T1C.04F200S65 Set Tool 1 for 0.040" with infeed rate of 200 inch/min Speed of 65,000 RPM
|
||||||
|
* DETECT,ON Detect broken tools
|
||||||
|
* M95 End of the header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // CLASS_EXCELLON_H
|
|
@ -0,0 +1,595 @@
|
||||||
|
/********************************/
|
||||||
|
/* excellon_read_drill_file.cpp */
|
||||||
|
/********************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions to read drill files (EXCELLON format) created by PcbNew
|
||||||
|
* These files use only a subset of EXCELLON commands.
|
||||||
|
* Here is a sample, in decimal format:
|
||||||
|
* (Note: coordinates formats are same as Gerber, and T commands are near Gerber D commands).
|
||||||
|
* M48
|
||||||
|
* ;DRILL file {PCBnew (2011-03-14 BZR 2894)-testing} date 15/03/2011 14:23:22
|
||||||
|
* ;FORMAT={-:-/ absolute / inch / decimal}
|
||||||
|
* FMAT,2
|
||||||
|
* INCH,TZ
|
||||||
|
* T1C0.02
|
||||||
|
* T2C0.032
|
||||||
|
* %
|
||||||
|
* G90
|
||||||
|
* G05
|
||||||
|
* M72
|
||||||
|
* T1
|
||||||
|
* X1.580Y-1.360
|
||||||
|
* X1.580Y-4.860
|
||||||
|
* X8.680Y-1.360
|
||||||
|
* X8.680Y-4.860
|
||||||
|
* T2
|
||||||
|
* X2.930Y-3.560
|
||||||
|
* X5.280Y-2.535
|
||||||
|
* X5.405Y-2.610
|
||||||
|
* X5.620Y-2.900
|
||||||
|
* T0
|
||||||
|
* M30
|
||||||
|
*/
|
||||||
|
#include "fctsys.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "confirm.h"
|
||||||
|
|
||||||
|
#include "gerbview.h"
|
||||||
|
#include "trigo.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "class_gerber_draw_item.h"
|
||||||
|
#include "class_GERBER.h"
|
||||||
|
#include "class_excellon.h"
|
||||||
|
#include "kicad_string.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "dialog_load_error.h"
|
||||||
|
|
||||||
|
extern int ReadInt( char*& text, bool aSkipSeparator = true );
|
||||||
|
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
|
||||||
|
extern void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||||
|
APERTURE_T aAperture,
|
||||||
|
int Dcode_index,
|
||||||
|
int aLayer,
|
||||||
|
const wxPoint& aPos,
|
||||||
|
wxSize aSize,
|
||||||
|
bool aLayerNegative );
|
||||||
|
void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||||
|
int Dcode_index,
|
||||||
|
int aLayer,
|
||||||
|
const wxPoint& aStart,
|
||||||
|
const wxPoint& aEnd,
|
||||||
|
wxSize aPenSize,
|
||||||
|
bool aLayerNegative );
|
||||||
|
|
||||||
|
static EXCELLON_CMD excellonHeaderCmdList[] =
|
||||||
|
{
|
||||||
|
{ "M0", DRILL_M_END, -1 }, // End of Program - No Rewind
|
||||||
|
{ "M00", DRILL_M_END, -1 }, // End of Program - No Rewind
|
||||||
|
{ "M30", DRILL_M_ENDREWIND, -1 }, // End of Program Rewind
|
||||||
|
{ "M47", DRILL_M_MESSAGE, -1 }, // Operator Message
|
||||||
|
{ "M45", DRILL_M_LONGMESSAGE, -1 }, // Long Operator message (use more than one line)
|
||||||
|
{ "M48", DRILL_M_HEADER, 0 }, // beginning of a header
|
||||||
|
{ "M95", DRILL_M_ENDHEADER, 0 }, // End of the header
|
||||||
|
{ "METRIC", DRILL_METRICHEADER, 1 },
|
||||||
|
{ "INCH", DRILL_IMPERIALHEADER, 1 },
|
||||||
|
{ "M71", DRILL_M_METRIC, 1 },
|
||||||
|
{ "M72", DRILL_M_IMPERIAL, 1 },
|
||||||
|
{ "M25", DRILL_M_BEGINPATTERN, 0 }, // Beginning of Pattern
|
||||||
|
{ "M01", DRILL_M_ENDPATTERN, 0 }, // End of Pattern
|
||||||
|
{ "M97", DRILL_M_CANNEDTEXT, -1 },
|
||||||
|
{ "M98", DRILL_M_CANNEDTEXT, -1 },
|
||||||
|
{ "DETECT", DRILL_DETECT_BROKEN, -1 },
|
||||||
|
{ "ICI", DRILL_INCREMENTALHEADER, 1 },
|
||||||
|
{ "FMAT", DRILL_FMT, 1 }, // Use Format command
|
||||||
|
{ "ATC", DRILL_AUTOMATIC_TOOL_CHANGE, 0 },
|
||||||
|
{ "TCST", DRILL_TOOL_CHANGE_STOP, 0 }, // Tool Change Stop
|
||||||
|
{ "AFS", DRILL_AUTOMATIC_SPEED }, // Automatic Feeds and Speeds
|
||||||
|
{ "VER", DRILL_AXIS_VERSION, 1 }, // Selection of X and Y Axis Version
|
||||||
|
{ "R", DRILL_RESET_CMD, -1 }, // Reset commands
|
||||||
|
{ "%", DRILL_REWIND_STOP, -1 }, // Rewind stop. End of the header
|
||||||
|
{ "/", DRILL_SKIP, -1 }, // Clear Tool Linking. End of the header
|
||||||
|
// Keep this item after all commands starting by 'T':
|
||||||
|
{ "T", DRILL_TOOL_INFORMATION, 0 }, // Tool Information
|
||||||
|
{ "", DRILL_M_UNKNOWN, 0 } // last item in list
|
||||||
|
};
|
||||||
|
|
||||||
|
static EXCELLON_CMD excellon_G_CmdList[] =
|
||||||
|
{
|
||||||
|
{ "G90", DRILL_G_ABSOLUTE, 0 }, // Absolute Mode
|
||||||
|
{ "G91", DRILL_G_INCREMENTAL, 0 }, // Incremental Input Mode
|
||||||
|
{ "G90", DRILL_G_ZEROSET, 0 }, // Absolute Mode
|
||||||
|
{ "G00", DRILL_G_ROUT, 1 }, // Route Mode
|
||||||
|
{ "G05", DRILL_G_DRILL, 0 }, // Drill Mode
|
||||||
|
{ "G85", DRILL_G_SLOT, 0 }, // Drill Mode slot (oval holes)
|
||||||
|
{ "G01", DRILL_G_LINEARMOVE, 0 }, // Linear (Straight Line) Mode
|
||||||
|
{ "G02", DRILL_G_CWMOVE, 0 }, // Circular CW Mode
|
||||||
|
{ "G03", DRILL_G_CCWMOVE, 0 }, // Circular CCW Mode
|
||||||
|
{ "G93", DRILL_G_ZERO_SET, 1 }, // Zero Set (XnnYmm and coordintes origin)
|
||||||
|
{ "", DRILL_G_UNKNOWN, 0 }, // last item in list
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a EXCELLON file.
|
||||||
|
* Gerber classes are used because there is likeness between Gerber files
|
||||||
|
* and Excellon files
|
||||||
|
* DCode can easily store T code (tool size) as round (or oval) shape
|
||||||
|
* Drill commands are similar to flashed gerber items
|
||||||
|
* Routing commands are similar to Gerber polygons
|
||||||
|
* coordinates have the same format as Gerber.
|
||||||
|
*/
|
||||||
|
bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
int layer = getActiveLayer(); // current layer used in gerbview
|
||||||
|
|
||||||
|
if( g_GERBER_List[layer] == NULL )
|
||||||
|
{
|
||||||
|
g_GERBER_List[layer] = new EXCELLON_IMAGE( this, layer );
|
||||||
|
}
|
||||||
|
|
||||||
|
EXCELLON_IMAGE* drill_Layer = (EXCELLON_IMAGE*) g_GERBER_List[layer];
|
||||||
|
ClearMessageList();
|
||||||
|
|
||||||
|
/* Read the gerber file */
|
||||||
|
FILE * file = wxFopen( aFullFileName, wxT( "rt" ) );
|
||||||
|
if( file == NULL )
|
||||||
|
{
|
||||||
|
msg.Printf( _( "File %s not found" ), GetChars( aFullFileName ) );
|
||||||
|
DisplayError( this, msg, 10 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString path = wxPathOnly( aFullFileName );
|
||||||
|
if( path != wxEmptyString )
|
||||||
|
wxSetWorkingDirectory( path );
|
||||||
|
|
||||||
|
bool success = drill_Layer->Read_EXCELLON_File( file, aFullFileName );
|
||||||
|
|
||||||
|
// Display errors list
|
||||||
|
if( m_Messages.size() > 0 )
|
||||||
|
{
|
||||||
|
DIALOG_LOAD_ERROR dlg( this );
|
||||||
|
dlg.ListSet( m_Messages );
|
||||||
|
dlg.ShowModal();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EXCELLON_IMAGE::Read_EXCELLON_File( FILE * aFile,
|
||||||
|
const wxString & aFullFileName )
|
||||||
|
{
|
||||||
|
/* Set the gerber scale: */
|
||||||
|
ResetDefaultValues();
|
||||||
|
|
||||||
|
m_FileName = aFullFileName;
|
||||||
|
m_Current_File = aFile;
|
||||||
|
|
||||||
|
SetLocaleTo_C_standard();
|
||||||
|
|
||||||
|
// FILE_LINE_READER will close the file.
|
||||||
|
if( m_Current_File == NULL )
|
||||||
|
{
|
||||||
|
wxMessageBox( wxT("NULL!"), m_FileName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_LINE_READER excellonReader( m_Current_File, m_FileName );
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
if( excellonReader.ReadLine() == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
char* line = excellonReader.Line();
|
||||||
|
char* text = StrPurge( line );
|
||||||
|
|
||||||
|
if( *text == ';' ) // comment: skip line
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( m_State == EXCELLON_IMAGE::READ_HEADER_STATE )
|
||||||
|
{
|
||||||
|
Execute_HEADER_Command( text );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( *text )
|
||||||
|
{
|
||||||
|
case 'M':
|
||||||
|
Execute_HEADER_Command( text );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'G': /* Line type Gxx : command */
|
||||||
|
Execute_EXCELLON_G_Command( text );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
case 'Y': // command like X12550Y19250
|
||||||
|
Execute_Drill_Command(text);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
case 'J': /* Auxiliary Move command */
|
||||||
|
m_IJPos = ReadIJCoord( text );
|
||||||
|
if( *text == '*' ) // command like X35142Y15945J504*
|
||||||
|
{
|
||||||
|
Execute_Drill_Command( text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T': // Tool command
|
||||||
|
Select_Tool( text );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
msg.Printf( wxT( "Unexpected symbol <%c>" ), *text );
|
||||||
|
if( GetParent() )
|
||||||
|
GetParent()->ReportMessage( msg );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} // End switch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetLocaleTo_Default();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EXCELLON_IMAGE::Execute_HEADER_Command( char*& text )
|
||||||
|
{
|
||||||
|
EXCELLON_CMD* cmd = NULL;
|
||||||
|
int iprm;
|
||||||
|
double dprm;
|
||||||
|
D_CODE* dcode;
|
||||||
|
wxString msg;
|
||||||
|
|
||||||
|
// Search command in list
|
||||||
|
EXCELLON_CMD* candidate;
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ; ii++ )
|
||||||
|
{
|
||||||
|
candidate = &excellonHeaderCmdList[ii];
|
||||||
|
int len = candidate->m_Name.size();
|
||||||
|
if( len == 0 ) // End of list reached
|
||||||
|
break;
|
||||||
|
if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found.
|
||||||
|
{
|
||||||
|
cmd = candidate;
|
||||||
|
text += len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !cmd )
|
||||||
|
{
|
||||||
|
msg.Printf( wxT( "Unknown Excellon command <%s>" ), text );
|
||||||
|
ReportMessage( msg );
|
||||||
|
while( *text )
|
||||||
|
text++;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
// some do nothing
|
||||||
|
switch( cmd->m_Code )
|
||||||
|
{
|
||||||
|
case DRILL_SKIP:
|
||||||
|
case DRILL_M_UNKNOWN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_END:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_ENDREWIND:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_MESSAGE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_LONGMESSAGE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_HEADER:
|
||||||
|
m_State = READ_HEADER_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_ENDHEADER:
|
||||||
|
m_State = READ_PROGRAM_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_REWIND_STOP: // TODO: what this command really is ?
|
||||||
|
m_State = READ_PROGRAM_STATE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_METRIC:
|
||||||
|
SelectUnits( true );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_METRICHEADER: // command like METRIC,TZ or METRIC,LZ
|
||||||
|
SelectUnits( true );
|
||||||
|
if( *text != ',' )
|
||||||
|
{
|
||||||
|
ReportMessage( _( "METRIC command has no parameter" ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text++; // skip separator
|
||||||
|
if( *text == 'T' )
|
||||||
|
m_NoTrailingZeros = false;
|
||||||
|
else
|
||||||
|
m_NoTrailingZeros = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_IMPERIAL:
|
||||||
|
SelectUnits( false );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_IMPERIALHEADER: // command like INCH,TZ or INCH,LZ
|
||||||
|
SelectUnits( false );
|
||||||
|
if( *text != ',' )
|
||||||
|
{
|
||||||
|
ReportMessage( _( "INCH command has no parameter" ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
text++; // skip separator
|
||||||
|
if( *text == 'T' )
|
||||||
|
m_NoTrailingZeros = false;
|
||||||
|
else
|
||||||
|
m_NoTrailingZeros = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_BEGINPATTERN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_ENDPATTERN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_CANNEDTEXT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_M_TIPCHECK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_DETECT_BROKEN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_INCREMENTALHEADER:
|
||||||
|
m_Relative = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_TOOL_CHANGE_STOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_AUTOMATIC_SPEED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_AXIS_VERSION:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_RESET_CMD:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_AUTOMATIC_TOOL_CHANGE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_FMT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_TOOL_INFORMATION:
|
||||||
|
|
||||||
|
// Read a tool definition like T1C0.02:
|
||||||
|
// Read tool number:
|
||||||
|
iprm = ReadInt( text, false );
|
||||||
|
|
||||||
|
// Read tool shape
|
||||||
|
if( *text != 'C' )
|
||||||
|
ReportMessage( _( "Tool definition <%c> not supported" ) );
|
||||||
|
if( *text )
|
||||||
|
text++;
|
||||||
|
|
||||||
|
//read tool diameter:
|
||||||
|
dprm = ReadDouble( text, false );
|
||||||
|
m_Has_DCode = true;
|
||||||
|
|
||||||
|
// Initialize Dcode to handle this Tool
|
||||||
|
dcode = GetDCODE( iprm + FIRST_DCODE ); // Remember: dcodes are >= FIRST_DCODE
|
||||||
|
if( dcode == NULL )
|
||||||
|
break;
|
||||||
|
double conv_scale = m_GerbMetric ? PCB_INTERNAL_UNIT / 25.4 : PCB_INTERNAL_UNIT;
|
||||||
|
dcode->m_Size.x = dcode->m_Size.y = wxRound( dprm * conv_scale );
|
||||||
|
dcode->m_Shape = APT_CIRCLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( *text )
|
||||||
|
text++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EXCELLON_IMAGE::Execute_Drill_Command( char*& text )
|
||||||
|
{
|
||||||
|
D_CODE* tool;
|
||||||
|
GERBER_DRAW_ITEM * gbritem;
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
switch( *text )
|
||||||
|
{
|
||||||
|
case 'X':
|
||||||
|
ReadXYCoord( text );
|
||||||
|
break;
|
||||||
|
case 'Y':
|
||||||
|
ReadXYCoord( text );
|
||||||
|
break;
|
||||||
|
case 'G': // G85 is found here for oval holes
|
||||||
|
m_PreviousPos = m_CurrentPos;
|
||||||
|
Execute_EXCELLON_G_Command( text );
|
||||||
|
break;
|
||||||
|
case 0: // E.O.L: execute command
|
||||||
|
tool = GetDCODE( m_Current_Tool, false );
|
||||||
|
if( !tool )
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
msg.Printf( _( "Tool <%d> not defined" ), m_Current_Tool );
|
||||||
|
ReportMessage( msg );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gbritem = new GERBER_DRAW_ITEM( GetParent()->GetBoard(), this );
|
||||||
|
GetParent()->GetBoard()->m_Drawings.Append( gbritem );
|
||||||
|
if( m_SlotOn ) // Oval hole
|
||||||
|
{
|
||||||
|
fillLineGBRITEM( gbritem,
|
||||||
|
tool->m_Num_Dcode, GetParent()->getActiveLayer(),
|
||||||
|
m_PreviousPos, m_CurrentPos,
|
||||||
|
tool->m_Size, false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fillFlashedGBRITEM( gbritem, tool->m_Shape,
|
||||||
|
tool->m_Num_Dcode, GetParent()->getActiveLayer(),
|
||||||
|
m_CurrentPos,
|
||||||
|
tool->m_Size, false );
|
||||||
|
}
|
||||||
|
StepAndRepeatItem( *gbritem );
|
||||||
|
m_PreviousPos = m_CurrentPos;
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
text++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EXCELLON_IMAGE::Select_Tool( char*& text )
|
||||||
|
{
|
||||||
|
int tool_id = ReturnTCodeNumber( text );
|
||||||
|
|
||||||
|
if( tool_id >= 0 )
|
||||||
|
{
|
||||||
|
tool_id += FIRST_DCODE; // Remember: dcodes are >= FIRST_DCODE
|
||||||
|
if( tool_id > (TOOLS_MAX_COUNT - 1) )
|
||||||
|
tool_id = TOOLS_MAX_COUNT - 1;
|
||||||
|
m_Current_Tool = tool_id;
|
||||||
|
D_CODE* pt_Dcode = GetDCODE( tool_id , false );
|
||||||
|
if( pt_Dcode )
|
||||||
|
pt_Dcode->m_InUse = true;
|
||||||
|
}
|
||||||
|
while( *text )
|
||||||
|
text++;
|
||||||
|
|
||||||
|
return tool_id >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool EXCELLON_IMAGE::Execute_EXCELLON_G_Command( char*& text )
|
||||||
|
{
|
||||||
|
EXCELLON_CMD* cmd = NULL;
|
||||||
|
bool success = false;
|
||||||
|
int id = DRILL_G_UNKNOWN;
|
||||||
|
|
||||||
|
// Search command in list
|
||||||
|
EXCELLON_CMD* candidate;
|
||||||
|
char * gcmd = text; // gcmd points the G command, for error messages.
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ; ii++ )
|
||||||
|
{
|
||||||
|
candidate = &excellon_G_CmdList[ii];
|
||||||
|
int len = candidate->m_Name.size();
|
||||||
|
if( len == 0 ) // End of list reached
|
||||||
|
break;
|
||||||
|
if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found.
|
||||||
|
{
|
||||||
|
cmd = candidate;
|
||||||
|
text += len;
|
||||||
|
success = true;
|
||||||
|
id = cmd->m_Code;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( id )
|
||||||
|
{
|
||||||
|
case DRILL_G_ZERO_SET:
|
||||||
|
ReadXYCoord( text );
|
||||||
|
m_Offset = m_CurrentPos;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_ROUT:
|
||||||
|
m_SlotOn = false;
|
||||||
|
m_PolygonFillMode = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_DRILL:
|
||||||
|
m_SlotOn = false;
|
||||||
|
m_PolygonFillMode = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_SLOT:
|
||||||
|
m_SlotOn = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_LINEARMOVE:
|
||||||
|
m_Iterpolation = GERB_INTERPOL_LINEAR_1X;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_CWMOVE:
|
||||||
|
m_Iterpolation = GERB_INTERPOL_ARC_NEG;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_CCWMOVE:
|
||||||
|
m_Iterpolation = GERB_INTERPOL_ARC_POS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_ABSOLUTE:
|
||||||
|
m_Relative = false; // false = absolute coord
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_INCREMENTAL:
|
||||||
|
m_Relative = true; // true = relative coord
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DRILL_G_UNKNOWN:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
wxString msg;
|
||||||
|
msg.Printf( _( "Unknown Excellon G Code: <%s>" ), GetChars(FROM_UTF8(gcmd)) );
|
||||||
|
ReportMessage( msg );
|
||||||
|
while( *text )
|
||||||
|
text++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXCELLON_IMAGE::SelectUnits( bool aMetric )
|
||||||
|
{
|
||||||
|
/* Inches: Default fmt = 2.4 for X and Y axis: 6 digits with 0.0001 resolution (00.0000)
|
||||||
|
* metric: Default fmt = 3.2 for X and Y axis: 5 digits, 1 micron resolution (00.000)
|
||||||
|
*/
|
||||||
|
if( aMetric )
|
||||||
|
{
|
||||||
|
m_GerbMetric = true;
|
||||||
|
m_FmtScale.x = m_FmtScale.y = 3; // number of digits in mantissa: here 2
|
||||||
|
m_FmtLen.x = m_FmtLen.y = 5; // number of digits: here 3+2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_GerbMetric = false;
|
||||||
|
m_FmtScale.x = m_FmtScale.y = 4; // number of digits in mantissa: here 4
|
||||||
|
m_FmtLen.x = m_FmtLen.y = 6; // number of digits: here 2+4
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,7 +73,8 @@ clear an existing layer to load any new layers." ), NB_LAYERS );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_GERBVIEW_LOAD_DRILL_FILE:
|
case ID_GERBVIEW_LOAD_DRILL_FILE:
|
||||||
DisplayError( this, _( "Not yet available..." ) );
|
LoadExcellonFiles( wxEmptyString );
|
||||||
|
DrawPanel->Refresh();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_GERBVIEW_LOAD_DCODE_FILE:
|
case ID_GERBVIEW_LOAD_DCODE_FILE:
|
||||||
|
@ -195,6 +196,88 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName )
|
||||||
|
{
|
||||||
|
wxString filetypes;
|
||||||
|
wxArrayString filenamesList;
|
||||||
|
wxFileName filename = aFullFileName;
|
||||||
|
wxString currentPath;
|
||||||
|
|
||||||
|
if( !filename.IsOk() )
|
||||||
|
{
|
||||||
|
filetypes = _( "Drill files (.drl)" );
|
||||||
|
filetypes << wxT("|");
|
||||||
|
filetypes += wxT(";*.drl;*.DRL" );
|
||||||
|
filetypes << wxT("|");
|
||||||
|
/* All filetypes */
|
||||||
|
filetypes += AllFilesWildcard;
|
||||||
|
|
||||||
|
/* Use the current working directory if the file name path does not exist. */
|
||||||
|
if( filename.DirExists() )
|
||||||
|
currentPath = filename.GetPath();
|
||||||
|
else
|
||||||
|
currentPath = wxGetCwd();
|
||||||
|
|
||||||
|
wxFileDialog dlg( this,
|
||||||
|
_( "Open Drill File" ),
|
||||||
|
currentPath,
|
||||||
|
filename.GetFullName(),
|
||||||
|
filetypes,
|
||||||
|
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR );
|
||||||
|
|
||||||
|
if( dlg.ShowModal() == wxID_CANCEL )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dlg.GetPaths( filenamesList );
|
||||||
|
currentPath = wxGetCwd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFileName filename = aFullFileName;
|
||||||
|
filenamesList.Add( aFullFileName );
|
||||||
|
currentPath = filename.GetPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read gerber files: each file is loaded on a new gerbview layer
|
||||||
|
int layer = getActiveLayer();
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ )
|
||||||
|
{
|
||||||
|
wxFileName filename = filenamesList[ii];
|
||||||
|
|
||||||
|
if( !filename.IsAbsolute() )
|
||||||
|
filename.SetPath( currentPath );
|
||||||
|
|
||||||
|
GetScreen()->SetFileName( filename.GetFullPath() );
|
||||||
|
|
||||||
|
setActiveLayer( layer, false );
|
||||||
|
|
||||||
|
if( Read_EXCELLON_File( filename.GetFullPath() ) )
|
||||||
|
{
|
||||||
|
layer = getNextAvailableLayer( layer );
|
||||||
|
|
||||||
|
if( layer == NO_AVAILABLE_LAYERS )
|
||||||
|
{
|
||||||
|
wxString msg = wxT( "No more empty layers are available. The remaining gerber " );
|
||||||
|
msg += wxT( "files will not be loaded." );
|
||||||
|
wxMessageBox( msg );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setActiveLayer( layer, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Zoom_Automatique( false );
|
||||||
|
g_SaveTime = time( NULL );
|
||||||
|
|
||||||
|
// Synchronize layers tools with actual active layer:
|
||||||
|
setActiveLayer( getActiveLayer() );
|
||||||
|
syncLayerBox();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a DCode file (not used with RX274X files , just with RS274D old files).
|
* Read a DCode file (not used with RX274X files , just with RS274D old files).
|
||||||
|
|
|
@ -407,6 +407,17 @@ public: GERBVIEW_FRAME( wxWindow* father, const wxString& title,
|
||||||
bool Read_GERBER_File( const wxString& GERBER_FullFileName,
|
bool Read_GERBER_File( const wxString& GERBER_FullFileName,
|
||||||
const wxString& D_Code_FullFileName );
|
const wxString& D_Code_FullFileName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function LoadDrllFiles
|
||||||
|
* Load a drill (EXCELLON) file or many files.
|
||||||
|
* @param aFileName - void string or file name with full path to open or empty string to
|
||||||
|
* open a new file. In this case one one file is loaded
|
||||||
|
* if void string: user will be prompted for filename(s)
|
||||||
|
* @return true if file was opened successfully.
|
||||||
|
*/
|
||||||
|
bool LoadExcellonFiles( const wxString& aFileName );
|
||||||
|
bool Read_EXCELLON_File( const wxString& aFullFileName );
|
||||||
|
|
||||||
void GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey = 0 );
|
void GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey = 0 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,10 +39,9 @@ void GERBVIEW_FRAME::ReCreateMenuBar( void )
|
||||||
|
|
||||||
filesMenu->Append( ID_GERBVIEW_LOAD_DCODE_FILE, _( "Load DCodes" ),
|
filesMenu->Append( ID_GERBVIEW_LOAD_DCODE_FILE, _( "Load DCodes" ),
|
||||||
_( "Load D-Codes File" ), FALSE );
|
_( "Load D-Codes File" ), FALSE );
|
||||||
#if 0 // TODO
|
|
||||||
filesMenu->Append( ID_GERBVIEW_LOAD_DRILL_FILE, _( "Load EXCELLON Drill File" ),
|
filesMenu->Append( ID_GERBVIEW_LOAD_DRILL_FILE, _( "Load EXCELLON Drill File" ),
|
||||||
_( "Load excellon drill file" ), FALSE );
|
_( "Load excellon drill file" ), FALSE );
|
||||||
#endif
|
|
||||||
|
|
||||||
filesMenu->Append( ID_NEW_BOARD, _( "&Clear All" ),
|
filesMenu->Append( ID_NEW_BOARD, _( "&Clear All" ),
|
||||||
_( "Clear all layers. All data will be deleted" ), FALSE );
|
_( "Clear all layers. All data will be deleted" ), FALSE );
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
* @param aSize The diameter of the round flash
|
* @param aSize The diameter of the round flash
|
||||||
* @param aLayerNegative = true if the current layer is negative
|
* @param aLayerNegative = true if the current layer is negative
|
||||||
*/
|
*/
|
||||||
static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||||
APERTURE_T aAperture,
|
APERTURE_T aAperture,
|
||||||
int Dcode_index,
|
int Dcode_index,
|
||||||
int aLayer,
|
int aLayer,
|
||||||
|
@ -138,7 +138,7 @@ static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||||
* @param aPenSize The size of the flash. Note rectangular shapes are legal.
|
* @param aPenSize The size of the flash. Note rectangular shapes are legal.
|
||||||
* @param aLayerNegative = true if the current layer is negative
|
* @param aLayerNegative = true if the current layer is negative
|
||||||
*/
|
*/
|
||||||
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
|
||||||
int Dcode_index,
|
int Dcode_index,
|
||||||
int aLayer,
|
int aLayer,
|
||||||
const wxPoint& aStart,
|
const wxPoint& aStart,
|
||||||
|
@ -725,10 +725,6 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
|
||||||
|
|
||||||
case 2: // code D2: exposure OFF (i.e. "move to")
|
case 2: // code D2: exposure OFF (i.e. "move to")
|
||||||
m_Exposure = false;
|
m_Exposure = false;
|
||||||
|
|
||||||
// D( printf( "Move to %d,%d to %d,%d\n",
|
|
||||||
// m_PreviousPos.x, m_PreviousPos.y,
|
|
||||||
// m_CurrentPos.x, m_CurrentPos.y ); )
|
|
||||||
m_PreviousPos = m_CurrentPos;
|
m_PreviousPos = m_CurrentPos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -743,9 +739,6 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
|
||||||
|
|
||||||
gbritem = new GERBER_DRAW_ITEM( pcb, this );
|
gbritem = new GERBER_DRAW_ITEM( pcb, this );
|
||||||
pcb->m_Drawings.Append( gbritem );
|
pcb->m_Drawings.Append( gbritem );
|
||||||
|
|
||||||
// D( printf( "Add flashed dcode %d layer %d at %d %d\n", dcode, activeLayer,
|
|
||||||
// m_CurrentPos.x, m_CurrentPos.y ); )
|
|
||||||
fillFlashedGBRITEM( gbritem, aperture,
|
fillFlashedGBRITEM( gbritem, aperture,
|
||||||
dcode, activeLayer, m_CurrentPos,
|
dcode, activeLayer, m_CurrentPos,
|
||||||
size, GetLayerParams().m_LayerNegative );
|
size, GetLayerParams().m_LayerNegative );
|
||||||
|
|
Loading…
Reference in New Issue