// // Generate g-code for milling PC boards. // // Copyright 2004-2013 by John Johnson Software, LLC. // See readme.html for copyright information. // #include "source/pcb-gcode.h" #include "settings/pcb-defaults.h" #include "settings/pcb-machine.h" #include "settings/gcode-defaults.h" #include "settings/pcb-gcode-options.h" #include "source/filecopy.h" #include "source/math.h" #include "source/filename_subs.h" #include "plugin_headers.h" int m_current_units = OUTPUT_UNITS; string m_uom_suffix = "unknown"; string M_UOM_SUFFIXES[] = { "mc", // microns "mm", // millimeters "ml", // mils "in" // inches }; int m_setup_was_changed = NO; string m_cmd; string FILENAME_TOP_ETCH_FILE_SAMPLE; string FILENAME_TOP_DRILL_FILE_SAMPLE; string FILENAME_TOP_MILL_FILE_SAMPLE; string FILENAME_TOP_TEXT_FILE_SAMPLE; string FILENAME_TOP_FILL_FILE_SAMPLE; string FILENAME_BOT_ETCH_FILE_SAMPLE; string FILENAME_BOT_DRILL_FILE_SAMPLE; string FILENAME_BOT_MILL_FILE_SAMPLE; string FILENAME_BOT_TEXT_FILE_SAMPLE; string FILENAME_BOT_FILL_FILE_SAMPLE; string temp_str; void set_uom_suffix(int n) { m_uom_suffix = M_UOM_SUFFIXES[n]; } string get_uom_suffix() { return m_uom_suffix; } void write_bool_param(string name, int value) { printf("int %s = %s;\n", name, (value) ? "YES" : "NO"); } void write_int_param(string name, int value) { printf("int %s = %d;\n", name, value); } void write_int_defined(string name, string value) { printf("int %s = %s;\n", name, value); } void write_real_param(string name, real value) { printf("real %s = %f;\n", name, value); } void write_string_param(string name, string value) { printf("string %s = \"%s\";\n", name, value); } // UNIT CONVERSION BEGIN TAG DO NOT REMOVE void convert_units(int new_units) { MILLING_DEPTH = convert(MILLING_DEPTH, m_current_units, new_units); TEXT_DEPTH = convert(TEXT_DEPTH, m_current_units, new_units); SPOT_DRILL_DEPTH = convert(SPOT_DRILL_DEPTH, m_current_units, new_units); ISO_MIN = convert(ISO_MIN, m_current_units, new_units); ISO_MAX = convert(ISO_MAX, m_current_units, new_units); ISO_STEP = convert(ISO_STEP, m_current_units, new_units); DEFAULT_WIDTH = convert(DEFAULT_WIDTH, m_current_units, new_units); DEFAULT_Z_HIGH = convert(DEFAULT_Z_HIGH, m_current_units, new_units); DEFAULT_Z_UP = convert(DEFAULT_Z_UP, m_current_units, new_units); DEFAULT_Z_DOWN = convert(DEFAULT_Z_DOWN, m_current_units, new_units); DRILL_DEPTH = convert(DRILL_DEPTH, m_current_units, new_units); TOOL_CHANGE_POS_X = convert(TOOL_CHANGE_POS_X, m_current_units, new_units); TOOL_CHANGE_POS_Y = convert(TOOL_CHANGE_POS_Y, m_current_units, new_units); TOOL_CHANGE_POS_Z = convert(TOOL_CHANGE_POS_Z, m_current_units, new_units); FEED_RATE = convert(FEED_RATE, m_current_units, new_units); FEED_RATE_Z = convert(FEED_RATE_Z, m_current_units, new_units); EPSILON = convert(EPSILON, m_current_units, new_units); set_uom_suffix(OUTPUT_UNITS); dlgRedisplay(); m_current_units = new_units; } // UNIT CONVERSION END TAG DO NOT REMOVE // Copy the *.release.h files to *.h, thereby restoring // their default contents. void restore_file_defaults() { string restore_files[]; string file_name; int num_files; int i; int release_start; num_files = fileglob(restore_files, g_path + "/safe_options/" + "*.release.h"); if (num_files == 0) { dlgMessageBox("There aren't any .release.h files," " perhaps you should reinstall the program?"); exit(0); } for (i=0; i < num_files; i++) { release_start = strrstr(restore_files[i], ".release.h"); file_name = strsub(restore_files[i], 0, release_start) + ".h"; filecopy(restore_files[i], file_name); } filecopy(g_path + "/profiles/generic.pp", g_path + "/settings/gcode-defaults.h"); } int pp_selection = -1; string pp_files[]; string pp_auth_desc[]; int num_pp_files; num_pp_files = fileglob(pp_files, g_path + "/profiles/*.pp"); for(int i=0; i < num_pp_files; i++) { string lines[]; pp_auth_desc[i] = pp_files[i]; int num_lines = fileread(lines, pp_files[i]); for(int j=0; j < num_lines; j++) { string fields[]; int num_fields = strsplit(fields, lines[j], '='); for(int k=0; k < num_fields; k++) { if(strlwr(fields[k]) == "// author") { pp_auth_desc[i] = pp_auth_desc[i] + " \t" + fields[k + 1]; } else if(strlwr(fields[k]) == "// description") { pp_auth_desc[i] = pp_auth_desc[i] + " \t" + fields[k + 1]; } } } } string m_maximum_label = "Maximum"; string m_step_size_label = "Step size"; if (SINGLE_PASS) { m_maximum_label = "not used"; m_step_size_label = "not used"; } string m_eagle_compatibility = ""; string m_compatibility = ""; if (EAGLE_VERSION < 5) { m_compatibility = "NOT COMPATIBLE"; } else if (EAGLE_VERSION == 5) { m_compatibility = "verified compatible"; } else if (EAGLE_VERSION == 6) { if (EAGLE_RELEASE <= 3) { m_compatibility = "verified compatible"; } else { m_compatibility = "probably compatible"; } } sprintf(m_eagle_compatibility, "%d.%d (%s)", EAGLE_VERSION, EAGLE_RELEASE, m_compatibility); int Result = dlgDialog("pcb-gcode Setup") { set_uom_suffix(OUTPUT_UNITS); dlgVBoxLayout { dlgLabel( "
"
""
" "
""
" | "
"
| "
"
" "
");
dlgStretch(3);
}
dlgVBoxLayout {
dlgGroup("Board") {
dlgVBoxLayout {
dlgCheckBox("Show preview ", SHOW_PREVIEW);
dlgGridLayout {
dlgCell(0, 0) dlgCheckBox("Generate milling", GENERATE_MILLING);
dlgCell(0, 1) dlgLabel("Depth ");
dlgCell(0, 2) { dlgRealEdit(MILLING_DEPTH); dlgLabel(m_uom_suffix, YES); }
dlgCell(1, 0) dlgCheckBox("Generate text", GENERATE_TEXT);
dlgCell(1, 1) dlgLabel("Depth ");
dlgCell(1, 2) { dlgRealEdit(TEXT_DEPTH); dlgLabel(m_uom_suffix, YES); }
dlgCell(2, 0) dlgCheckBox("Spot drill holes", SPOT_DRILL);
dlgCell(2, 1) dlgLabel("Depth");
dlgCell(2, 2) { dlgRealEdit(SPOT_DRILL_DEPTH); dlgLabel(m_uom_suffix, YES); }
}
dlgGridLayout {
dlgCell(0, 0, 0, 1) dlgLabel("Isolation");
dlgCell(0, 1) {
dlgCheckBox("Single pass", SINGLE_PASS) {
if (SINGLE_PASS) {
/* dlgMessageBox("You have selected the single pass option.\n" +
"The next time you run pcb-gcode-setup, the Maximum and Step Size " +
"options will be hidden. Only Minimum will be shown.\n" +
"To change back, just turn Single pass off, " +
"click Accept, and run pcb-gcode-setup again.\n" +
"The minimum, maximum, and step size options will be available again.");
*/
m_maximum_label = "not used";
m_step_size_label = "not used";
}
else {
m_maximum_label = "Maximum";
m_step_size_label = "Step size";
}
}
}
dlgCell(1, 0) dlgLabel("Minimum");
dlgCell(1, 1) { dlgRealEdit(ISO_MIN);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(3, 0) dlgLabel(m_maximum_label, YES);
dlgCell(3, 1) { dlgRealEdit(ISO_MAX);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(4, 0) dlgLabel(m_step_size_label, YES);
dlgCell(4, 1) { dlgRealEdit(ISO_STEP);
dlgLabel(m_uom_suffix, YES);
}
}
dlgSpacing(10);
dlgVBoxLayout {
dlgLabel("Etching Tool Size ");
dlgHBoxLayout { dlgRealEdit(DEFAULT_WIDTH);
dlgLabel(m_uom_suffix, YES);
}
}
}
}
dlgStretch(1);
}
dlgStretch(20);
}
dlgHBoxLayout {
}
}
/***************************************************************
*
* M A C H I N E
*
***************************************************************/
if (program_is_setup()) dlgTabPage("Machine") {
dlgHBoxLayout {
dlgStretch(20);
dlgLabel("
");
dlgGroup("Z Axis") {
dlgGridLayout {
dlgCell(1, 0) dlgLabel("Z High ");
dlgCell(1, 1) {
dlgRealEdit(DEFAULT_Z_HIGH);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(2, 0) dlgLabel("Z Up ");
dlgCell(2, 1) {
dlgRealEdit(DEFAULT_Z_UP);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(3, 0) dlgLabel("Z Down ");
dlgCell(3, 1) {
dlgRealEdit(DEFAULT_Z_DOWN);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(4, 0) dlgLabel("Drill Depth ");
dlgCell(4, 1) {
dlgRealEdit(DRILL_DEPTH);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(5, 0) dlgLabel("Drill Dwell ");
dlgCell(5, 1) dlgRealEdit(DRILL_DWELL, 0); // DO NOT CONVERT
}
}
dlgGroup("Tool Change") {
dlgGridLayout {
dlgCell(1, 0) dlgLabel("Position X ");
dlgCell(1, 1) { dlgRealEdit(TOOL_CHANGE_POS_X);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(2, 0) dlgLabel("Position Y ");
dlgCell(2, 1) { dlgRealEdit(TOOL_CHANGE_POS_Y);
dlgLabel(m_uom_suffix, YES);
}
dlgCell(3, 0) dlgLabel("Position Z ");
dlgCell(3, 1) { dlgRealEdit(TOOL_CHANGE_POS_Z);
dlgLabel(m_uom_suffix, YES);
}
}
}
dlgStretch(20);
}
dlgHBoxLayout {
dlgStretch(20);
dlgGroup("Units") {
dlgRadioButton("Microns", OUTPUT_UNITS) {
convert_units(U_MICRONS);
}
dlgRadioButton("Millimeters", OUTPUT_UNITS) {
convert_units(U_MILLIMETERS);
}
dlgRadioButton("Mils", OUTPUT_UNITS) {
convert_units(U_MILS);
}
dlgRadioButton("Inches", OUTPUT_UNITS) {
convert_units(U_INCHES);
}
}
dlgGroup("Spindle") {
dlgGridLayout {
dlgCell(1, 0) dlgLabel("Spin Up Time ");
dlgCell(1, 1) dlgRealEdit(SPINDLE_ON_TIME); // DO NOT CONVERT
}
}
dlgGroup("Feed Rates") {
dlgGridLayout {
dlgCell(1, 0) dlgLabel("X Y ");
dlgCell(1, 1) { dlgRealEdit(FEED_RATE);
dlgLabel(m_uom_suffix, YES); dlgLabel("/min");
}
dlgCell(2, 0) dlgLabel("Z ");
dlgCell(2, 1) { dlgRealEdit(FEED_RATE_Z);
dlgLabel(m_uom_suffix, YES); dlgLabel("/min");
}
}
}
dlgGroup("Misc") {
dlgGridLayout {
dlgCell(1, 0) dlgLabel("Epsilon");
dlgCell(1, 1) { dlgRealEdit(EPSILON);
dlgLabel(m_uom_suffix, YES);
dlgPushButton("?") {
dlgMessageBox("If an X or Y move is less than this amount, do not "
"put a move in the g-code file. For instance, if one point is "
"only 0.00001\" away from another point, there is no need to "
"write the move to the g-code file, since the machine will not "
"move anyway. This helps make the g-code file smaller, and run faster.");
}
}
dlgCell(2, 0) dlgLabel("Default Drill Rack File");
dlgCell(2, 1) dlgStringEdit(DEFAULT_DRILL_FILE);
dlgCell(2, 2) {
dlgPushButton("...") {
DEFAULT_DRILL_FILE = dlgFileOpen("Find default drill rack file",
g_path + "/settings",
"Drill files (*.drl);;All files (*.*)");
}
dlgPushButton("?") {
dlgMessageBox(
"Please see docs/readme.html for full details." "
| pcb-defaults.h | pcb-gcode-options.h |
| pcb-machine.h | user-gcode.h |
" "If you aren't sure, click No.
"
"Are you sure?", "Yes", "No") == 0) dlgReject();
}
}
};
// Accept Accept and make board
if (Result == 1 || Result == 2) {
fileerror();
output(g_path + "/settings/pcb-defaults.h", "wt") {
int now = time();
printf(
"//\n// Default values for generating gcode from a PCB.\n//\n");
printf("// These settings were last changed with "
"pcb-gcode-setup: %s\n//\n", t2string(now));
printf("//\n// Changes you make in this file will be overwritten "
"if you use pcb-gcode-setup.\n//\n\n");
write_bool_param("SINGLE_PASS", SINGLE_PASS);
write_real_param("ISO_MIN", ISO_MIN);
write_real_param("ISO_MAX", ISO_MAX);
write_real_param("ISO_STEP", ISO_STEP);
printf("\n");
write_bool_param("GENERATE_TOP_OUTLINES", GENERATE_TOP_OUTLINES);
write_bool_param("GENERATE_TOP_DRILL", GENERATE_TOP_DRILL);
write_bool_param("GENERATE_TOP_FILL", GENERATE_TOP_FILL);
printf("\n");
write_bool_param("GENERATE_BOTTOM_OUTLINES",
GENERATE_BOTTOM_OUTLINES);
write_bool_param("GENERATE_BOTTOM_DRILL", GENERATE_BOTTOM_DRILL);
write_bool_param("GENERATE_BOTTOM_FILL", GENERATE_BOTTOM_FILL);
write_bool_param("MIRROR_BOTTOM",
MIRROR_BOTTOM);
write_bool_param("SIMPLE_DRILL_CODE", SIMPLE_DRILL_CODE);
printf("\n");
write_bool_param("GENERATE_MILLING", GENERATE_MILLING);
printf("\n");
write_bool_param("GENERATE_TEXT", GENERATE_TEXT);
printf("\n");
write_bool_param("SPOT_DRILL", SPOT_DRILL);
write_real_param("SPOT_DRILL_DEPTH", SPOT_DRILL_DEPTH);
printf("\n");
write_bool_param("DO_TOOL_CHANGE_WITH_ZERO_STEP",
DO_TOOL_CHANGE_WITH_ZERO_STEP);
printf("\n");
write_bool_param("FLIP_BOARD_IN_Y", FLIP_BOARD_IN_Y);
printf("\n");
// Place a // in front of units not being used
if (OUTPUT_UNITS != U_MICRONS) printf("//");
write_int_defined("OUTPUT_UNITS", "U_MICRONS");
if (OUTPUT_UNITS != U_MILLIMETERS) printf("//");
write_int_defined("OUTPUT_UNITS", "U_MILLIMETERS");
if (OUTPUT_UNITS != U_MILS) printf("//");
write_int_defined("OUTPUT_UNITS", "U_MILS");
if (OUTPUT_UNITS != U_INCHES) printf("//");
write_int_defined("OUTPUT_UNITS", "U_INCHES");
}
if(fileerror())
exit(1);
if(pp_selection > -1) {
if (dlgMessageBox(
" "
"(Click Yes if you aren't sure.) "
"Save your selection?