Drill files generation: add 3 structured comments in NC (Excellon) drill files and remove duplicate code.
This commit is contained in:
parent
106eaaade6
commit
0b890b4d1d
|
@ -31,6 +31,47 @@
|
||||||
#include <fctsys.h>
|
#include <fctsys.h>
|
||||||
#include <gbr_metadata.h>
|
#include <gbr_metadata.h>
|
||||||
|
|
||||||
|
wxString GbrMakeCreationDateAttributeString( GBR_NC_STRING_FORMAT aFormat )
|
||||||
|
{
|
||||||
|
// creates the CreationDate attribute:
|
||||||
|
// The attribute value must conform to the full version of the ISO 8601
|
||||||
|
// date and time format, including time and time zone. Note that this is
|
||||||
|
// the date the Gerber file was effectively created,
|
||||||
|
// not the time the project of PCB was started
|
||||||
|
wxDateTime date( wxDateTime::GetTimeNow() );
|
||||||
|
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
|
||||||
|
wxString timezone_offset; // ISO 8601 offset from UTC in timezone
|
||||||
|
timezone_offset = date.Format( "%z" ); // Extract the time zone offset
|
||||||
|
// The time zone offset format is +mm or +hhmm (or -mm or -hhmm)
|
||||||
|
// (mm = number of minutes, hh = number of hours. 1h00mn is returned as +0100)
|
||||||
|
// we want +(or -) hh:mm
|
||||||
|
if( timezone_offset.Len() > 3 ) // format +hhmm or -hhmm found
|
||||||
|
// Add separator between hours and minutes
|
||||||
|
timezone_offset.insert( 3, ":", 1 );
|
||||||
|
|
||||||
|
wxString msg;
|
||||||
|
|
||||||
|
switch( aFormat )
|
||||||
|
{
|
||||||
|
case GBR_NC_STRING_FORMAT_X2:
|
||||||
|
msg.Printf( "%%TF.CreationDate,%s%s*%%", date.FormatISOCombined(), timezone_offset );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GBR_NC_STRING_FORMAT_X1:
|
||||||
|
msg.Printf( "G04 #@! TF.CreationDate,%s%s", date.FormatISOCombined(), timezone_offset );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GBR_NC_STRING_FORMAT_GBRJOB:
|
||||||
|
msg.Printf( "\"CreationDate\": \"%s%s\"", date.FormatISOCombined(), timezone_offset );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GBR_NC_STRING_FORMAT_NCDRILL:
|
||||||
|
msg.Printf( "; #@! TF.CreationDate,%s%s", date.FormatISOCombined(), timezone_offset );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString GbrMakeProjectGUIDfromString( wxString& aText )
|
wxString GbrMakeProjectGUIDfromString( wxString& aText )
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,29 @@
|
||||||
|
|
||||||
#include <gbr_netlist_metadata.h>
|
#include <gbr_netlist_metadata.h>
|
||||||
|
|
||||||
|
/** creates the TF.CreationDate attribute:
|
||||||
|
* The attribute value must conform to the full version of the ISO 8601
|
||||||
|
* date and time format, including time and time zone. Note that this is
|
||||||
|
* the date the Gerber file is effectively created,
|
||||||
|
* not the time the project of PCB was started
|
||||||
|
* @param aFormat = string compatibility: X1, X2, GBRJOB or NC drill synthax.
|
||||||
|
* exemple of structured comment (compatible X1 gerber)
|
||||||
|
* G04 #@! TF.CreationDate,2018-11-21T08:49:16+01:00* (exemple of X1 attribute)
|
||||||
|
* exemple NC drill files
|
||||||
|
* ; #@! TF.CreationDate,2018-11-21T08:49:16+01:00* (exemple of NC drill comment)
|
||||||
|
* exemple of X2 attribute:
|
||||||
|
* %TF.CreationDate,2018-11-06T08:25:24+01:00*%
|
||||||
|
*/
|
||||||
|
enum GBR_NC_STRING_FORMAT // Options for string format in some attribute strings
|
||||||
|
{
|
||||||
|
GBR_NC_STRING_FORMAT_X1,
|
||||||
|
GBR_NC_STRING_FORMAT_X2,
|
||||||
|
GBR_NC_STRING_FORMAT_GBRJOB,
|
||||||
|
GBR_NC_STRING_FORMAT_NCDRILL
|
||||||
|
};
|
||||||
|
wxString GbrMakeCreationDateAttributeString( GBR_NC_STRING_FORMAT aFormat );
|
||||||
|
|
||||||
|
|
||||||
/** A helper function to build a project GUID using format RFC4122 Version 1 or 4
|
/** A helper function to build a project GUID using format RFC4122 Version 1 or 4
|
||||||
* from the project name, because a kicad project has no specific GUID
|
* from the project name, because a kicad project has no specific GUID
|
||||||
* RFC4122 is used mainly for its syntax, because fields have no meaning for Gerber files
|
* RFC4122 is used mainly for its syntax, because fields have no meaning for Gerber files
|
||||||
|
|
|
@ -45,9 +45,11 @@
|
||||||
|
|
||||||
#include <pcbplot.h>
|
#include <pcbplot.h>
|
||||||
#include <pcbnew.h>
|
#include <pcbnew.h>
|
||||||
|
#include <class_board.h>
|
||||||
#include <gendrill_Excellon_writer.h>
|
#include <gendrill_Excellon_writer.h>
|
||||||
#include <wildcards_and_files_ext.h>
|
#include <wildcards_and_files_ext.h>
|
||||||
#include <reporter.h>
|
#include <reporter.h>
|
||||||
|
#include <gbr_metadata.h>
|
||||||
|
|
||||||
// Comment/uncomment this to write or not a comment
|
// Comment/uncomment this to write or not a comment
|
||||||
// in drill file when PTH and NPTH are merged to flag
|
// in drill file when PTH and NPTH are merged to flag
|
||||||
|
@ -126,7 +128,7 @@ void EXCELLON_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createDrillFile( file );
|
createDrillFile( file, pair, doing_npth );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +138,8 @@ void EXCELLON_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int EXCELLON_WRITER::createDrillFile( FILE* aFile )
|
int EXCELLON_WRITER::createDrillFile( FILE* aFile, DRILL_LAYER_PAIR aLayerPair,
|
||||||
|
bool aGenerateNPTH_list )
|
||||||
{
|
{
|
||||||
m_file = aFile;
|
m_file = aFile;
|
||||||
|
|
||||||
|
@ -147,7 +150,7 @@ int EXCELLON_WRITER::createDrillFile( FILE* aFile )
|
||||||
|
|
||||||
LOCALE_IO dummy; // Use the standard notation for double numbers
|
LOCALE_IO dummy; // Use the standard notation for double numbers
|
||||||
|
|
||||||
writeEXCELLONHeader();
|
writeEXCELLONHeader( aLayerPair, aGenerateNPTH_list );
|
||||||
|
|
||||||
holes_count = 0;
|
holes_count = 0;
|
||||||
|
|
||||||
|
@ -440,18 +443,19 @@ void EXCELLON_WRITER::writeCoordinates( char* aLine, double aCoordX, double aCoo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EXCELLON_WRITER::writeEXCELLONHeader()
|
void EXCELLON_WRITER::writeEXCELLONHeader( DRILL_LAYER_PAIR aLayerPair,
|
||||||
|
bool aGenerateNPTH_list)
|
||||||
{
|
{
|
||||||
fputs( "M48\n", m_file ); // The beginning of a header
|
fputs( "M48\n", m_file ); // The beginning of a header
|
||||||
|
|
||||||
if( !m_minimalHeader )
|
if( !m_minimalHeader )
|
||||||
{
|
{
|
||||||
// The next 2 lines in EXCELLON files are comments:
|
// The next lines in EXCELLON files are comments:
|
||||||
wxString msg;
|
wxString msg;
|
||||||
msg << wxT("KiCad") << wxT( " " ) << GetBuildVersion();
|
msg << "KiCad " << GetBuildVersion();
|
||||||
|
|
||||||
fprintf( m_file, ";DRILL file {%s} date %s\n", TO_UTF8( msg ), TO_UTF8( DateAndTime() ) );
|
fprintf( m_file, "; DRILL file {%s} date %s\n", TO_UTF8( msg ), TO_UTF8( DateAndTime() ) );
|
||||||
msg = wxT( ";FORMAT={" );
|
msg = "; FORMAT={";
|
||||||
|
|
||||||
// Print precision:
|
// Print precision:
|
||||||
// Note in decimal format the precision is not used.
|
// Note in decimal format the precision is not used.
|
||||||
|
@ -459,10 +463,10 @@ void EXCELLON_WRITER::writeEXCELLONHeader()
|
||||||
if( m_zeroFormat != DECIMAL_FORMAT )
|
if( m_zeroFormat != DECIMAL_FORMAT )
|
||||||
msg << m_precision.GetPrecisionString();
|
msg << m_precision.GetPrecisionString();
|
||||||
else
|
else
|
||||||
msg << wxT( "-:-" ); // in decimal format the precision is irrelevant
|
msg << "-:-"; // in decimal format the precision is irrelevant
|
||||||
|
|
||||||
msg << wxT( "/ absolute / " );
|
msg << "/ absolute / ";
|
||||||
msg << ( m_unitsMetric ? wxT( "metric" ) : wxT( "inch" ) );
|
msg << ( m_unitsMetric ? "metric" : "inch" );
|
||||||
|
|
||||||
/* Adding numbers notation format.
|
/* Adding numbers notation format.
|
||||||
* this is same as m_Choice_Zeros_Format strings, but NOT translated
|
* this is same as m_Choice_Zeros_Format strings, but NOT translated
|
||||||
|
@ -475,14 +479,34 @@ void EXCELLON_WRITER::writeEXCELLONHeader()
|
||||||
|
|
||||||
const wxString zero_fmt[4] =
|
const wxString zero_fmt[4] =
|
||||||
{
|
{
|
||||||
wxT( "decimal" ),
|
"decimal",
|
||||||
wxT( "suppress leading zeros" ),
|
"suppress leading zeros",
|
||||||
wxT( "suppress trailing zeros" ),
|
"suppress trailing zeros",
|
||||||
wxT( "keep zeros" )
|
"keep zeros"
|
||||||
};
|
};
|
||||||
|
|
||||||
msg << zero_fmt[m_zeroFormat] << wxT( "}\n" );
|
msg << zero_fmt[m_zeroFormat] << "}\n";
|
||||||
fputs( TO_UTF8( msg ), m_file );
|
fputs( TO_UTF8( msg ), m_file );
|
||||||
|
|
||||||
|
// add the structured comment TF.CreationDate:
|
||||||
|
// The attribute value must conform to the full version of the ISO 8601
|
||||||
|
msg = GbrMakeCreationDateAttributeString( GBR_NC_STRING_FORMAT_NCDRILL ) + "\n";
|
||||||
|
fputs( TO_UTF8( msg ), m_file );
|
||||||
|
|
||||||
|
// Add the application name that created the drill file
|
||||||
|
msg = "; #@! TF.GenerationSoftware,Kicad,Pcbnew,";
|
||||||
|
msg << GetBuildVersion() << "\n";
|
||||||
|
fputs( TO_UTF8( msg ), m_file );
|
||||||
|
|
||||||
|
if( !m_merge_PTH_NPTH )
|
||||||
|
{
|
||||||
|
// Add the standard X2 FileFunction for drill files
|
||||||
|
// TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH]
|
||||||
|
msg = BuildFileFunctionAttributeString( aLayerPair, aGenerateNPTH_list, true )
|
||||||
|
+ "\n";
|
||||||
|
fputs( TO_UTF8( msg ), m_file );
|
||||||
|
}
|
||||||
|
|
||||||
fputs( "FMAT,2\n", m_file ); // Use Format 2 commands (version used since 1979)
|
fputs( "FMAT,2\n", m_file ); // Use Format 2 commands (version used since 1979)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,17 +114,22 @@ private:
|
||||||
* @param aFile = an opened file to write to will be closed by CreateDrillFile
|
* @param aFile = an opened file to write to will be closed by CreateDrillFile
|
||||||
* @return hole count
|
* @return hole count
|
||||||
*/
|
*/
|
||||||
int createDrillFile( FILE * aFile );
|
int createDrillFile( FILE * aFile, DRILL_LAYER_PAIR aLayerPair,
|
||||||
|
bool aGenerateNPTH_list );
|
||||||
|
|
||||||
|
|
||||||
/* Print the DRILL file header. The full header is:
|
/* Print the DRILL file header. The full header is somethink like:
|
||||||
* M48
|
* M48
|
||||||
* ;DRILL file {PCBNEW (2007-11-29-b)} date 17/1/2008-21:02:35
|
* ;DRILL file {PCBNEW (2007-11-29-b)} date 17/1/2008-21:02:35
|
||||||
* ;FORMAT={ <precision> / absolute / <units> / <numbers format>}
|
* ;FORMAT={ <precision> / absolute / <units> / <numbers format>}
|
||||||
|
* ; #@! TF.FileFunction,Plated,1,4,PTH
|
||||||
|
* ; #@! TF.CreationDate,2018-11-23T15:59:51+01:00
|
||||||
|
* ; #@! TF.GenerationSoftware,Kicad,Pcbnew,2017.04
|
||||||
* FMAT,2
|
* FMAT,2
|
||||||
* INCH,TZ
|
* INCH,TZ
|
||||||
*/
|
*/
|
||||||
void writeEXCELLONHeader();
|
void writeEXCELLONHeader( DRILL_LAYER_PAIR aLayerPair,
|
||||||
|
bool aGenerateNPTH_list);
|
||||||
|
|
||||||
void writeEXCELLONEndOfFile();
|
void writeEXCELLONEndOfFile();
|
||||||
|
|
||||||
|
|
|
@ -342,3 +342,88 @@ void GENDRILL_WRITER_BASE::CreateMapFilesSet( const wxString& aPlotDirectory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const wxString GENDRILL_WRITER_BASE::BuildFileFunctionAttributeString(
|
||||||
|
DRILL_LAYER_PAIR aLayerPair, bool aIsNpth, bool aCompatNCdrill ) const
|
||||||
|
{
|
||||||
|
// Build a wxString containing the .FileFunction attribute for drill files.
|
||||||
|
// %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
|
||||||
|
wxString text;
|
||||||
|
|
||||||
|
if( aCompatNCdrill )
|
||||||
|
text = "; #@! ";
|
||||||
|
else
|
||||||
|
text = "%";
|
||||||
|
|
||||||
|
text << "TF.FileFunction,";
|
||||||
|
|
||||||
|
if( aIsNpth )
|
||||||
|
text << "NonPlated,";
|
||||||
|
else
|
||||||
|
text << "Plated,";
|
||||||
|
|
||||||
|
int layer1 = aLayerPair.first;
|
||||||
|
int layer2 = aLayerPair.second;
|
||||||
|
// In Gerber files, layers num are 1 to copper layer count instead of F_Cu to B_Cu
|
||||||
|
// (0 to copper layer count-1)
|
||||||
|
// Note also for a n copper layers board, gerber layers num are 1 ... n
|
||||||
|
layer1 += 1;
|
||||||
|
|
||||||
|
if( layer2 == B_Cu )
|
||||||
|
layer2 = m_pcb->GetCopperLayerCount();
|
||||||
|
else
|
||||||
|
layer2 += 1;
|
||||||
|
|
||||||
|
text << layer1 << ",";
|
||||||
|
text << layer2 << ",";
|
||||||
|
|
||||||
|
// Now add PTH or NPTH or Blind or Buried attribute
|
||||||
|
int toplayer = 1;
|
||||||
|
int bottomlayer = m_pcb->GetCopperLayerCount();
|
||||||
|
|
||||||
|
if( aIsNpth )
|
||||||
|
text << "NPTH";
|
||||||
|
else if( layer1 == toplayer && layer2 == bottomlayer )
|
||||||
|
text << "PTH";
|
||||||
|
else if( layer1 == toplayer || layer2 == bottomlayer )
|
||||||
|
text << "Blind";
|
||||||
|
else
|
||||||
|
text << "Buried";
|
||||||
|
|
||||||
|
// In NC drill file, these previous parameters should be enough:
|
||||||
|
if( aCompatNCdrill )
|
||||||
|
return text;
|
||||||
|
|
||||||
|
|
||||||
|
// Now add Drill or Route or Mixed:
|
||||||
|
// file containing only round holes have Drill attribute
|
||||||
|
// file containing only oblong holes have Routed attribute
|
||||||
|
// file containing both holes have Mixed attribute
|
||||||
|
bool hasOblong = false;
|
||||||
|
bool hasDrill = false;
|
||||||
|
|
||||||
|
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
||||||
|
{
|
||||||
|
const HOLE_INFO& hole_descr = m_holeListBuffer[ii];
|
||||||
|
|
||||||
|
if( hole_descr.m_Hole_Shape ) // m_Hole_Shape not 0 is an oblong hole)
|
||||||
|
hasOblong = true;
|
||||||
|
else
|
||||||
|
hasDrill = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hasOblong && hasDrill )
|
||||||
|
text << ",Mixed";
|
||||||
|
else if( hasDrill )
|
||||||
|
text << ",Drill";
|
||||||
|
else if( hasOblong )
|
||||||
|
text << ",Route";
|
||||||
|
|
||||||
|
// else: empty file.
|
||||||
|
|
||||||
|
// End of .FileFunction attribute:
|
||||||
|
text << "*%";
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
|
@ -340,6 +340,20 @@ protected:
|
||||||
*/
|
*/
|
||||||
virtual const wxString getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
virtual const wxString getDrillFileName( DRILL_LAYER_PAIR aPair, bool aNPTH,
|
||||||
bool aMerge_PTH_NPTH ) const;
|
bool aMerge_PTH_NPTH ) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a wxString containing the .FileFunction attribute.
|
||||||
|
* the standard X2 FileFunction for drill files is
|
||||||
|
* %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
|
||||||
|
* There is no X1 version, as the Gerber drill files uses only X2 format
|
||||||
|
* There is a compatible NC drill version.
|
||||||
|
* @param aLayerPair is the layer pair (Drill from rom first layer to second layer)
|
||||||
|
* @param aIsNpth is true when generating NPTH drill file
|
||||||
|
* @param aCompatNCdrill is true when generating NC (Excellon) compatible drill file
|
||||||
|
*/
|
||||||
|
const wxString BuildFileFunctionAttributeString( DRILL_LAYER_PAIR aLayerPair,
|
||||||
|
bool aIsNpth, bool aCompatNCdrill = false ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #define GENDRILL_FILE_WRITER_BASE_H
|
#endif // #define GENDRILL_FILE_WRITER_BASE_H
|
||||||
|
|
|
@ -95,13 +95,13 @@ void GERBER_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||||
{
|
{
|
||||||
wxString fullFilename = fn.GetFullPath();
|
wxString fullFilename = fn.GetFullPath();
|
||||||
|
|
||||||
int result = createDrillFile( fullFilename, doing_npth, pair.first, pair.second );
|
int result = createDrillFile( fullFilename, doing_npth, pair );
|
||||||
|
|
||||||
if( result < 0 )
|
if( result < 0 )
|
||||||
{
|
{
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
{
|
{
|
||||||
msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullFilename ) );
|
msg.Printf( _( "** Unable to create %s **\n" ), fullFilename );
|
||||||
aReporter->Report( msg );
|
aReporter->Report( msg );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -110,7 +110,7 @@ void GERBER_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||||
{
|
{
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
{
|
{
|
||||||
msg.Printf( _( "Create file %s\n" ), GetChars( fullFilename ) );
|
msg.Printf( _( "Create file %s\n" ), fullFilename );
|
||||||
aReporter->Report( msg );
|
aReporter->Report( msg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ void GERBER_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory,
|
||||||
static void convertOblong2Segment( wxSize aSize, double aOrient, wxPoint& aStart, wxPoint& aEnd );
|
static void convertOblong2Segment( wxSize aSize, double aOrient, wxPoint& aStart, wxPoint& aEnd );
|
||||||
|
|
||||||
int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth,
|
int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth,
|
||||||
int aLayer1, int aLayer2 )
|
DRILL_LAYER_PAIR aLayerPair )
|
||||||
{
|
{
|
||||||
int holes_count;
|
int holes_count;
|
||||||
|
|
||||||
|
@ -148,68 +148,7 @@ int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth,
|
||||||
|
|
||||||
// Add the standard X2 FileFunction for drill files
|
// Add the standard X2 FileFunction for drill files
|
||||||
// %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
|
// %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
|
||||||
wxString text( "%TF.FileFunction," );
|
wxString text = BuildFileFunctionAttributeString( aLayerPair, aIsNpth );
|
||||||
|
|
||||||
if( aIsNpth )
|
|
||||||
text << "NonPlated,";
|
|
||||||
else
|
|
||||||
text << "Plated,";
|
|
||||||
|
|
||||||
// In Gerber files, layers num are 1 to copper layer count instead of F_Cu to B_Cu
|
|
||||||
// (0 to copper layer count-1)
|
|
||||||
// Note also for a n copper layers board, gerber layers num are 1 ... n
|
|
||||||
aLayer1 += 1;
|
|
||||||
|
|
||||||
if( aLayer2 == B_Cu )
|
|
||||||
aLayer2 = m_pcb->GetCopperLayerCount();
|
|
||||||
else
|
|
||||||
aLayer2 += 1;
|
|
||||||
|
|
||||||
text << aLayer1 << ",";
|
|
||||||
text << aLayer2 << ",";
|
|
||||||
|
|
||||||
// Now add PTH or NPTH or Blind or Buried attribute
|
|
||||||
int toplayer = 1;
|
|
||||||
int bottomlayer = m_pcb->GetCopperLayerCount();
|
|
||||||
|
|
||||||
if( aIsNpth )
|
|
||||||
text << "NPTH";
|
|
||||||
else if( aLayer1 == toplayer && aLayer2 == bottomlayer )
|
|
||||||
text << "PTH";
|
|
||||||
else if( aLayer1 == toplayer || aLayer2 == bottomlayer )
|
|
||||||
text << "Blind";
|
|
||||||
else
|
|
||||||
text << "Buried";
|
|
||||||
|
|
||||||
// Now add Drill or Route or Mixed:
|
|
||||||
// file containing only round holes have Drill attribute
|
|
||||||
// file containing only oblong holes have Routed attribute
|
|
||||||
// file containing both holes have Mixed attribute
|
|
||||||
bool hasOblong = false;
|
|
||||||
bool hasDrill = false;
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
|
|
||||||
{
|
|
||||||
HOLE_INFO& hole_descr = m_holeListBuffer[ii];
|
|
||||||
|
|
||||||
if( hole_descr.m_Hole_Shape ) // m_Hole_Shape not 0 is an oblong hole)
|
|
||||||
hasOblong = true;
|
|
||||||
else
|
|
||||||
hasDrill = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( hasOblong && hasDrill )
|
|
||||||
text << ",Mixed";
|
|
||||||
else if( hasDrill )
|
|
||||||
text << ",Drill";
|
|
||||||
else if( hasOblong )
|
|
||||||
text << ",Route";
|
|
||||||
|
|
||||||
// else: empty file.
|
|
||||||
|
|
||||||
// End of .FileFunction attribute:
|
|
||||||
text << "*%";
|
|
||||||
|
|
||||||
plotter.AddLineToHeader( text );
|
plotter.AddLineToHeader( text );
|
||||||
|
|
||||||
// Add file polarity (positive)
|
// Add file polarity (positive)
|
||||||
|
|
|
@ -84,12 +84,11 @@ private:
|
||||||
* Creates an Excellon drill file
|
* Creates an Excellon drill file
|
||||||
* @param aFullFilename = the full filename
|
* @param aFullFilename = the full filename
|
||||||
* @param aIsNpth = true for a NPTH file, false for a PTH file
|
* @param aIsNpth = true for a NPTH file, false for a PTH file
|
||||||
* @param aLayer1 = the first board layer
|
* @param aLayerPair = first board layer and the last board layer for this drill file
|
||||||
* @param aLayer2 = the last board layer
|
|
||||||
* for blind buried vias, they are not always top and bottom layers
|
* for blind buried vias, they are not always top and bottom layers
|
||||||
* @return hole count, or -1 if the file cannot be created
|
* @return hole count, or -1 if the file cannot be created
|
||||||
*/
|
*/
|
||||||
int createDrillFile( wxString& aFullFilename, bool aIsNpth, int aLayer1, int aLayer2 );
|
int createDrillFile( wxString& aFullFilename, bool aIsNpth, DRILL_LAYER_PAIR aLayerPair );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a filename which identify the drill file function.
|
* @return a filename which identify the drill file function.
|
||||||
|
|
|
@ -155,20 +155,10 @@ void GERBER_JOBFILE_WRITER::addJSONHeader()
|
||||||
addJSONObject( text );
|
addJSONObject( text );
|
||||||
closeBlockWithSep();
|
closeBlockWithSep();
|
||||||
|
|
||||||
// creates the TF.CreationDate ext:
|
// creates the CreationDate attribute:
|
||||||
// The attribute value must conform to the full version of the ISO 8601
|
// The attribute value must conform to the full version of the ISO 8601
|
||||||
// date and time format, including time and time zone. Note that this is
|
// date and time format, including time and time zone.
|
||||||
// the date the Gerber file was effectively created,
|
text = GbrMakeCreationDateAttributeString( GBR_NC_STRING_FORMAT_GBRJOB ) + "\n";
|
||||||
// not the time the project of PCB was started
|
|
||||||
wxDateTime date( wxDateTime::GetTimeNow() );
|
|
||||||
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
|
|
||||||
wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset
|
|
||||||
// The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours)
|
|
||||||
// we want +(or -) hh:mm
|
|
||||||
if( msg.Len() > 3 )
|
|
||||||
msg.insert( 3, ":", 1 );
|
|
||||||
|
|
||||||
text.Printf( wxT( "\"CreationDate\": \"%s%s\"\n" ),date.FormatISOCombined(), msg );
|
|
||||||
addJSONObject( text );
|
addJSONObject( text );
|
||||||
|
|
||||||
closeBlockWithSep();
|
closeBlockWithSep();
|
||||||
|
|
|
@ -287,20 +287,11 @@ void AddGerberX2Header( PLOTTER * aPlotter,
|
||||||
text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() );
|
text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() );
|
||||||
aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
|
aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
|
||||||
|
|
||||||
// creates the TF.CreationDate ext:
|
// creates the TF.CreationDate attribute:
|
||||||
// The attribute value must conform to the full version of the ISO 8601
|
text = GbrMakeCreationDateAttributeString( aUseX1CompatibilityMode ?
|
||||||
// date and time format, including time and time zone. Note that this is
|
GBR_NC_STRING_FORMAT_X1 :
|
||||||
// the date the Gerber file was effectively created,
|
GBR_NC_STRING_FORMAT_X2 );
|
||||||
// not the time the project of PCB was started
|
aPlotter->AddLineToHeader( text );
|
||||||
wxDateTime date( wxDateTime::GetTimeNow() );
|
|
||||||
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
|
|
||||||
wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset
|
|
||||||
// The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours)
|
|
||||||
// we want +(or -) hh:mm
|
|
||||||
if( msg.Len() > 3 )
|
|
||||||
msg.insert( 3, ":", 1 ),
|
|
||||||
text.Printf( wxT( "%%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) );
|
|
||||||
aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) );
|
|
||||||
|
|
||||||
// Creates the TF,.ProjectId. Format is (from Gerber file format doc):
|
// Creates the TF,.ProjectId. Format is (from Gerber file format doc):
|
||||||
// %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
|
// %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
|
||||||
|
@ -312,7 +303,7 @@ void AddGerberX2Header( PLOTTER * aPlotter,
|
||||||
// <project GUID> is a string which is an unique id of a project.
|
// <project GUID> is a string which is an unique id of a project.
|
||||||
// However Kicad does not handle such a project GUID, so it is built from the board name
|
// However Kicad does not handle such a project GUID, so it is built from the board name
|
||||||
wxFileName fn = aBoard->GetFileName();
|
wxFileName fn = aBoard->GetFileName();
|
||||||
msg = fn.GetFullName();
|
wxString msg = fn.GetFullName();
|
||||||
|
|
||||||
// Build a <project GUID>, from the board name
|
// Build a <project GUID>, from the board name
|
||||||
wxString guid = GbrMakeProjectGUIDfromString( msg );
|
wxString guid = GbrMakeProjectGUIDfromString( msg );
|
||||||
|
|
Loading…
Reference in New Issue