Skip to content

Commit 025e4ec

Browse files
committed
Implement character-counting protocol for Grbl. Closes t-oster#74
1 parent 904b520 commit 025e4ec

File tree

2 files changed

+148
-11
lines changed

2 files changed

+148
-11
lines changed

src/com/t_oster/liblasercut/drivers/GenericGcodeDriver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ protected void line(PrintStream out, double x, double y, double resolution) thro
495495
sendLine("G1 X%f Y%f"+append, x, y);
496496
}
497497

498-
private void writeInitializationCode() throws IOException {
498+
protected void writeInitializationCode() throws IOException {
499499
if (preJobGcode != null)
500500
{
501501
for (String line : preJobGcode.split(","))
@@ -506,7 +506,7 @@ private void writeInitializationCode() throws IOException {
506506
}
507507

508508

509-
private void writeShutdownCode() throws IOException {
509+
protected void writeShutdownCode() throws IOException {
510510
if (postJobGcode != null)
511511
{
512512
for (String line : postJobGcode.split(","))
@@ -671,7 +671,7 @@ protected String connect_serial(CommPortIdentifier i, ProgressListener pl) throw
671671
* Used to buffer the file before uploading via http
672672
*/
673673
private ByteArrayOutputStream outputBuffer;
674-
private String jobName;
674+
protected String jobName;
675675
protected void connect(ProgressListener pl) throws IOException, PortInUseException, NoSuchPortException, UnsupportedCommOperationException
676676
{
677677
outputBuffer = null;

src/com/t_oster/liblasercut/drivers/Grbl.java

Lines changed: 145 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@
2020

2121
import com.t_oster.liblasercut.ProgressListener;
2222
import com.t_oster.liblasercut.platform.Util;
23+
import com.t_oster.liblasercut.*;
2324
import java.io.IOException;
2425
import java.io.PrintStream;
2526
import java.util.Arrays;
2627
import java.util.LinkedList;
2728
import java.util.List;
29+
import java.util.ArrayDeque;
2830

2931
/**
3032
* This class implements a driver for Grbl based firmwares.
@@ -33,8 +35,11 @@
3335
*/
3436
public class Grbl extends GenericGcodeDriver
3537
{
38+
protected ArrayDeque<Integer> commandLenQueue;
39+
3640
public Grbl()
3741
{
42+
commandLenQueue = new ArrayDeque<Integer>();
3843
//set some grbl-specific defaults
3944
setLineend("CR");
4045
setIdentificationLine("Grbl");
@@ -105,6 +110,24 @@ public void setAutoHome(boolean auto_home)
105110
this.autoHome = auto_home;
106111
}
107112

113+
protected boolean simpleStreamMode = true;
114+
115+
public boolean isSimpleStreamMode()
116+
{
117+
return simpleStreamMode;
118+
}
119+
120+
public void setSimpleStreamMode(boolean mode) throws IOException
121+
{
122+
if (mode != simpleStreamMode) {
123+
if (!simpleStreamMode)
124+
waitForCommandsCompletion();
125+
else
126+
commandLenQueue.clear();
127+
128+
simpleStreamMode = mode;
129+
}
130+
}
108131

109132
@Override
110133
public String getModelName()
@@ -119,6 +142,53 @@ protected void sendLineWithoutWait(String text, Object... parameters) throws IOE
119142
sendLine(text, parameters);
120143
setWaitForOKafterEachLine(wasSetWaitingForOk);
121144
}
145+
146+
147+
protected static final int GRBL_BUF_LEN = 128;
148+
149+
protected Integer getBufferedCommandsLen()
150+
{
151+
Integer len = 0;
152+
for (Integer c : commandLenQueue)
153+
len += c;
154+
return len;
155+
}
156+
157+
protected void sendLineCC(String text, Object... parameters) throws IOException
158+
{
159+
String outStr = String.format(FORMAT_LOCALE, text+LINEEND(), parameters);
160+
int len = outStr.length();
161+
162+
while (in.ready() || (getBufferedCommandsLen() + len > GRBL_BUF_LEN)) {
163+
String line = waitForLine();
164+
if (!"ok".equals(line))
165+
{
166+
throw new IOException("Lasercutter did not respond 'ok', but '"+line+"'instead.");
167+
}
168+
commandLenQueue.remove();
169+
System.out.println(String.format(FORMAT_LOCALE, "%d" + LINEEND(), getBufferedCommandsLen(), parameters));
170+
}
171+
172+
commandLenQueue.add(len);
173+
out.print(outStr);
174+
//TODO: Remove
175+
System.out.println(String.format(FORMAT_LOCALE, "%d> %s", getBufferedCommandsLen(), outStr));
176+
out.flush();
177+
}
178+
179+
protected void waitForCommandsCompletion() throws IOException
180+
{
181+
while (!commandLenQueue.isEmpty()) {
182+
String line = waitForLine();
183+
if (!"ok".equals(line))
184+
{
185+
throw new IOException("Lasercutter did not respond 'ok', but '"+line+"'instead.");
186+
}
187+
commandLenQueue.remove();
188+
System.out.println(String.format(FORMAT_LOCALE, "%d" + LINEEND(), getBufferedCommandsLen()));
189+
}
190+
}
191+
122192

123193
/**
124194
* Initializes Grbl, handling issuing of soft-reset and initial homing
@@ -187,14 +257,7 @@ protected void move(PrintStream out, double x, double y, double resolution) thro
187257
}
188258
}
189259

190-
/**
191-
* Send a line of gcode to the cutter, stripping out any whitespace in the process
192-
* @param text
193-
* @param parameters
194-
* @throws IOException
195-
*/
196-
@Override
197-
protected void sendLine(String text, Object... parameters) throws IOException
260+
protected void sendLineSimple(String text, Object... parameters) throws IOException
198261
{
199262
out.format(FORMAT_LOCALE, text.replace(" ", "")+LINEEND(), parameters);
200263
//TODO: Remove
@@ -210,6 +273,80 @@ protected void sendLine(String text, Object... parameters) throws IOException
210273
}
211274
}
212275

276+
/**
277+
* Send a line of gcode to the cutter, stripping out any whitespace in the process
278+
* @param text
279+
* @param parameters
280+
* @throws IOException
281+
*/
282+
@Override
283+
284+
protected void sendLine(String text, Object... parameters) throws IOException
285+
{
286+
if (isSimpleStreamMode())
287+
sendLineSimple(text, parameters);
288+
else
289+
sendLineCC(text, parameters);
290+
}
291+
292+
@Override
293+
public void sendJob(LaserJob job, ProgressListener pl, List<String> warnings) throws IllegalJobException, Exception {
294+
pl.progressChanged(this, 0);
295+
this.currentPower = -1;
296+
this.currentSpeed = -1;
297+
298+
pl.taskChanged(this, "checking job");
299+
checkJob(job);
300+
this.jobName = job.getName()+".gcode";
301+
job.applyStartPoint();
302+
pl.taskChanged(this, "connecting...");
303+
connect(pl);
304+
pl.taskChanged(this, "sending");
305+
try {
306+
writeInitializationCode();
307+
308+
boolean wasSimpleMode = isSimpleStreamMode();
309+
setSimpleStreamMode( false );
310+
311+
pl.progressChanged(this, 20);
312+
int i = 0;
313+
int max = job.getParts().size();
314+
for (JobPart p : job.getParts())
315+
{
316+
if (p instanceof Raster3dPart || p instanceof RasterPart)
317+
{
318+
p = convertRasterizableToVectorPart((RasterizableJobPart) p, p.getDPI(), getUseBidirectionalRastering());
319+
}
320+
if (p instanceof VectorPart)
321+
{
322+
//TODO: in direct mode use progress listener to indicate progress
323+
//of individual job
324+
writeVectorGCode((VectorPart) p, p.getDPI());
325+
}
326+
i++;
327+
pl.progressChanged(this, 20 + (int) (i*(double) 60/max));
328+
}
329+
setSimpleStreamMode(wasSimpleMode);
330+
writeShutdownCode();
331+
disconnect(job.getName()+".gcode");
332+
}
333+
catch (IOException e) {
334+
pl.taskChanged(this, "disconnecting");
335+
disconnect(this.jobName);
336+
throw e;
337+
}
338+
pl.taskChanged(this, "sent.");
339+
pl.progressChanged(this, 100);
340+
}
341+
342+
@Override
343+
protected void setKeysMissingFromDeserialization()
344+
{
345+
super.setKeysMissingFromDeserialization();
346+
commandLenQueue = new ArrayDeque<Integer>();
347+
simpleStreamMode = true;
348+
}
349+
213350
@Override
214351
public Grbl clone()
215352
{

0 commit comments

Comments
 (0)