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 if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker':
21 name = 'MarlinUltimaker'
22 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
24 if profile.getMachineSetting('has_heated_bed', machineIndex) == 'True':
26 if sys.platform.startswith('linux'):
30 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
32 return resources.getPathForFirmware(name + '.hex')
34 if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker_plus':
35 name = 'MarlinUltimaker-UMOP'
36 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
38 if sys.platform.startswith('linux'):
42 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
44 return resources.getPathForFirmware(name + '.hex')
46 if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker2':
47 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
49 if profile.getMachineSettingFloat('extruder_amount', machineIndex) == 2:
50 return resources.getPathForFirmware("MarlinUltimaker2-dual.hex")
51 return resources.getPathForFirmware("MarlinUltimaker2.hex")
52 if profile.getMachineSetting('machine_type', machineIndex) == 'lulzbot_mini':
53 return resources.getPathForFirmware("marlin_mini_2014Q4.hex")
54 if profile.getMachineSetting('machine_type', machineIndex) == 'Witbox':
55 return resources.getPathForFirmware("MarlinWitbox.hex")
58 class InstallFirmware(wx.Dialog):
59 def __init__(self, parent = None, filename = None, port = None, machineIndex = None):
60 super(InstallFirmware, self).__init__(parent=parent, title=_("Firmware install for %s") % (profile.getMachineSetting('machine_name', machineIndex).title()), size=(250, 100))
62 port = profile.getMachineSetting('serial_port')
64 filename = getDefaultFirmware(machineIndex)
66 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)
69 self._machine_type = profile.getMachineSetting('machine_type', machineIndex)
70 if self._machine_type == 'reprap':
71 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)
73 sizer = wx.BoxSizer(wx.VERTICAL)
75 self.progressLabel = wx.StaticText(self, -1, 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nX\nX')
76 sizer.Add(self.progressLabel, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
77 self.progressGauge = wx.Gauge(self, -1)
78 sizer.Add(self.progressGauge, 0, flag=wx.EXPAND)
79 self.okButton = wx.Button(self, -1, _("OK"))
80 self.okButton.Disable()
81 self.okButton.Bind(wx.EVT_BUTTON, self.OnOk)
82 sizer.Add(self.okButton, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
85 self.filename = filename
91 self.thread = threading.Thread(target=self.OnRun)
92 self.thread.daemon = True
100 wx.CallAfter(self.updateLabel, _("Reading firmware..."))
101 hexFile = intelHex.readHex(self.filename)
102 wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
103 programmer = stk500v2.Stk500v2()
104 programmer.progressCallback = self.OnProgress
105 if self.port == 'AUTO':
106 wx.CallAfter(self.updateLabel, _("Please connect the printer to\nyour computer with the USB cable."))
107 while not programmer.isConnected():
108 for self.port in machineCom.serialList(True):
110 programmer.connect(self.port)
112 except ispBase.IspError:
120 programmer.connect(self.port)
121 except ispBase.IspError:
124 if not programmer.isConnected():
125 wx.MessageBox(_("Failed to find machine for firmware upgrade\nIs your machine connected to the PC?"),
126 _("Firmware update"), wx.OK | wx.ICON_ERROR)
127 wx.CallAfter(self.Close)
130 if self._machine_type == 'ultimaker':
131 if programmer.hasChecksumFunction():
132 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+?"))
134 wx.CallAfter(self.okButton.Enable)
136 if self._machine_type == 'ultimaker_plus' or self._machine_type == 'ultimaker2':
137 if not programmer.hasChecksumFunction():
138 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?"))
140 wx.CallAfter(self.okButton.Enable)
143 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
145 programmer.programChip(hexFile)
146 wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
147 except ispBase.IspError as e:
148 wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))
151 wx.CallAfter(self.okButton.Enable)
153 def updateLabel(self, text):
154 self.progressLabel.SetLabel(text)
157 def OnProgress(self, value, max):
158 wx.CallAfter(self.progressGauge.SetRange, max)
159 wx.CallAfter(self.progressGauge.SetValue, value)
160 taskbar.setProgress(self.GetParent(), value, max)
164 taskbar.setBusy(self.GetParent(), False)
166 def OnClose(self, e):
170 class AutoUpdateFirmware(wx.Dialog):
171 def __init__(self, parent, filename = None, port = None, machineIndex = None):
172 super(AutoUpdateFirmware, self).__init__(parent=parent, title=_("Auto Firmware install"), size=(250, 500))
174 port = profile.getMachineSetting('serial_port')
177 sizer = wx.BoxSizer(wx.VERTICAL)
179 self.progressLabel = wx.StaticText(self, -1, 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\nX\nX')
180 sizer.Add(self.progressLabel, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
181 self.progressGauge = wx.Gauge(self, -1)
182 sizer.Add(self.progressGauge, 0, flag=wx.EXPAND)
183 self.okButton = wx.Button(self, -1, _("OK"))
184 self.okButton.Bind(wx.EVT_BUTTON, self.OnOk)
185 sizer.Add(self.okButton, 0, flag=wx.ALIGN_CENTER|wx.ALL, border=5)
187 f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False)
188 self._termLog = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_DONTWRAP)
189 self._termLog.SetFont(f)
190 self._termLog.SetEditable(0)
191 self._termLog.SetMinSize((1, 400))
192 self._termInput = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER)
193 self._termInput.SetFont(f)
194 sizer.Add(self._termLog, 0, flag=wx.ALIGN_CENTER|wx.ALL|wx.EXPAND)
195 sizer.Add(self._termInput, 0, flag=wx.ALIGN_CENTER|wx.ALL|wx.EXPAND)
197 self.Bind(wx.EVT_TEXT_ENTER, self.OnTermEnterLine, self._termInput)
201 self.filename = filename
207 self.thread = threading.Thread(target=self.OnRun)
208 self.thread.daemon = True
211 self.read_thread = threading.Thread(target=self.OnSerialRead)
212 self.read_thread.daemon = True
213 self.read_thread.start()
219 def _addTermLog(self, line):
220 if self._termLog is not None:
221 if len(self._termLog.GetValue()) > 10000:
222 self._termLog.SetValue(self._termLog.GetValue()[-10000:])
223 self._termLog.SetInsertionPointEnd()
224 if type(line) != unicode:
225 line = unicode(line, 'utf-8', 'replace')
226 self._termLog.AppendText(line.encode('utf-8', 'replace'))
228 def OnTermEnterLine(self, e):
229 lines = self._termInput.GetValue().split(';')
233 self._addTermLog('> %s\n' % (line))
234 if self._serial is not None:
235 self._serial.write(line + '\n')
240 new_mtime = os.stat(self.filename).st_mtime
241 if mtime != new_mtime:
243 if self._serial is not None:
249 self._serial = serial.Serial(self.port, 250000)
254 def OnSerialRead(self):
256 if self._serial is None:
260 line = self._serial.readline()
261 wx.CallAfter(self._addTermLog, line)
266 wx.CallAfter(self.okButton.Disable)
267 wx.CallAfter(self.updateLabel, _("Reading firmware..."))
268 hexFile = intelHex.readHex(self.filename)
269 wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
270 programmer = stk500v2.Stk500v2()
271 programmer.progressCallback = self.OnProgress
272 if self.port == 'AUTO':
273 wx.CallAfter(self.updateLabel, _("Please connect the printer to\nyour computer with the USB cable."))
274 while not programmer.isConnected():
275 for self.port in machineCom.serialList(True):
277 programmer.connect(self.port)
279 except ispBase.IspError:
287 programmer.connect(self.port)
288 except ispBase.IspError:
291 if not programmer.isConnected():
292 wx.CallAfter(self.updateLabel, _("Failed to connect to programmer.\n"))
295 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
297 programmer.programChip(hexFile)
298 wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
299 except ispBase.IspError as e:
300 wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))
303 wx.CallAfter(self.okButton.Enable)
305 def updateLabel(self, text):
306 self.progressLabel.SetLabel(text)
309 def OnProgress(self, value, max):
310 wx.CallAfter(self.progressGauge.SetRange, max)
311 wx.CallAfter(self.progressGauge.SetValue, value)
312 taskbar.setProgress(self.GetParent(), value, max)
316 taskbar.setBusy(self.GetParent(), False)
318 def OnClose(self, e):