Commit 208be01c authored by Guillaume Seguin's avatar Guillaume Seguin

Initial untested implementation of gcoder-based printing.

parent b6159d8f
...@@ -22,6 +22,7 @@ import time, getopt, sys ...@@ -22,6 +22,7 @@ import time, getopt, sys
import platform, os import platform, os
from collections import deque from collections import deque
from GCodeAnalyzer import GCodeAnalyzer from GCodeAnalyzer import GCodeAnalyzer
from printrun import gcoder
def control_ttyhup(port, disable_hup): def control_ttyhup(port, disable_hup):
"""Controls the HUPCL""" """Controls the HUPCL"""
...@@ -48,7 +49,7 @@ class printcore(): ...@@ -48,7 +49,7 @@ class printcore():
self.clear = 0 #clear to send, enabled after responses self.clear = 0 #clear to send, enabled after responses
self.online = False #The printer has responded to the initial command and is active self.online = False #The printer has responded to the initial command and is active
self.printing = False #is a print currently running, true if printing, false if paused self.printing = False #is a print currently running, true if printing, false if paused
self.mainqueue = [] self.mainqueue = None
self.priqueue = [] self.priqueue = []
self.queueindex = 0 self.queueindex = 0
self.lineno = 0 self.lineno = 0
...@@ -204,8 +205,8 @@ class printcore(): ...@@ -204,8 +205,8 @@ class printcore():
def _checksum(self, command): def _checksum(self, command):
return reduce(lambda x, y:x^y, map(ord, command)) return reduce(lambda x, y:x^y, map(ord, command))
def startprint(self, data, startindex = 0): def startprint(self, gcode, startindex = 0):
"""Start a print, data is an array of gcode commands. """Start a print, gcode is an array of gcode commands.
returns True on success, False if already printing. returns True on success, False if already printing.
The print queue will be replaced with the contents of the data array, the next line will be set to 0 and the firmware notified. The print queue will be replaced with the contents of the data array, the next line will be set to 0 and the firmware notified.
Printing will then start in a parallel thread. Printing will then start in a parallel thread.
...@@ -213,12 +214,12 @@ class printcore(): ...@@ -213,12 +214,12 @@ class printcore():
if self.printing or not self.online or not self.printer: if self.printing or not self.online or not self.printer:
return False return False
self.printing = True self.printing = True
self.mainqueue = [] + data self.mainqueue = gcode
self.lineno = 0 self.lineno = 0
self.queueindex = startindex self.queueindex = startindex
self.resendfrom = -1 self.resendfrom = -1
self._send("M110", -1, True) self._send("M110", -1, True)
if len(data) == 0: if not gcode.lines:
return True return True
self.clear = False self.clear = False
self.print_thread = Thread(target = self._print) self.print_thread = Thread(target = self._print)
...@@ -265,8 +266,6 @@ class printcore(): ...@@ -265,8 +266,6 @@ class printcore():
self.pauseF = self.analyzer.f; self.pauseF = self.analyzer.f;
self.pauseRelative = self.analyzer.relative; self.pauseRelative = self.analyzer.relative;
def resume(self): def resume(self):
"""Resumes a paused print. """Resumes a paused print.
""" """
...@@ -380,13 +379,13 @@ class printcore(): ...@@ -380,13 +379,13 @@ class printcore():
if self.priqueue: if self.priqueue:
self._send(self.priqueue.pop(0)) self._send(self.priqueue.pop(0))
return return
if self.printing and self.queueindex < len(self.mainqueue): if self.printing and self.queueindex < len(self.mainqueue.idxs):
tline = self.mainqueue[self.queueindex] (layer, line) = self.mainqueue.idxs[self.queueindex]
tline = self.mainqueue.all_layers[layer].lines[line].raw
#check for host command #check for host command
if tline.lstrip().startswith(";@"): if tline.lstrip().startswith(";@"):
#it is a host command: pop it from the list
self.mainqueue.pop(self.queueindex)
self.processHostCommand(tline) self.processHostCommand(tline)
self.queueindex += 1
return return
tline = tline.split(";")[0] tline = tline.split(";")[0]
...@@ -455,7 +454,8 @@ if __name__ == '__main__': ...@@ -455,7 +454,8 @@ if __name__ == '__main__':
p = printcore(port, baud) p = printcore(port, baud)
p.loud = loud p.loud = loud
time.sleep(2) time.sleep(2)
gcode = [i.replace("\n", "") for i in open(filename)] gcode = [i.strip() for i in open(filename)]
gcode = gcoder.GCode(gcode)
p.startprint(gcode) p.startprint(gcode)
try: try:
......
...@@ -130,6 +130,12 @@ class GCode(object): ...@@ -130,6 +130,12 @@ class GCode(object):
layers = None layers = None
all_layers = None all_layers = None
idxs = None idxs = None
append_layer = None
append_layer_id = None
imperial = False
relative = False
relative_e = False
def __init__(self,data): def __init__(self,data):
self.lines = [Line(l2) for l2 in self.lines = [Line(l2) for l2 in
...@@ -138,11 +144,26 @@ class GCode(object): ...@@ -138,11 +144,26 @@ class GCode(object):
self._preprocess() self._preprocess()
self._create_layers() self._create_layers()
def _preprocess(self): def __len__(self):
return len(self.idxs)
def append(self, command):
command = command.strip()
if not command:
return
gline = Line(command)
self.lines.append(gline)
self._preprocess([gline])
self.append_layer.lines.append(gline)
self.idxs.append((self.append_layer_id, len(self.append_layer.lines)))
def _preprocess(self, lines = None):
"""Checks for G20, G21, G90 and G91, sets imperial and relative flags""" """Checks for G20, G21, G90 and G91, sets imperial and relative flags"""
imperial = False if not lines:
relative = False lines = self.lines
relative_e = False imperial = self.imperial
relative = self.relative
relative_e = self.relative_e
for line in self.lines: for line in self.lines:
if line.is_move: if line.is_move:
line.relative = relative line.relative = relative
...@@ -163,6 +184,9 @@ class GCode(object): ...@@ -163,6 +184,9 @@ class GCode(object):
relative_e = True relative_e = True
if line.command[0] == "G": if line.command[0] == "G":
line.parse_coordinates(imperial) line.parse_coordinates(imperial)
self.imperial = imperial
self.relative = relative
self.relative_e = relative_e
# FIXME : looks like this needs to be tested with list Z on move # FIXME : looks like this needs to be tested with list Z on move
def _create_layers(self): def _create_layers(self):
...@@ -218,6 +242,9 @@ class GCode(object): ...@@ -218,6 +242,9 @@ class GCode(object):
else: else:
del layers[idx] del layers[idx]
self.append_layer_id = len(all_layers)
self.append_layer = Layer([])
all_layers.append(self.append_layer)
self.all_layers = all_layers self.all_layers = all_layers
self.layers = layers self.layers = layers
self.idxs = idxs self.idxs = idxs
......
...@@ -629,7 +629,7 @@ class pronsole(cmd.Cmd): ...@@ -629,7 +629,7 @@ class pronsole(cmd.Cmd):
self.log(_("Uploading %s") % self.filename) self.log(_("Uploading %s") % self.filename)
self.p.send_now("M28 " + targetname) self.p.send_now("M28 " + targetname)
self.log(_("Press Ctrl-C to interrupt upload.")) self.log(_("Press Ctrl-C to interrupt upload."))
self.p.startprint(self.f) self.p.startprint(self.fgcode)
try: try:
sys.stdout.write(_("Progress: ") + "00.0%") sys.stdout.write(_("Progress: ") + "00.0%")
sys.stdout.flush() sys.stdout.flush()
...@@ -651,7 +651,7 @@ class pronsole(cmd.Cmd): ...@@ -651,7 +651,7 @@ class pronsole(cmd.Cmd):
self.p.send_now("M29 "+targetname) self.p.send_now("M29 "+targetname)
time.sleep(0.2) time.sleep(0.2)
self.p.clear = 1 self.p.clear = 1
self.p.startprint([]) self.p.startprint(None)
self.log(_("A partial file named %s may have been written to the sd card.") % targetname) self.log(_("A partial file named %s may have been written to the sd card.") % targetname)
def complete_upload(self, text, line, begidx, endidx): def complete_upload(self, text, line, begidx, endidx):
...@@ -668,13 +668,13 @@ class pronsole(cmd.Cmd): ...@@ -668,13 +668,13 @@ class pronsole(cmd.Cmd):
self.log("Uploads a gcode file to the sd card") self.log("Uploads a gcode file to the sd card")
def help_print(self): def help_print(self):
if not self.f: if not self.fgcode:
self.log(_("Send a loaded gcode file to the printer. Load a file with the load command first.")) self.log(_("Send a loaded gcode file to the printer. Load a file with the load command first."))
else: else:
self.log(_("Send a loaded gcode file to the printer. You have %s loaded right now.") % self.filename) self.log(_("Send a loaded gcode file to the printer. You have %s loaded right now.") % self.filename)
def do_print(self, l): def do_print(self, l):
if not self.f: if not self.fgcode:
self.log(_("No file loaded. Please use load first.")) self.log(_("No file loaded. Please use load first."))
return return
if not self.p.online: if not self.p.online:
...@@ -682,7 +682,7 @@ class pronsole(cmd.Cmd): ...@@ -682,7 +682,7 @@ class pronsole(cmd.Cmd):
return return
self.log(_("Printing %s") % self.filename) self.log(_("Printing %s") % self.filename)
self.log(_("You can monitor the print with the monitor command.")) self.log(_("You can monitor the print with the monitor command."))
self.p.startprint(self.f) self.p.startprint(self.fgcode)
def do_pause(self, l): def do_pause(self, l):
if self.sdprinting: if self.sdprinting:
......
...@@ -587,7 +587,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -587,7 +587,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
obj = e.GetEventObject() obj = e.GetEventObject()
popupmenu = wx.Menu() popupmenu = wx.Menu()
item = popupmenu.Append(-1, _("SD Upload")) item = popupmenu.Append(-1, _("SD Upload"))
if not self.f or not len(self.f): if not self.f:
item.Enable(False) item.Enable(False)
self.Bind(wx.EVT_MENU, self.upload, id = item.GetId()) self.Bind(wx.EVT_MENU, self.upload, id = item.GetId())
item = popupmenu.Append(-1, _("SD Print")) item = popupmenu.Append(-1, _("SD Print"))
...@@ -605,7 +605,7 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -605,7 +605,7 @@ class PronterWindow(MainWindow, pronsole.pronsole):
wx.CallAfter(self.btemp.SetInsertionPoint, 0) wx.CallAfter(self.btemp.SetInsertionPoint, 0)
def showwin(self, event): def showwin(self, event):
if self.f is not None: if self.f:
self.gwindow.Show(True) self.gwindow.Show(True)
self.gwindow.SetToolTip(wx.ToolTip("Mousewheel zooms the display\nShift / Mousewheel scrolls layers")) self.gwindow.SetToolTip(wx.ToolTip("Mousewheel zooms the display\nShift / Mousewheel scrolls layers"))
self.gwindow.Raise() self.gwindow.Raise()
...@@ -1236,13 +1236,12 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1236,13 +1236,12 @@ class PronterWindow(MainWindow, pronsole.pronsole):
fn = self.filename fn = self.filename
try: try:
self.filename = self.filename.replace(".stl", "_export.gcode").replace(".STL", "_export.gcode").replace(".obj", "_export.gcode").replace(".OBJ", "_export.gcode") self.filename = self.filename.replace(".stl", "_export.gcode").replace(".STL", "_export.gcode").replace(".obj", "_export.gcode").replace(".OBJ", "_export.gcode")
of = open(self.filename) self.f = [line.strip() for line in open(self.filename)]
self.f = [i.replace("\n", "").replace("\r", "") for i in of] self.fgcode = gcoder.GCode(self.f)
of.close()
if self.p.online: if self.p.online:
wx.CallAfter(self.printbtn.Enable) wx.CallAfter(self.printbtn.Enable)
wx.CallAfter(self.status.SetStatusText, _("Loaded ")+self.filename+_(", %d lines") % (len(self.f),)) wx.CallAfter(self.status.SetStatusText, _("Loaded %s, %d lines") % (self.filename, len(self.f),))
wx.CallAfter(self.pausebtn.Disable) wx.CallAfter(self.pausebtn.Disable)
wx.CallAfter(self.printbtn.SetLabel, _("Print")) wx.CallAfter(self.printbtn.SetLabel, _("Print"))
...@@ -1299,9 +1298,8 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1299,9 +1298,8 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.skein(name) self.skein(name)
else: else:
self.filename = name self.filename = name
of = open(self.filename) self.f = [line.strip() for line in open(self.filename)]
self.f = [i.replace("\n", "").replace("\r", "") for i in of] self.fgcode = gcoder.GCode(self.f)
of.close()
self.status.SetStatusText(_("Loaded %s, %d lines") % (name, len(self.f))) self.status.SetStatusText(_("Loaded %s, %d lines") % (name, len(self.f)))
wx.CallAfter(self.printbtn.SetLabel, _("Print")) wx.CallAfter(self.printbtn.SetLabel, _("Print"))
wx.CallAfter(self.pausebtn.SetLabel, _("Pause")) wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
...@@ -1337,14 +1335,14 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1337,14 +1335,14 @@ class PronterWindow(MainWindow, pronsole.pronsole):
self.p.send_now("M24") self.p.send_now("M24")
return return
if self.f is None or not len(self.f): if not self.f:
wx.CallAfter(self.status.SetStatusText, _("No file loaded. Please use load first.")) wx.CallAfter(self.status.SetStatusText, _("No file loaded. Please use load first."))
return return
if not self.p.online: if not self.p.online:
wx.CallAfter(self.status.SetStatusText, _("Not connected to printer.")) wx.CallAfter(self.status.SetStatusText, _("Not connected to printer."))
return return
self.on_startprint() self.on_startprint()
self.p.startprint(self.f) self.p.startprint(self.fgcode)
def on_startprint(self): def on_startprint(self):
wx.CallAfter(self.pausebtn.SetLabel, _("Pause")) wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
...@@ -1361,14 +1359,14 @@ class PronterWindow(MainWindow, pronsole.pronsole): ...@@ -1361,14 +1359,14 @@ class PronterWindow(MainWindow, pronsole.pronsole):
def uploadtrigger(self, l): def uploadtrigger(self, l):
if "Writing to file" in l: if "Writing to file" in l:
self.uploading = True self.uploading = True
self.p.startprint(self.f) self.p.startprint(self.fgcode)
self.p.endcb = self.endupload self.p.endcb = self.endupload
self.recvlisteners.remove(self.uploadtrigger) self.recvlisteners.remove(self.uploadtrigger)
elif "open failed, File" in l: elif "open failed, File" in l:
self.recvlisteners.remove(self.uploadtrigger) self.recvlisteners.remove(self.uploadtrigger)
def upload(self, event): def upload(self, event):
if not self.f or not len(self.f): if not self.f:
return return
if not self.p.online: if not self.p.online:
return return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment