diff --git a/src/com/t_oster/liblasercut/drivers/.GenericGcodeDriver.java.swp b/src/com/t_oster/liblasercut/drivers/.GenericGcodeDriver.java.swp new file mode 100644 index 00000000..c21c07fd Binary files /dev/null and b/src/com/t_oster/liblasercut/drivers/.GenericGcodeDriver.java.swp differ diff --git a/src/com/t_oster/liblasercut/drivers/.Grbl.java.swp b/src/com/t_oster/liblasercut/drivers/.Grbl.java.swp new file mode 100644 index 00000000..c04cbc2b Binary files /dev/null and b/src/com/t_oster/liblasercut/drivers/.Grbl.java.swp differ diff --git a/src/com/t_oster/liblasercut/drivers/GenericGcodeDriver.java b/src/com/t_oster/liblasercut/drivers/GenericGcodeDriver.java index cfb2e009..baf5d7fb 100644 --- a/src/com/t_oster/liblasercut/drivers/GenericGcodeDriver.java +++ b/src/com/t_oster/liblasercut/drivers/GenericGcodeDriver.java @@ -495,7 +495,7 @@ protected void line(PrintStream out, double x, double y, double resolution) thro sendLine("G1 X%f Y%f"+append, x, y); } - private void writeInitializationCode() throws IOException { + protected void writeInitializationCode() throws IOException { if (preJobGcode != null) { for (String line : preJobGcode.split(",")) @@ -506,7 +506,7 @@ private void writeInitializationCode() throws IOException { } - private void writeShutdownCode() throws IOException { + protected void writeShutdownCode() throws IOException { if (postJobGcode != null) { for (String line : postJobGcode.split(",")) @@ -671,7 +671,7 @@ protected String connect_serial(CommPortIdentifier i, ProgressListener pl) throw * Used to buffer the file before uploading via http */ private ByteArrayOutputStream outputBuffer; - private String jobName; + protected String jobName; protected void connect(ProgressListener pl) throws IOException, PortInUseException, NoSuchPortException, UnsupportedCommOperationException { outputBuffer = null; @@ -791,6 +791,17 @@ else if (this.port != null) } + + /* sendJobPrepare() and sendJobFinish() can be overrided in children to + * perform device-specific setup before and after sending job over serial + * line + */ + protected void sendJobPrepare() throws IOException { + } + + protected void sendJobFinish() throws IOException { + } + @Override public void sendJob(LaserJob job, ProgressListener pl, List warnings) throws IllegalJobException, Exception { pl.progressChanged(this, 0); @@ -805,6 +816,7 @@ public void sendJob(LaserJob job, ProgressListener pl, List warnings) th connect(pl); pl.taskChanged(this, "sending"); try { + sendJobPrepare(); writeInitializationCode(); pl.progressChanged(this, 20); int i = 0; @@ -825,6 +837,7 @@ public void sendJob(LaserJob job, ProgressListener pl, List warnings) th pl.progressChanged(this, 20 + (int) (i*(double) 60/max)); } writeShutdownCode(); + sendJobFinish(); disconnect(job.getName()+".gcode"); } catch (IOException e) { diff --git a/src/com/t_oster/liblasercut/drivers/Grbl.java b/src/com/t_oster/liblasercut/drivers/Grbl.java index 68beb9bc..be605c82 100644 --- a/src/com/t_oster/liblasercut/drivers/Grbl.java +++ b/src/com/t_oster/liblasercut/drivers/Grbl.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.ArrayDeque; /** * This class implements a driver for Grbl based firmwares. @@ -33,8 +34,11 @@ */ public class Grbl extends GenericGcodeDriver { + protected ArrayDeque commandLenQueue; + public Grbl() { + commandLenQueue = new ArrayDeque(); //set some grbl-specific defaults setLineend("CR"); setIdentificationLine("Grbl"); @@ -105,13 +109,31 @@ public void setAutoHome(boolean auto_home) this.autoHome = auto_home; } + protected boolean simpleStreamMode = true; + + public boolean isSimpleStreamMode() + { + return simpleStreamMode; + } + + public void setSimpleStreamMode(boolean mode) throws IOException + { + if (mode != simpleStreamMode) { + if (!simpleStreamMode) + waitForCommandsCompletion(); + else + commandLenQueue.clear(); + + simpleStreamMode = mode; + } + } @Override public String getModelName() { return "Grbl Gcode Driver"; } - + protected void sendLineWithoutWait(String text, Object... parameters) throws IOException { boolean wasSetWaitingForOk = isWaitForOKafterEachLine(); @@ -119,6 +141,77 @@ protected void sendLineWithoutWait(String text, Object... parameters) throws IOE sendLine(text, parameters); setWaitForOKafterEachLine(wasSetWaitingForOk); } + + @Override + protected String waitForLine() throws IOException + { + String line = ""; + while ("".equals(line)) + {//skip empty lines + line = in.readLine(); + } + + //TODO: remove + if (isSimpleStreamMode() || !"ok".equals(line)) + System.out.println("< "+line); + else { + int len = commandLenQueue.peek(); + // Debug: print counted chars still remains in the buffer AFTER receiving this 'ok' response + System.out.println(String.format(FORMAT_LOCALE, "%d< %s", getBufferedCommandsLen() - len, line)); + } + + return line; + } + + protected static final int GRBL_BUF_LEN = 128; + + protected Integer getBufferedCommandsLen() + { + Integer len = 0; + for (Integer c : commandLenQueue) + len += c; + return len; + } + + protected void sendLineSimple(String text, Object... parameters) throws IOException + { + super.sendLine(text, parameters); + } + + protected void sendLineCC(String text, Object... parameters) throws IOException + { + String outStr = String.format(FORMAT_LOCALE, text+LINEEND(), parameters); + int len = outStr.length(); + + // Read all received responses from grbl or wait for needed free space in the serial buffer + while (in.ready() || (getBufferedCommandsLen() + len > GRBL_BUF_LEN)) { + String line = waitForLine(); + if (!"ok".equals(line)) + { + throw new IOException("Lasercutter did not respond 'ok', but '"+line+"'instead."); + } + commandLenQueue.remove(); + } + + commandLenQueue.add(len); + out.print(outStr); + //TODO: Remove + System.out.println(String.format(FORMAT_LOCALE, "%d> %s", getBufferedCommandsLen(), outStr)); + out.flush(); + } + + protected void waitForCommandsCompletion() throws IOException + { + while (!commandLenQueue.isEmpty()) { + String line = waitForLine(); + if (!"ok".equals(line)) + { + throw new IOException("Lasercutter did not respond 'ok', but '"+line+"'instead."); + } + commandLenQueue.remove(); + } + } + /** * Initializes Grbl, handling issuing of soft-reset and initial homing @@ -186,7 +279,7 @@ protected void move(PrintStream out, double x, double y, double resolution) thro sendLine("G0 X%f Y%f", x, y); } } - + /** * Send a line of gcode to the cutter, stripping out any whitespace in the process * @param text @@ -194,20 +287,31 @@ protected void move(PrintStream out, double x, double y, double resolution) thro * @throws IOException */ @Override + protected void sendLine(String text, Object... parameters) throws IOException { - out.format(FORMAT_LOCALE, text.replace(" ", "")+LINEEND(), parameters); - //TODO: Remove - System.out.println(String.format(FORMAT_LOCALE, "> "+text+LINEEND(), parameters)); - out.flush(); - if (isWaitForOKafterEachLine()) - { - String line = waitForLine(); - if (!"ok".equals(line)) - { - throw new IOException("Lasercutter did not respond 'ok', but '"+line+"'instead."); - } - } + if (isSimpleStreamMode()) + sendLineSimple(text, parameters); + else + sendLineCC(text, parameters); + } + + @Override + protected void sendJobPrepare() throws IOException { + setSimpleStreamMode(false); + } + + @Override + protected void sendJobFinish() throws IOException { + setSimpleStreamMode(true); + } + + @Override + protected void setKeysMissingFromDeserialization() + { + super.setKeysMissingFromDeserialization(); + commandLenQueue = new ArrayDeque(); + simpleStreamMode = true; } @Override