chiark / gitweb /
Use same quickprint settings for lulzbot_TAZ and lulzbot_TAZ_4
[cura.git] / Cura / gui / firmwareInstall.py
1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
2
3 import os
4 import wx
5 import threading
6 import sys
7 import time
8 import serial
9
10 from Cura.avr_isp import stk500v2
11 from Cura.avr_isp import ispBase
12 from Cura.avr_isp import intelHex
13
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
18
19 def getDefaultFirmware(machineIndex = None):
20         if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker':
21                 name = 'MarlinUltimaker'
22                 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
23                         return None
24                 if profile.getMachineSetting('has_heated_bed', machineIndex) == 'True':
25                         name += '-HBK'
26                 if sys.platform.startswith('linux'):
27                         name += '-115200'
28                 else:
29                         name += '-250000'
30                 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
31                         name += '-dual'
32                 return resources.getPathForFirmware(name + '.hex')
33
34         if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker_plus':
35                 name = 'MarlinUltimaker-UMOP'
36                 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
37                         return None
38                 if sys.platform.startswith('linux'):
39                         name += '-115200'
40                 else:
41                         name += '-250000'
42                 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 1:
43                         name += '-dual'
44                 return resources.getPathForFirmware(name + '.hex')
45
46         if profile.getMachineSetting('machine_type', machineIndex) == 'ultimaker2':
47                 if profile.getMachineSettingFloat('extruder_amount', machineIndex) > 2:
48                         return None
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")
56         return None
57
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))
61                 if port is None:
62                         port = profile.getMachineSetting('serial_port')
63                 if filename is None:
64                         filename = getDefaultFirmware(machineIndex)
65                 if filename is None:
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)
67                         self.Destroy()
68                         return
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)
72
73                 sizer = wx.BoxSizer(wx.VERTICAL)
74
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)
83                 self.SetSizer(sizer)
84
85                 self.filename = filename
86                 self.port = port
87
88                 self.Layout()
89                 self.Fit()
90
91                 self.thread = threading.Thread(target=self.OnRun)
92                 self.thread.daemon = True
93                 self.thread.start()
94
95                 self.ShowModal()
96                 self.Destroy()
97                 return
98
99         def OnRun(self):
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):
109                                         try:
110                                                 programmer.connect(self.port)
111                                                 break
112                                         except ispBase.IspError:
113                                                 programmer.close()
114                                 time.sleep(1)
115                                 if not self:
116                                         #Window destroyed
117                                         return
118                 else:
119                         try:
120                                 programmer.connect(self.port)
121                         except ispBase.IspError:
122                                 programmer.close()
123
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)
128                         return
129
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+?"))
133                                 programmer.close()
134                                 wx.CallAfter(self.okButton.Enable)
135                                 return
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?"))
139                                 programmer.close()
140                                 wx.CallAfter(self.okButton.Enable)
141                                 return
142
143                 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
144                 try:
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))
149
150                 programmer.close()
151                 wx.CallAfter(self.okButton.Enable)
152
153         def updateLabel(self, text):
154                 self.progressLabel.SetLabel(text)
155                 #self.Layout()
156
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)
161
162         def OnOk(self, e):
163                 self.Close()
164                 taskbar.setBusy(self.GetParent(), False)
165
166         def OnClose(self, e):
167                 self.Destroy()
168
169
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))
173                 if port is None:
174                         port = profile.getMachineSetting('serial_port')
175                 self._serial = None
176
177                 sizer = wx.BoxSizer(wx.VERTICAL)
178
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)
186
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)
196
197                 self.Bind(wx.EVT_TEXT_ENTER, self.OnTermEnterLine, self._termInput)
198
199                 self.SetSizer(sizer)
200
201                 self.filename = filename
202                 self.port = port
203
204                 self.Layout()
205                 self.Fit()
206
207                 self.thread = threading.Thread(target=self.OnRun)
208                 self.thread.daemon = True
209                 self.thread.start()
210
211                 self.read_thread = threading.Thread(target=self.OnSerialRead)
212                 self.read_thread.daemon = True
213                 self.read_thread.start()
214
215                 self.ShowModal()
216                 self.Destroy()
217                 return
218
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'))
227
228         def OnTermEnterLine(self, e):
229                 lines = self._termInput.GetValue().split(';')
230                 for line in lines:
231                         if line == '':
232                                 continue
233                         self._addTermLog('> %s\n' % (line))
234                         if self._serial is not None:
235                                 self._serial.write(line + '\n')
236
237         def OnRun(self):
238                 mtime = 0
239                 while bool(self):
240                         new_mtime = os.stat(self.filename).st_mtime
241                         if mtime != new_mtime:
242                                 mtime = new_mtime
243                                 if self._serial is not None:
244                                         self._serial.close()
245                                         self._serial = None
246                                 time.sleep(0.5)
247                                 self.OnInstall()
248                                 try:
249                                         self._serial = serial.Serial(self.port, 250000)
250                                 except:
251                                         pass
252                         time.sleep(0.5)
253
254         def OnSerialRead(self):
255                 while bool(self):
256                         if self._serial is None:
257                                 time.sleep(0.5)
258                         else:
259                                 try:
260                                         line = self._serial.readline()
261                                         wx.CallAfter(self._addTermLog, line)
262                                 except:
263                                         pass
264
265         def OnInstall(self):
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):
276                                         try:
277                                                 programmer.connect(self.port)
278                                                 break
279                                         except ispBase.IspError:
280                                                 pass
281                                 time.sleep(1)
282                                 if not self:
283                                         #Window destroyed
284                                         return
285                 else:
286                         try:
287                                 programmer.connect(self.port)
288                         except ispBase.IspError:
289                                 pass
290
291                 if not programmer.isConnected():
292                         wx.CallAfter(self.updateLabel, _("Failed to connect to programmer.\n"))
293                         return
294
295                 wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
296                 try:
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))
301
302                 programmer.close()
303                 wx.CallAfter(self.okButton.Enable)
304
305         def updateLabel(self, text):
306                 self.progressLabel.SetLabel(text)
307                 #self.Layout()
308
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)
313
314         def OnOk(self, e):
315                 self.Close()
316                 taskbar.setBusy(self.GetParent(), False)
317
318         def OnClose(self, e):
319                 self.Destroy()
320