From: Lionel S. C. <lio...@gm...> - 2015-04-19 03:31:27
|
commit e8354170dffa5dc843454f461ff26642e83422ed Author: Lionel SC <co...@di...> Date: Sun Apr 19 05:28:24 2015 +0200 Add m4 output and the first m4 template (gerber.m4) Probably not perfect, but it does the job diff --git a/m4_exporter.cpp b/m4_exporter.cpp new file mode 100644 index 0000000..43474d5 --- /dev/null +++ b/m4_exporter.cpp @@ -0,0 +1,302 @@ +/*!\defgroup M4_EXPORTER*/ +/******************************************************************************/ +/*! + \file m4_exporter.cpp + \brief + + \version + based on 1.1.4 - 2009, 2010 Patrick Birnzain <pbi...@us...> + + \ingroup M4_EXPORTER + */ +/******************************************************************************/ + +#include "m4_exporter.hpp" +#include <boost/foreach.hpp> +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <iomanip> +using namespace std; + +#include <glibmm/miscutils.h> +using Glib::build_filename; + +/******************************************************************************/ +/* + */ +/******************************************************************************/ +M4_Exporter::M4_Exporter(shared_ptr<Board> board) + : Exporter(board), dpi(board->get_dpi()), quantization_error( 2.0 / dpi ) { + this->board = board; + bDoSVG = false; +} + +/******************************************************************************/ +/* + */ +/******************************************************************************/ +void M4_Exporter::set_svg_exporter(shared_ptr<SVG_Exporter> svgexpo) { + this->svgexpo = svgexpo; + bDoSVG = true; +} + +/******************************************************************************/ +/* + */ +/******************************************************************************/ +void M4_Exporter::add_header(string header) { + this->header.push_back(header); +} + +/******************************************************************************/ +/* + */ +/******************************************************************************/ +void M4_Exporter::export_all(boost::program_options::variables_map& options) { + + bMetricinput = options["metric"].as<bool>(); //set flag for metric input + bMetricoutput = options["metricoutput"].as<bool>(); //set flag for metric output + bMirrored = options["mirror-absolute"].as<bool>(); //set flag + bCutfront = options["cut-front"].as<bool>(); //set flag + bFrontAutoleveller = options["al-front"].as<bool>(); + bBackAutoleveller = options["al-back"].as<bool>(); + string outputdir = options["output-dir"].as<string>(); + + //set imperial/metric conversion factor for output coordinates depending on metricoutput option + cfactor = bMetricoutput ? 25.4 : 1; + + if( options["zero-start"].as<bool>() ) + { + xoffset = board->get_min_x(); + yoffset = board->get_min_y(); + } + else + { + xoffset = 0; + yoffset = 0; + } + + if( options.count("g64") ) + g64 = options["g64"].as<double>(); + else + g64 = quantization_error * cfactor; // set maximum deviation to 2 pixels to ensure smooth movement + + if( bFrontAutoleveller || bBackAutoleveller ) + leveller = new autoleveller ( options, quantization_error, xoffset, yoffset ); + + if (options["bridges"].as<double>() > 0 && options["bridgesnum"].as<unsigned int>() != 0) + bBridges = true; + else + bBridges = false; + + BOOST_FOREACH( string layername, board->list_layers() ) { + std::stringstream option_name; + option_name << layername << "-output"; + string of_name = build_filename(outputdir, options[option_name.str()].as<string>()); + of_name += ".m4"; + cerr << "Exporting " << layername << "... "; + export_layer(board->get_layer(layername), of_name); + cerr << "DONE." << " (Height: " << board->get_height() * cfactor + << (bMetricoutput ? "mm" : "in") << " Width: " + << board->get_width() * cfactor << (bMetricoutput ? "mm" : "in") + << ")" << endl; + } +} + +/******************************************************************************/ +/* +/* +/******************************************************************************/ +void M4_Exporter::export_layer(shared_ptr<Layer> layer, string of_name) { + + string layername = layer->get_name(); + shared_ptr<RoutingMill> mill = layer->get_manufacturer(); + bool bSvgOnce = TRUE; + bool bAutolevelNow; + vector<unsigned int> bridgesIndexes; + vector<unsigned int>::const_iterator currentBridge; + vector<shared_ptr<icoords> > toolpaths = layer->get_toolpaths(); + + // open output file + std::ofstream of; + of.open(of_name.c_str()); + + // write header to .m4 file + BOOST_FOREACH( string s, header ) { + of << "m4_header(`" << s << "')\n"; + } + + if( ( bFrontAutoleveller && layername == "front" ) || + ( bBackAutoleveller && layername == "back" ) ) { + of << "define(m4_autoleveller)dnl\n"; + bAutolevelNow = true; + } + else { + of << "define(m4_noautoleveller)dnl\n"; + bAutolevelNow = false; + } + + of.setf(ios_base::fixed); //write floating-point values in fixed-point notation + of.precision(5); //Set floating-point decimal precision + of << setw(7); //Sets the field width to be used on output operations. + of << "define(m4_digitdot," << 2 << ")dnl\n"; + of << "define(m4_dotdigit," << 5 << ")dnl\n"; + + if (bMetricoutput) { + of << "define(m4_metric)dnl\n"; + } else { + of << "define(m4_imperial)dnl\n"; + } + + of << "define(m4_spindlespeed," << mill->speed << ")dnl\n"; + of << "define(m4_maxdeviation," << g64 << ")dnl\n"; + of << "define(m4_feedrate," << mill->feed * cfactor << ")dnl\n"; + of << "define(m4_plungerate," << mill->feed/2 * cfactor << ")dnl\n"; + of << "define(m4_zsafe," << mill->zsafe * cfactor << ")dnl\n"; + of << "define(m4_zwork," << mill->zwork * cfactor << ")dnl\n"; + + if( bAutolevelNow ) { + if( !leveller->prepareWorkarea( toolpaths ) ) { + std::cerr << "Required number of probe points (" << leveller->requiredProbePoints() << + ") exceeds the maximum number (" << leveller->maxProbePoints() << "). " + "Reduce either al-x or al-y." << std::endl; + exit(EXIT_FAILURE); + } + + leveller->header( of ); + } + + //SVG EXPORTER + if (bDoSVG) { + //choose a color + svgexpo->set_rand_color(); + } + + of << "m4_preamble" << "\n"; //insert external preamble + + // contours + BOOST_FOREACH( shared_ptr<icoords> path, toolpaths ) { + + of << "m4_move(" << ( path->begin()->first - xoffset ) * cfactor << "," << ( path->begin()->second - yoffset ) * cfactor << ")\n"; + + //SVG EXPORTER + if (bDoSVG) { + svgexpo->move_to(path->begin()->first, path->begin()->second); + bSvgOnce = TRUE; + } + + /* if we're cutting, perhaps do it in multiple steps, but do isolations just once. + * i know this is partially repetitive, but this way it's easier to read + */ + shared_ptr<Cutter> cutter = boost::dynamic_pointer_cast<Cutter>(mill); + + if (cutter && cutter->do_steps) { + if( bBridges ) { + try { + bridgesIndexes = outline_bridges::makeBridges( path, cutter->bridges_num, cutter->bridges_width + cutter->tool_diameter ); + currentBridge = bridgesIndexes.begin(); + if ( bridgesIndexes.size() != cutter->bridges_num ) + cerr << "Can't create " << cutter->bridges_num << " bridges on this layer, only " << bridgesIndexes.size() << " will be created." << endl; + } catch ( outline_bridges_exception &exc ) { + cerr << "Error while adding outline bridges. Outline bridges on this path won't be created." << endl; + } + } + + //-------------------------------------------------------------------- + //cutting (outline) + + double z_step = cutter->stepsize; + double z = mill->zwork + z_step * abs(int(mill->zwork / z_step)); + + while (z >= mill->zwork) { + of << "m4_plunge("<< z << ")\n"; + + icoords::iterator iter = path->begin(); + icoords::iterator last = path->end(); // initializing to quick & dirty sentinel value + icoords::iterator peek; + while (iter != path->end()) { + peek = iter + 1; + + if (mill->optimise //Already optimised (also includes the bridge case) + || last == path->end() //First + || peek == path->end() //Last + || !aligned(last, iter, peek) ) { //Not aligned + of << "m4_mill(" << ( iter->first - xoffset ) * cfactor << "," << ( iter->second - yoffset ) * cfactor << ")\n"; + if (bDoSVG) { + if (bSvgOnce) + svgexpo->line_to(iter->first, iter->second); + } + + if( bBridges && currentBridge != bridgesIndexes.end() ) { + if( *currentBridge == iter - path->begin() ) + of << "m4_Z(" << cutter->bridges_height * cfactor << ")\n"; + else if( *currentBridge == last - path->begin() ) { + of << "m4_Z(" << z * cfactor << ")\n"; + ++currentBridge; + } + } + } + + last = iter; + ++iter; + } + //SVG EXPORTER + if (bDoSVG) { + svgexpo->close_path(); + bSvgOnce = FALSE; + } + z -= z_step; + } + } else { + //-------------------------------------------------------------------- + // isolating (front/backside) + if( bAutolevelNow ) { + leveller->setLastChainPoint( icoordpair( ( path->begin()->first - xoffset ) * cfactor, ( path->begin()->second - yoffset ) * cfactor ) ); + of << "m4_G01corr(" << ( path->begin()->first - xoffset ) * cfactor << "," << ( path->begin()->second - yoffset ) * cfactor << ")\n"; + } + + icoords::iterator iter = path->begin(); + icoords::iterator last = path->end(); // initializing to quick & dirty sentinel value + icoords::iterator peek; + while (iter != path->end()) { + peek = iter + 1; + if (mill->optimise //When simplifypath is performed, no further optimisation is required + || last == path->end() //First + || peek == path->end() //Last + || !aligned(last, iter, peek) ) { //Not aligned + /* no need to check for "they are on one axis but iter is outside of last and peek" because that's impossible from how they are generated */ + if( bAutolevelNow ) + of << "m4_addChainPoint(" << ( iter->first - xoffset ) * cfactor << "," << ( iter->second - yoffset ) * cfactor << ")\n"; + else + of << "m4_mill(" << ( iter->first - xoffset ) * cfactor << "," << ( iter->second - yoffset ) * cfactor << ")\n"; + //SVG EXPORTER + if (bDoSVG) + if (bSvgOnce) + svgexpo->line_to(iter->first, iter->second); + } + + last = iter; + ++iter; + } + //SVG EXPORTER + if (bDoSVG) { + svgexpo->close_path(); + bSvgOnce = FALSE; + } + } + } + + of << "m4_postamble" << "\n"; + + if( bAutolevelNow ) { + leveller->footer( of ); + } + + of.close(); + + //SVG EXPORTER + if (bDoSVG) { + svgexpo->stroke(); + } +} + diff --git a/m4_exporter.hpp b/m4_exporter.hpp new file mode 100644 index 0000000..d4629a4 --- /dev/null +++ b/m4_exporter.hpp @@ -0,0 +1,89 @@ +/*!\defgroup M4_EXPORTER*/ +/******************************************************************************/ +/*! + \file m4_exporter.hpp + \brief + + \version + based on latest 1.1.4 - 2009, 2010 Patrick Birnzain <pbi...@us...> + + \ingroup M4_EXPORTER + */ +/******************************************************************************/ + +#ifndef M4EXPORTER_H +#define M4EXPORTER_H + +#include <vector> +using std::vector; + +#include <string> +using std::string; +using std::pair; + +#include <fstream> +using std::ofstream; + +#include <boost/shared_ptr.hpp> +using boost::shared_ptr; + +#include <boost/program_options.hpp> + +#include "coord.hpp" +#include "mill.hpp" +#include "exporter.hpp" +#include "svg_exporter.hpp" +#include "autoleveller.hpp" +#ifndef Included_OutlineBridges_H +#include "outline_bridges.hpp" +#endif + +/******************************************************************************/ +/* + */ +/******************************************************************************/ +class M4_Exporter: public Exporter { +public: + M4_Exporter(shared_ptr<Board> board); + /* virtual void add_path( shared_ptr<icoords> ); */ + /* virtual void add_path( vector< shared_ptr<icoords> > ); */ + void add_header(string); + void export_all(boost::program_options::variables_map&); + void set_svg_exporter(shared_ptr<SVG_Exporter> svgexpo); + void set_preamble(string); + void set_postamble(string); + +protected: + void export_layer(shared_ptr<Layer> layer, string of_name); + inline bool aligned(icoords::const_iterator p0, icoords::const_iterator p1, icoords::const_iterator p2) { + return ( (p0->first == p1->first) && (p1->first == p2->first) ) || //x-aligned + ( (p0->second == p1->second) && (p1->second == p2->second) ); //y-aligned + } + + bool bDoSVG; //!< if true, export svg + shared_ptr<SVG_Exporter> svgexpo; + shared_ptr<Board> board; + vector<string> header; + string preamble; //!< Preamble from command line (user file) + string postamble; //!< Postamble from command line (user file) + + double g64; //!< maximum deviation from commanded toolpath + double cfactor; //!< imperial/metric conversion factor for output file + bool bMetricinput; //!< if true, input parameters are in metric units + bool bMetricoutput; //!< if true, metric g-code output + bool bMirrored; //!< if true, mirrored along y axis + bool bCutfront; //!< if true, the outline will be cut from front + bool bBridges; + const unsigned int dpi; + const double quantization_error; + + + autoleveller *leveller; + bool bFrontAutoleveller; + bool bBackAutoleveller; + + double xoffset; + double yoffset; +}; + +#endif // M4EXPORTER_H diff --git a/main.cpp b/main.cpp index a2edd6a..7c1053a 100644 --- a/main.cpp +++ b/main.cpp @@ -64,6 +64,7 @@ using Glib::build_filename; #include "gerberimporter.hpp" #include "surface.hpp" #include "ngc_exporter.hpp" +#include "m4_exporter.hpp" #include "board.hpp" #include "drill.hpp" #include "options.hpp" @@ -318,24 +319,44 @@ int main(int argc, char* argv[]) { svgexpo->create_svg( build_filename(outputdir, vm["svg"].as<string>()) ); } - shared_ptr<NGC_Exporter> exporter(new NGC_Exporter(board)); - exporter->add_header(PACKAGE_STRING); - - if (vm.count("preamble") || vm.count("preamble-text")) { - exporter->set_preamble(preamble); - } - - if (vm.count("postamble")) { - exporter->set_postamble(postamble); - } - - //SVG EXPORTER - if (vm.count("svg")) { - exporter->set_svg_exporter(svgexpo); + if (vm["m4"].as<bool>()){ + shared_ptr<M4_Exporter> exporter(new M4_Exporter(board)); + exporter->add_header(PACKAGE_STRING); + + //if (vm.count("preamble") || vm.count("preamble-text")) { + // exporter->set_preamble(preamble); + //} + + //if (vm.count("postamble")) { + // exporter->set_postamble(postamble); + //} + + //SVG EXPORTER + if (vm.count("svg")) { + exporter->set_svg_exporter(svgexpo); + } + + exporter->export_all(vm); + } else { + shared_ptr<NGC_Exporter> exporter(new NGC_Exporter(board)); + exporter->add_header(PACKAGE_STRING); + + if (vm.count("preamble") || vm.count("preamble-text")) { + exporter->set_preamble(preamble); + } + + if (vm.count("postamble")) { + exporter->set_postamble(postamble); + } + + //SVG EXPORTER + if (vm.count("svg")) { + exporter->set_svg_exporter(svgexpo); + } + + exporter->export_all(vm); } - exporter->export_all(vm); - } catch (std::logic_error& le) { cout << "Internal Error: " << le.what() << endl; } catch (std::runtime_error& re) { diff --git a/ngc_exporter.cpp b/ngc_exporter.cpp index 023adec..1d21560 100644 --- a/ngc_exporter.cpp +++ b/ngc_exporter.cpp @@ -126,6 +126,7 @@ void NGC_Exporter::export_all(boost::program_options::variables_map& options) { std::stringstream option_name; option_name << layername << "-output"; string of_name = build_filename(outputdir, options[option_name.str()].as<string>()); + of_name += ".ngc"; cerr << "Exporting " << layername << "... "; export_layer(board->get_layer(layername), of_name); cerr << "DONE." << " (Height: " << board->get_height() * cfactor diff --git a/ngc_exporter.hpp b/ngc_exporter.hpp index 7894419..f8d194d 100644 --- a/ngc_exporter.hpp +++ b/ngc_exporter.hpp @@ -66,7 +66,9 @@ using boost::shared_ptr; #include "exporter.hpp" #include "svg_exporter.hpp" #include "autoleveller.hpp" +#ifndef Included_OutlineBridges_H #include "outline_bridges.hpp" +#endif /******************************************************************************/ /* diff --git a/options.cpp b/options.cpp index cb590ad..92b3225 100644 --- a/options.cpp +++ b/options.cpp @@ -110,9 +110,9 @@ void options::parse(int argc, char** argv) { basename = instance().vm["basename"].as<string>() + "_"; } - string front_output = "--front-output=" + basename + "front.ngc"; - string back_output = "--back-output=" + basename + "back.ngc"; - string outline_output = "--outline-output=" + basename + "outline.ngc"; + string front_output = "--front-output=" + basename + "front"; + string back_output = "--back-output=" + basename + "back"; + string outline_output = "--outline-output=" + basename + "outline"; string drill_output = "--drill-output=" + basename + "drill.ngc"; const char *fake_basename_command_line[] = { "", front_output.c_str(), @@ -180,66 +180,67 @@ options::options() "version", "show the current software version"); cfg_options.add_options()( - "front", po::value<string>(),"front side RS274-X .gbr")( - "back", po::value<string>(), "back side RS274-X .gbr")( - "outline", po::value<string>(), "pcb outline polygon RS274-X .gbr")( - "drill", po::value<string>(), "Excellon drill file")( - "svg", po::value<string>(), "SVG output file. EXPERIMENTAL")( - "zwork", po::value<double>(), - "milling depth in inches (Z-coordinate while engraving)")( - "zsafe", po::value<double>(), "safety height (Z-coordinate during rapid moves)")( - "offset", po::value<double>(), "distance between the PCB traces and the end mill path in inches; usually half the isolation width")( - "mill-feed", po::value<double>(), "feed while isolating in [i/m] or [mm/m]")( - "mill-speed", po::value<int>(), "spindle rpm when milling")( - "milldrill", po::value<bool>()->default_value(false)->implicit_value(true), "drill using the mill head")( - "nog81", po::value<bool>()->default_value(false)->implicit_value(true), "replace G81 with G0+G1")( - "extra-passes", po::value<int>()->default_value(0), "specify the the number of extra isolation passes, increasing the isolation width half the tool diameter with each pass")( - "fill-outline", po::value<bool>()->default_value(false)->implicit_value(true), "accept a contour instead of a polygon as outline (you likely want to enable this one)")( - "outline-width", po::value<double>(), "width of the outline")( - "cutter-diameter", po::value<double>(), "diameter of the end mill used for cutting out the PCB")( - "zcut", po::value<double>(), "PCB cutting depth in inches")( - "cut-feed", po::value<double>(), "PCB cutting feed in [i/m] or [mm/m]")( - "cut-speed", po::value<int>(), "spindle rpm when cutting")( - "cut-infeed", po::value<double>(), "maximum cutting depth; PCB may be cut in multiple passes")( - "cut-front", po::value<bool>()->default_value(false)->implicit_value(true), "cut from front side. Default is back side.")( - "zdrill", po::value<double>(), "drill depth")( - "zchange", po::value<double>(), "tool changing height")( - "drill-feed", po::value<double>(), "drill feed in [i/m] or [mm/m]")( - "drill-speed", po::value<int>(), "spindle rpm when drilling")( - "drill-front", po::value<bool>()->default_value(false)->implicit_value(true), "drill through the front side of board")( - "onedrill", po::value<bool>()->default_value(false)->implicit_value(true), "use only one drill bit size")( - "metric", po::value<bool>()->default_value(false)->implicit_value(true), "use metric units for parameters. does not affect gcode output")( - "metricoutput", po::value<bool>()->default_value(false)->implicit_value(true), "use metric units for output")( - "optimise", po::value<bool>()->default_value(false)->implicit_value(true), "Reduce output file size by up to 40% while accepting a little loss of precision.")( - "bridges", po::value<double>()->default_value(0), "add bridges with the given width to the outline cut")( - "bridgesnum", po::value<unsigned int>()->default_value(2), "specify how many bridges should be created")( - "zbridges", po::value<double>(), "bridges heigth (Z-coordinates while engraving bridges, default to zsafe) ")( - "al-front", po::value<bool>()->default_value(false)->implicit_value(true), - "enable the z autoleveller for the front layer")( - "al-back", po::value<bool>()->default_value(false)->implicit_value(true), - "enable the z autoleveller for the back layer")( - "software", po::value<string>(), "choose the destination software (useful only with the autoleveller). Supported softwares are linuxcnc, mach3, mach4 and custom")( - "al-x", po::value<double>(), "width of the x probes")( - "al-y", po::value<double>(), "width of the y probes")( - "al-probefeed", po::value<double>(), "speed during the probing")( - "al-probe-on", po::value<string>()->default_value("(MSG, Attach the probe tool)@M0 ( Temporary machine stop. )"), "execute this commands to enable the probe tool (default is M0)")( - "al-probe-off", po::value<string>()->default_value("(MSG, Detach the probe tool)@M0 ( Temporary machine stop. )"), "execute this commands to disable the probe tool (default is M0)")( - "al-probecode", po::value<string>()->default_value("G31"), "custom probe code (default is G31)")( - "al-probevar", po::value<unsigned int>()->default_value(2002), "number of the variable where the result of the probing is saved (default is 2002)")( - "al-setzzero", po::value<string>()->default_value("G92 Z0"), "gcode for setting the actual position as zero (default is G92 Z0)")( - "dpi", po::value<int>()->default_value(1000), "virtual photoplot resolution")( - "zero-start", po::value<bool>()->default_value(false)->implicit_value(true), "set the starting point of the project at (0,0)")( - "g64", po::value<double>(), "maximum deviation from toolpath, overrides internal calculation")( - "mirror-absolute", po::value<bool>()->default_value(false)->implicit_value(true), "mirror back side along absolute zero instead of board center\n")( - "output-dir", po::value<string>()->default_value(""), "output directory")( - "basename", po::value<string>(), "prefix for default output file names")( - "front-output", po::value<string>()->default_value("front.ngc"), "output file for front layer")( - "back-output", po::value<string>()->default_value("back.ngc"), "output file for back layer")( - "outline-output", po::value<string>()->default_value("outline.ngc"), "output file for outline")( - "drill-output", po::value<string>()->default_value("drill.ngc"), "output file for drilling")( - "preamble-text", po::value<string>(), "preamble text file, inserted at the very beginning as a comment.")( - "preamble", po::value<string>(), "gcode preamble file, inserted at the very beginning.")( - "postamble", po::value<string>(), "gcode postamble file, inserted before M9 and M2."); + "m4", po::value<bool>()->default_value(0),"export m4")( + "front", po::value<string>(),"front side RS274-X .gbr")( + "back", po::value<string>(), "back side RS274-X .gbr")( + "outline", po::value<string>(), "pcb outline polygon RS274-X .gbr")( + "drill", po::value<string>(), "Excellon drill file")( + "svg", po::value<string>(), "SVG output file. EXPERIMENTAL")( + "zwork", po::value<double>(), + "milling depth in inches (Z-coordinate while engraving)")( + "zsafe", po::value<double>(), "safety height (Z-coordinate during rapid moves)")( + "offset", po::value<double>(), "distance between the PCB traces and the end mill path in inches; usually half the isolation width")( + "mill-feed", po::value<double>(), "feed while isolating in [i/m] or [mm/m]")( + "mill-speed", po::value<int>(), "spindle rpm when milling")( + "milldrill", po::value<bool>()->default_value(false)->implicit_value(true), "drill using the mill head")( + "nog81", po::value<bool>()->default_value(false)->implicit_value(true), "replace G81 with G0+G1")( + "extra-passes", po::value<int>()->default_value(0), "specify the the number of extra isolation passes, increasing the isolation width half the tool diameter with each pass")( + "fill-outline", po::value<bool>()->default_value(false)->implicit_value(true), "accept a contour instead of a polygon as outline (you likely want to enable this one)")( + "outline-width", po::value<double>(), "width of the outline")( + "cutter-diameter", po::value<double>(), "diameter of the end mill used for cutting out the PCB")( + "zcut", po::value<double>(), "PCB cutting depth in inches")( + "cut-feed", po::value<double>(), "PCB cutting feed in [i/m] or [mm/m]")( + "cut-speed", po::value<int>(), "spindle rpm when cutting")( + "cut-infeed", po::value<double>(), "maximum cutting depth; PCB may be cut in multiple passes")( + "cut-front", po::value<bool>()->default_value(false)->implicit_value(true), "cut from front side. Default is back side.")( + "zdrill", po::value<double>(), "drill depth")( + "zchange", po::value<double>(), "tool changing height")( + "drill-feed", po::value<double>(), "drill feed in [i/m] or [mm/m]")( + "drill-speed", po::value<int>(), "spindle rpm when drilling")( + "drill-front", po::value<bool>()->default_value(false)->implicit_value(true), "drill through the front side of board")( + "onedrill", po::value<bool>()->default_value(false)->implicit_value(true), "use only one drill bit size")( + "metric", po::value<bool>()->default_value(false)->implicit_value(true), "use metric units for parameters. does not affect gcode output")( + "metricoutput", po::value<bool>()->default_value(false)->implicit_value(true), "use metric units for output")( + "optimise", po::value<bool>()->default_value(false)->implicit_value(true), "Reduce output file size by up to 40% while accepting a little loss of precision.")( + "bridges", po::value<double>()->default_value(0), "add bridges with the given width to the outline cut")( + "bridgesnum", po::value<unsigned int>()->default_value(2), "specify how many bridges should be created")( + "zbridges", po::value<double>(), "bridges heigth (Z-coordinates while engraving bridges, default to zsafe) ")( + "al-front", po::value<bool>()->default_value(false)->implicit_value(true), + "enable the z autoleveller for the front layer")( + "al-back", po::value<bool>()->default_value(false)->implicit_value(true), + "enable the z autoleveller for the back layer")( + "software", po::value<string>(), "choose the destination software (useful only with the autoleveller). Supported softwares are linuxcnc, mach3, mach4 and custom")( + "al-x", po::value<double>(), "width of the x probes")( + "al-y", po::value<double>(), "width of the y probes")( + "al-probefeed", po::value<double>(), "speed during the probing")( + "al-probe-on", po::value<string>()->default_value("(MSG, Attach the probe tool)@M0 ( Temporary machine stop. )"), "execute this commands to enable the probe tool (default is M0)")( + "al-probe-off", po::value<string>()->default_value("(MSG, Detach the probe tool)@M0 ( Temporary machine stop. )"), "execute this commands to disable the probe tool (default is M0)")( + "al-probecode", po::value<string>()->default_value("G31"), "custom probe code (default is G31)")( + "al-probevar", po::value<unsigned int>()->default_value(2002), "number of the variable where the result of the probing is saved (default is 2002)")( + "al-setzzero", po::value<string>()->default_value("G92 Z0"), "gcode for setting the actual position as zero (default is G92 Z0)")( + "dpi", po::value<int>()->default_value(1000), "virtual photoplot resolution")( + "zero-start", po::value<bool>()->default_value(false)->implicit_value(true), "set the starting point of the project at (0,0)")( + "g64", po::value<double>(), "maximum deviation from toolpath, overrides internal calculation")( + "mirror-absolute", po::value<bool>()->default_value(false)->implicit_value(true), "mirror back side along absolute zero instead of board center\n")( + "output-dir", po::value<string>()->default_value(""), "output directory")( + "basename", po::value<string>(), "prefix for default output file names")( + "front-output", po::value<string>()->default_value("front"), "output file for front layer")( + "back-output", po::value<string>()->default_value("back"), "output file for back layer")( + "outline-output", po::value<string>()->default_value("outline"), "output file for outline")( + "drill-output", po::value<string>()->default_value("drill.ngc"), "output file for drilling")( + "preamble-text", po::value<string>(), "preamble text file, inserted at the very beginning as a comment.")( + "preamble", po::value<string>(), "gcode preamble file, inserted at the very beginning.")( + "postamble", po::value<string>(), "gcode postamble file, inserted before M9 and M2."); } /******************************************************************************/ diff --git a/outline_bridges.hpp b/outline_bridges.hpp index 91f4ae9..89aaae3 100755 --- a/outline_bridges.hpp +++ b/outline_bridges.hpp @@ -22,6 +22,8 @@ */ /******************************************************************************/ +#define Included_OutlineBridges_H + #include <vector> using std::vector; using std::pair; diff --git a/pcb2gcode.sh b/pcb2gcode.sh new file mode 100755 index 0000000..e9f9c9a --- /dev/null +++ b/pcb2gcode.sh @@ -0,0 +1,68 @@ +PCB2GCODE_BASE=/home/saintel/pcb2gcode/git_20150418/pcb2gcode/ +PCB2GCODE=$PCB2GCODE_BASE/pcb2gcode +PCB2GCODE_M4=$PCB2GCODE_BASE/pcb2gcode_m4 +MILLPROJECT=millproject + +if [ -a $MILLPROJECT ] ; then { + $PCB2GCODE --m4=true + + + if (grep -q front $MILLPROJECT); then { + + if (grep -q ^front-output $MILLPROJECT); then { + FRONT_OUTPUT=`grep front-output millproject | sed -e 's/^[ ]*front-output[ ]*=[ ]*\([^ \t]\+\)/\1/'` + }; else { + FRONT_OUTPUT='front' + }; fi; + FRONT_OUTPUT_M4=$FRONT_OUTPUT.m4 + FRONT_OUTPUT_GBR=$FRONT_OUTPUT.gbr + + if [ -a $FRONT_OUTPUT_M4 ]; then { + echo "Processing front file : $FRONT_FILE" + m4 $PCB2GCODE_M4/gerber.m4 $FRONT_OUTPUT_M4 > $FRONT_OUTPUT_GBR + }; else { + echo "Front template file not found : $FRONT_OUTPUT_M4" + }; fi; + + } fi; + + if (grep -q ^back $MILLPROJECT); then { + + if (grep -q back-output $MILLPROJECT); then { + BACK_OUTPUT=`grep back-output millproject | sed -e 's/^[ ]*back-output[ ]*=[ ]*\([^ \t]\+\)/\1/'` + }; else { + BACK_OUTPUT='back' + }; fi; + BACK_OUTPUT_M4=$BACK_OUTPUT.m4 + BACK_OUTPUT_GBR=$BACK_OUTPUT.gbr + + if [ -a $BACK_OUTPUT_M4 ]; then { + echo "Processing back file : $BACK_FILE" + m4 $PCB2GCODE_M4/gerber.m4 $BACK_OUTPUT_M4 > $BACK_OUTPUT_GBR + }; else { + echo "Back template file not found : $BACK_OUTPUT_M4" + }; fi; + + } fi; + + if (grep -q outline $MILLPROJECT); then { + + if (grep -q outline-output $MILLPROJECT); then { + OUTLINE_OUTPUT=`grep outline-output millproject | sed -e 's/^[ ]*outline-output[ ]*=[ ]*\([^ \t]\+\)/\1/'` + }; else { + OUTLINE_OUTPUT='outline' + }; fi; + OUTLINE_OUTPUT_M4=$OUTLINE_OUTPUT.m4 + OUTLINE_OUTPUT_GBR=$OUTLINE_OUTPUT.gbr + + if [ -a $OUTLINE_OUTPUT_M4 ]; then { + echo "Processing outline file : $OUTLINE_FILE" + m4 $PCB2GCODE_M4/gerber.m4 $OUTLINE_OUTPUT_M4 > $OUTLINE_OUTPUT_GBR + }; else { + echo "Outline template file not found : $OUTLINE_FILE_M4" + }; fi; + + } fi; + +} fi; + diff --git a/pcb2gcode_m4/gerber.m4 b/pcb2gcode_m4/gerber.m4 new file mode 100644 index 0000000..e27ab81 --- /dev/null +++ b/pcb2gcode_m4/gerber.m4 @@ -0,0 +1,17 @@ +define(`m4_header',`G04 $1 *')dnl +define(`m4_preamble',`G04 File Generated using pb2gcode and m4 template gerber.m4* +`%FSLAX'm4_digitdot`'m4_dotdigit`Y'm4_digitdot`'m4_dotdigit`*%' +ifdef(`m4_metric',`%MOMM*%')`'dnl +ifdef(`m4_imperial',`%MOIN*%') +%TF.Part,Other*% +%LPD% +%ADD10C,0.010*% +D10* +G01*')dnl +define(`m4_coord',`define(`dotpos',`index($1,`.')')substr($1,0,eval(dotpos))substr($1,eval(dotpos+1))')dnl +define(m4_postamble,M02*)dnl +define(m4_header,)dnl +define(m4_move,`define(`X',$1)define(`Y',$2)`X'm4_coord(X)`Y'm4_coord(Y)`D02*'')dnl +define(m4_mill,`define(`X',$1)define(`Y',$2)`X'm4_coord(X)`Y'm4_coord(Y)`D01*'')dnl +define(plunge,`G04 Plunge')dnl +define(m4_Z,`G04 Z:$1')dnl |