1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
10 from Cura.avr_isp import stk500v2
11 from Cura.avr_isp import ispBase
12 from Cura.avr_isp import intelHex
14 from Cura.gui.util import taskbar
15 from Cura.util import machineCom
16 from Cura.util import profile
17 from Cura.util import resources
19 def getDefaultFirmware(machineIndex = None):
20 machine_type = profile.getMachineSetting('machine_type', machineIndex)
21 extruders = profile.getMachineSettingFloat('extruder_amount', machineIndex)
22 heated_bed = profile.getMachineSetting('has_heated_bed', machineIndex) == 'True'
24 if sys.platform.startswith('linux'):
26 if machine_type == 'ultimaker':
27 name = 'MarlinUltimaker'
32 name += '-%d' % (baudrate)
35 return resources.getPathForFirmware(name + '.hex')
37 if machine_type == 'ultimaker_plus':
38 name = 'MarlinUltimaker-UMOP-%d' % (baudrate)
43 return resources.getPathForFirmware(name + '.hex')
45 if machine_type == 'ultimaker2':
49 return resources.getPathForFirmware("MarlinUltimaker2-dual.hex")
50 return resources.getPathForFirmware("MarlinUltimaker2.hex")
51 if machine_type == 'ultimaker2go':
52 return resources.getPathForFirmware("MarlinUltimaker2go.hex")
53 if machine_type == 'ultimaker2extended':
57 return resources.getPathForFirmware("MarlinUltimaker2extended-dual.hex")
58 return resources.getPathForFirmware("MarlinUltimaker2extended.hex")
59 if machine_type == 'Witbox':
60 return resources.getPathForFirmware("MarlinWitbox.hex")
63 class InstallFirmware(wx.Dialog):
64 def __init__(self, parent = None, filename = None, port = None, machineIndex = None):
65 super(InstallFirmware, self).__init__(parent=parent, title="Firmware install for %s" % (profile.getMachineSetting('machine_name', machineIndex).title()), size=(250, 100))
67 port = profile.getMachineSetting('serial_port')
69 filename = getDefaultFirmware(machineIndex)
71 wx.MessageBox(_("I am sorry, but Cura does not ship with a default firmware for your machine configuration."), _("Firmware update"), wx.OK | wx.ICON_ERROR)
74 self._machine_type = profile.getMachineSetting('machine_type', machineIndex)
75 if self._machine_type == 'reprap':
76 wx.MessageBox(_("Cura only supports firmware updates for ATMega2560 based hardware.\nSo updating your RepRap with Cura might or might not work."), _("Firmware update"), wx.OK | wx.ICON_INFORMATION)
78 sizer = wx.BoxSizer(wx.VERTICAL)
80 self.progressLabel = wx.StaticText(self, -1, 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nX\nX')
81 sizer.Add(self.progressLabel, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
82 self.progressGauge = wx.Gauge(self, -1)
83 sizer.Add(self.progressGauge, 0, flag=wx.EXPAND)
84 self.okButton = wx.Button(self, -1, _("OK"))
85 self.okButton.Disable()
86 self.okButton.Bind(wx.EVT_BUTTON, self.OnOk)
87 sizer.Add(self.okButton, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
90 self.filename = filename
96 self.thread = threading.Thread(target=self.OnRun)
97 self.thread.daemon = True
105 wx.CallAfter(self.updateLabel, _("Reading firmware..."))
106 hexFile = intelHex.readHex(self.filename)
107 wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
108 programmer = stk500v2.Stk500v2()
109 programmer.progressCallback = self.OnProgress
110 if self.port == 'AUTO':
111 wx.CallAfter(self.updateLabel, _("Please connect the printer to\nyour computer with the USB cable."))
112 while not programmer.isConnected():
113 for self.port in machineCom.serialList(True):
115 programmer.connect(self.port)
117 except ispBase.IspError:
125 programmer.connect(self.port)
126 except ispBase.IspError:
129 if not programmer.isConnected():
130 wx.MessageBox(_("Failed to find machine for firmware upgrade\nIs your machine connected to the PC?"),
131 _("Firmware update"), wx.OK | wx.ICON_ERROR)
132 wx.CallAfter(self.Close)
135 if self._machine_type == 'ultimaker':
136 if programmer.hasChecksumFunction():
137 wx.CallAfter(self.updateLabel, _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UMO firmware on an UM2 or UMO+?"))
139 wx.CallAfter(self.okButton.Enable)
141 if self._machine_type == 'ultimaker_plus' or self._machine_type == 'ultimaker2':
142 if not programmer.hasChecksumFunction():
143 wx.CallAfter(self.updateLabel, _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UM2 or UMO+ firmware on an UMO?"))
145 wx.CallAfter(self.okButton.Enable)
148 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
150 programmer.programChip(hexFile)
151 wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
152 except ispBase.IspError as e:
153 wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))
156 wx.CallAfter(self.okButton.Enable)
158 def updateLabel(self, text):
159 self.progressLabel.SetLabel(text)
162 def OnProgress(self, value, max):
163 wx.CallAfter(self.progressGauge.SetRange, max)
164 wx.CallAfter(self.progressGauge.SetValue, value)
165 taskbar.setProgress(self.GetParent(), value, max)
169 taskbar.setBusy(self.GetParent(), False)
171 def OnClose(self, e):
175 class AutoUpdateFirmware(wx.Dialog):
176 def __init__(self, parent, filename = None, port = None, machineIndex = None):
177 super(AutoUpdateFirmware, self).__init__(parent=parent, title="Auto Firmware install", size=(250, 500))
179 port = profile.getMachineSetting('serial_port')
182 sizer = wx.BoxSizer(wx.VERTICAL)
184 self.progressLabel = wx.StaticText(self, -1, 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nX\nX')
185 sizer.Add(self.progressLabel, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
186 self.progressGauge = wx.Gauge(self, -1)
187 sizer.Add(self.progressGauge, 0, flag=wx.EXPAND)
188 self.okButton = wx.Button(self, -1, _("OK"))
189 self.okButton.Bind(wx.EVT_BUTTON, self.OnOk)
190 sizer.Add(self.okButton, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
192 f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
193 self._termLog = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_DONTWRAP)
194 self._termLog.SetFont(f)
195 self._termLog.SetEditable(0)
196 self._termLog.SetMinSize((1, 400))
197 self._termInput = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
198 self._termInput.SetFont(f)
199 sizer.Add(self._termLog, 0, flag=wx.ALIGN_CENTER|wx.ALL|wx.EXPAND)
200 sizer.Add(self._termInput, 0, flag=wx.ALIGN_CENTER|wx.ALL|wx.EXPAND)
202 self.Bind(wx.EVT_TEXT_ENTER, self.OnTermEnterLine, self._termInput)
206 self.filename = filename
212 self.thread = threading.Thread(target=self.OnRun)
213 self.thread.daemon = True
216 self.read_thread = threading.Thread(target=self.OnSerialRead)
217 self.read_thread.daemon = True
218 self.read_thread.start()
224 def _addTermLog(self, line):
225 if self._termLog is not None:
226 if len(self._termLog.GetValue()) > 10000:
227 self._termLog.SetValue(self._termLog.GetValue()[-10000:])
228 self._termLog.SetInsertionPointEnd()
229 if type(line) != unicode:
230 line = unicode(line, 'utf-8', 'replace')
231 self._termLog.AppendText(line.encode('utf-8', 'replace'))
233 def OnTermEnterLine(self, e):
234 lines = self._termInput.GetValue().split(';')
238 self._addTermLog('> %s\n' % (line))
239 if self._serial is not None:
240 self._serial.write(line + '\n')
245 new_mtime = os.stat(self.filename).st_mtime
246 if mtime != new_mtime:
248 if self._serial is not None:
254 self._serial = serial.Serial(self.port, 250000)
259 def OnSerialRead(self):
261 if self._serial is None:
265 line = self._serial.readline()
266 wx.CallAfter(self._addTermLog, line)
271 wx.CallAfter(self.okButton.Disable)
272 wx.CallAfter(self.updateLabel, _("Reading firmware..."))
273 hexFile = intelHex.readHex(self.filename)
274 wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
275 programmer = stk500v2.Stk500v2()
276 programmer.progressCallback = self.OnProgress
277 if self.port == 'AUTO':
278 wx.CallAfter(self.updateLabel, _("Please connect the printer to\nyour computer with the USB cable."))
279 while not programmer.isConnected():
280 for self.port in machineCom.serialList(True):
282 programmer.connect(self.port)
284 except ispBase.IspError:
292 programmer.connect(self.port)
293 except ispBase.IspError:
296 if not programmer.isConnected():
297 wx.CallAfter(self.updateLabel, _("Failed to connect to programmer.\n"))
300 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
302 programmer.programChip(hexFile)
303 wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
304 except ispBase.IspError as e:
305 wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))
308 wx.CallAfter(self.okButton.Enable)
310 def updateLabel(self, text):
311 self.progressLabel.SetLabel(text)
314 def OnProgress(self, value, max):
315 wx.CallAfter(self.progressGauge.SetRange, max)
316 wx.CallAfter(self.progressGauge.SetValue, value)
317 taskbar.setProgress(self.GetParent(), value, max)
321 taskbar.setBusy(self.GetParent(), False)
323 def OnClose(self, e):