python3: pep8 all files.
e.g. 4 spaces for identation using black for this: https://github.com/ambv/black
This commit is contained in:
parent
9b49097ac3
commit
bf72cb7f10
221
configtool.py
221
configtool.py
|
|
@ -14,12 +14,15 @@
|
|||
from __future__ import print_function
|
||||
import sys
|
||||
import time
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
print("You are currently running Python3. Python3 is not supported.\n"
|
||||
print(
|
||||
"You are currently running Python3. Python3 is not supported.\n"
|
||||
"Please try running with Python2.\n\n"
|
||||
"It often works to type \"python2 configtool.py\" in the command line.")
|
||||
time.sleep(10)
|
||||
sys.exit(-1)
|
||||
'It often works to type "python2 configtool.py" in the command line.'
|
||||
)
|
||||
time.sleep(10)
|
||||
sys.exit(-1)
|
||||
|
||||
import getopt
|
||||
import os.path
|
||||
|
|
@ -29,92 +32,99 @@ from configtool.settings import Settings
|
|||
from configtool.board import Board
|
||||
from configtool.printer import Printer
|
||||
|
||||
cmdFolder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(
|
||||
inspect.currentframe()))[0]))
|
||||
cmdFolder = os.path.realpath(
|
||||
os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0])
|
||||
)
|
||||
|
||||
verbose = 0
|
||||
settings = None
|
||||
board = None
|
||||
printer = None
|
||||
|
||||
def getSettings(arg = None):
|
||||
global settings
|
||||
if arg or not settings:
|
||||
settings = Settings(None, cmdFolder, arg)
|
||||
settings.verbose = verbose
|
||||
return settings
|
||||
|
||||
def getSettings(arg=None):
|
||||
global settings
|
||||
if arg or not settings:
|
||||
settings = Settings(None, cmdFolder, arg)
|
||||
settings.verbose = verbose
|
||||
return settings
|
||||
|
||||
|
||||
def cmdLoad(arg):
|
||||
xx, ext = os.path.splitext(arg)
|
||||
fn = os.path.basename(arg)
|
||||
xx, ext = os.path.splitext(arg)
|
||||
fn = os.path.basename(arg)
|
||||
|
||||
if ext == ".ini":
|
||||
settings = getSettings(arg)
|
||||
if not settings.loaded:
|
||||
print("Failed to load settings file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
if ext == ".ini":
|
||||
settings = getSettings(arg)
|
||||
if not settings.loaded:
|
||||
print("Failed to load settings file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
|
||||
if ext == ".h":
|
||||
if fn.startswith("board."):
|
||||
global board
|
||||
board = Board(getSettings())
|
||||
ok, fn = board.loadConfigFile(arg)
|
||||
if not ok:
|
||||
print("Failed trying to load board file: %s." % fn)
|
||||
sys.exit(2)
|
||||
return
|
||||
elif fn.startswith("printer."):
|
||||
global printer
|
||||
printer = Printer(getSettings())
|
||||
ok, fn = printer.loadConfigFile(arg)
|
||||
if not ok:
|
||||
print("Failed trying to load printer file: %s" % fn)
|
||||
sys.exit(2)
|
||||
return
|
||||
if ext == ".h":
|
||||
if fn.startswith("board."):
|
||||
global board
|
||||
board = Board(getSettings())
|
||||
ok, fn = board.loadConfigFile(arg)
|
||||
if not ok:
|
||||
print("Failed trying to load board file: %s." % fn)
|
||||
sys.exit(2)
|
||||
return
|
||||
elif fn.startswith("printer."):
|
||||
global printer
|
||||
printer = Printer(getSettings())
|
||||
ok, fn = printer.loadConfigFile(arg)
|
||||
if not ok:
|
||||
print("Failed trying to load printer file: %s" % fn)
|
||||
sys.exit(2)
|
||||
return
|
||||
|
||||
print("Unrecognized file: %s." % arg)
|
||||
print("Expected one of *.ini, board.*.h or printer.*.h.")
|
||||
sys.exit(2)
|
||||
|
||||
print("Unrecognized file: %s." % arg)
|
||||
print("Expected one of *.ini, board.*.h or printer.*.h.")
|
||||
sys.exit(2)
|
||||
|
||||
def cmdSave(arg):
|
||||
xx, ext = os.path.splitext(arg)
|
||||
fn = os.path.basename(arg)
|
||||
xx, ext = os.path.splitext(arg)
|
||||
fn = os.path.basename(arg)
|
||||
|
||||
if ext == ".ini":
|
||||
if not getSettings(arg).save(arg):
|
||||
print("Failed to save settings file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
if ext == ".ini":
|
||||
if not getSettings(arg).save(arg):
|
||||
print("Failed to save settings file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
|
||||
if ext == ".h":
|
||||
if fn.startswith("board."):
|
||||
global board
|
||||
if not board.saveConfigFile(arg, None):
|
||||
print("Failed trying to save board file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
elif fn.startswith("printer."):
|
||||
global printer
|
||||
if not printer.saveConfigFile(arg, None):
|
||||
print("Failed trying to save printer file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
if ext == ".h":
|
||||
if fn.startswith("board."):
|
||||
global board
|
||||
if not board.saveConfigFile(arg, None):
|
||||
print("Failed trying to save board file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
elif fn.startswith("printer."):
|
||||
global printer
|
||||
if not printer.saveConfigFile(arg, None):
|
||||
print("Failed trying to save printer file: %s." % arg)
|
||||
sys.exit(2)
|
||||
return
|
||||
|
||||
print("Unrecognized file: %s." % arg)
|
||||
print("Expected one of *.ini, board.*.h or printer.*.h.")
|
||||
sys.exit(2)
|
||||
|
||||
print("Unrecognized file: %s." % arg)
|
||||
print("Expected one of *.ini, board.*.h or printer.*.h.")
|
||||
sys.exit(2)
|
||||
|
||||
def cmdShowAll():
|
||||
names = {"configtool": getSettings(), "board": board, "printer": printer}
|
||||
for namespace in names:
|
||||
if names[namespace]:
|
||||
values = names[namespace].getValues()
|
||||
for k in sorted(values):
|
||||
print("%s.%s: %s" % (namespace, k, str(values[k])))
|
||||
names = {"configtool": getSettings(), "board": board, "printer": printer}
|
||||
for namespace in names:
|
||||
if names[namespace]:
|
||||
values = names[namespace].getValues()
|
||||
for k in sorted(values):
|
||||
print("%s.%s: %s" % (namespace, k, str(values[k])))
|
||||
|
||||
|
||||
def cmdHelp():
|
||||
print("""Usage: %s [options]
|
||||
print(
|
||||
"""Usage: %s [options]
|
||||
|
||||
Running without any options starts the gui (normal operation).
|
||||
Following options are available for command line automation:
|
||||
|
|
@ -137,50 +147,55 @@ Following options are available for command line automation:
|
|||
-a, --show-all Show all loaded variables and values.
|
||||
|
||||
-q, --quit Quit processing without launching the GUI.
|
||||
""" % sys.argv[0])
|
||||
"""
|
||||
% sys.argv[0]
|
||||
)
|
||||
|
||||
|
||||
def CommandLine(argv):
|
||||
""" Parse and act on command line arguments. All script automation commands
|
||||
""" Parse and act on command line arguments. All script automation commands
|
||||
result in sys.exit() (i.e. they do not return from this function). Other
|
||||
options like --debug will return to allow the gui to launch.
|
||||
"""
|
||||
global settings, verbose
|
||||
global settings, verbose
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "hvl:as:q", ["help", "verbose", "load=",
|
||||
"show-all", "save=", "quit"])
|
||||
except getopt.GetoptError as err:
|
||||
print(err)
|
||||
print("Use '%s --help' to get help with command line options." %
|
||||
sys.argv[0])
|
||||
sys.exit(2)
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
argv, "hvl:as:q", ["help", "verbose", "load=", "show-all", "save=", "quit"]
|
||||
)
|
||||
except getopt.GetoptError as err:
|
||||
print(err)
|
||||
print("Use '%s --help' to get help with command line options." % sys.argv[0])
|
||||
sys.exit(2)
|
||||
|
||||
# Check for HELP first.
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
cmdHelp()
|
||||
sys.exit()
|
||||
# Check for HELP first.
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
cmdHelp()
|
||||
sys.exit()
|
||||
|
||||
# Now parse other options.
|
||||
for opt, arg in opts:
|
||||
if opt in ("-v", "--verbose"):
|
||||
verbose += 1
|
||||
getSettings()
|
||||
# Now parse other options.
|
||||
for opt, arg in opts:
|
||||
if opt in ("-v", "--verbose"):
|
||||
verbose += 1
|
||||
getSettings()
|
||||
|
||||
elif opt in ("-l", "--load"):
|
||||
cmdLoad(arg)
|
||||
elif opt in ("-l", "--load"):
|
||||
cmdLoad(arg)
|
||||
|
||||
elif opt in ("-s", "--save"):
|
||||
cmdSave(arg)
|
||||
elif opt in ("-s", "--save"):
|
||||
cmdSave(arg)
|
||||
|
||||
elif opt in ("-a", "--show-all"):
|
||||
cmdShowAll()
|
||||
elif opt in ("-a", "--show-all"):
|
||||
cmdShowAll()
|
||||
|
||||
elif opt in ("-q", "--quit"):
|
||||
sys.exit()
|
||||
elif opt in ("-q", "--quit"):
|
||||
sys.exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
CommandLine(sys.argv[1:])
|
||||
|
||||
from configtool.gui import StartGui
|
||||
StartGui(getSettings())
|
||||
if __name__ == "__main__":
|
||||
CommandLine(sys.argv[1:])
|
||||
|
||||
from configtool.gui import StartGui
|
||||
|
||||
StartGui(getSettings())
|
||||
|
|
|
|||
|
|
@ -1,120 +1,126 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
|
||||
|
||||
class AccelerationPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
|
||||
self.accTypeKeys = ['ACCELERATION_REPRAP', 'ACCELERATION_RAMPING',
|
||||
'ACCELERATION_TEMPORAL']
|
||||
self.jerkKeys = ['MAX_JERK_X', 'MAX_JERK_Y', 'MAX_JERK_Z', 'MAX_JERK_E']
|
||||
self.accTypeKeys = [
|
||||
"ACCELERATION_REPRAP",
|
||||
"ACCELERATION_RAMPING",
|
||||
"ACCELERATION_TEMPORAL",
|
||||
]
|
||||
self.jerkKeys = ["MAX_JERK_X", "MAX_JERK_Y", "MAX_JERK_Z", "MAX_JERK_E"]
|
||||
|
||||
self.labels = {'ACCELERATION_REPRAP': "RepRap",
|
||||
'ACCELERATION_RAMPING': "Ramping",
|
||||
'ACCELERATION_TEMPORAL': "Temporal",
|
||||
'ACCELERATION': "Acceleration:",
|
||||
'LOOKAHEAD': "Look Ahead",
|
||||
'MAX_JERK_X': "X:", 'MAX_JERK_Y': "Y:", 'MAX_JERK_Z': "Z:",
|
||||
'MAX_JERK_E': "E:"}
|
||||
self.labels = {
|
||||
"ACCELERATION_REPRAP": "RepRap",
|
||||
"ACCELERATION_RAMPING": "Ramping",
|
||||
"ACCELERATION_TEMPORAL": "Temporal",
|
||||
"ACCELERATION": "Acceleration:",
|
||||
"LOOKAHEAD": "Look Ahead",
|
||||
"MAX_JERK_X": "X:",
|
||||
"MAX_JERK_Y": "Y:",
|
||||
"MAX_JERK_Z": "Z:",
|
||||
"MAX_JERK_E": "E:",
|
||||
}
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos = (0, 0))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Acceleration Type")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
style = wx.RB_GROUP
|
||||
for k in self.accTypeKeys:
|
||||
rb = self.addRadioButton(k, style, self.onAccTypeSelect, b)
|
||||
style = 0
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos=(0, 0))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Acceleration Type")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
style = wx.RB_GROUP
|
||||
for k in self.accTypeKeys:
|
||||
rb = self.addRadioButton(k, style, self.onAccTypeSelect, b)
|
||||
style = 0
|
||||
|
||||
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
self.rbNone = wx.RadioButton(self, wx.ID_ANY, "None", style = style)
|
||||
self.rbNone.SetFont(font)
|
||||
self.rbNone.SetValue(True)
|
||||
self.Bind(wx.EVT_RADIOBUTTON, self.onAccTypeSelect, self.rbNone)
|
||||
sbox.Add(self.rbNone, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
sz.Add(sbox, pos = (1, 1))
|
||||
self.rbNone = wx.RadioButton(self, wx.ID_ANY, "None", style=style)
|
||||
self.rbNone.SetFont(font)
|
||||
self.rbNone.SetValue(True)
|
||||
self.Bind(wx.EVT_RADIOBUTTON, self.onAccTypeSelect, self.rbNone)
|
||||
sbox.Add(self.rbNone, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
sz.Add(sbox, pos=(1, 1))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Ramping Parameters")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Ramping Parameters")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'ACCELERATION'
|
||||
tc = self.addTextCtrl(k, 80, self.onTextCtrlFloat)
|
||||
self.textControls[k].Enable(False)
|
||||
k = "ACCELERATION"
|
||||
tc = self.addTextCtrl(k, 80, self.onTextCtrlFloat)
|
||||
self.textControls[k].Enable(False)
|
||||
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'LOOKAHEAD'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
self.checkBoxes[k].Enable(False)
|
||||
k = "LOOKAHEAD"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
self.checkBoxes[k].Enable(False)
|
||||
|
||||
sbox.Add(cb, 1, wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sbox.Add((5, 5))
|
||||
sbox.Add(cb, 1, wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 3))
|
||||
sz.Add(sbox, pos=(1, 3))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Jerk")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.jerkKeys:
|
||||
tc = self.addTextCtrl(k, 40, self.onTextCtrlInteger)
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Jerk")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.jerkKeys:
|
||||
tc = self.addTextCtrl(k, 40, self.onTextCtrlInteger)
|
||||
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add((80, 20), pos = (1, 4))
|
||||
sz.Add(sbox, pos = (1, 5))
|
||||
sz.Add((80, 20), pos=(1, 4))
|
||||
sz.Add(sbox, pos=(1, 5))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def enableAll(self, flag = True):
|
||||
self.rbNone.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
def enableAll(self, flag=True):
|
||||
self.rbNone.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
|
||||
def onAccTypeSelect(self, evt):
|
||||
self.assertModified(True)
|
||||
rb = evt.GetEventObject()
|
||||
label = rb.GetLabel()
|
||||
def onAccTypeSelect(self, evt):
|
||||
self.assertModified(True)
|
||||
rb = evt.GetEventObject()
|
||||
label = rb.GetLabel()
|
||||
|
||||
if label == self.labels['ACCELERATION_RAMPING']:
|
||||
ena = True
|
||||
else:
|
||||
ena = False
|
||||
if label == self.labels["ACCELERATION_RAMPING"]:
|
||||
ena = True
|
||||
else:
|
||||
ena = False
|
||||
|
||||
self.checkBoxes['LOOKAHEAD'].Enable(ena)
|
||||
self.textControls['ACCELERATION'].Enable(ena)
|
||||
evt.Skip()
|
||||
self.checkBoxes["LOOKAHEAD"].Enable(ena)
|
||||
self.textControls["ACCELERATION"].Enable(ena)
|
||||
evt.Skip()
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
|
||||
self.checkBoxes['LOOKAHEAD'].Enable(False)
|
||||
self.textControls['ACCELERATION'].Enable(False)
|
||||
for tag in self.accTypeKeys:
|
||||
if tag in cfgValues.keys() and cfgValues[tag]:
|
||||
self.radioButtons[tag].SetValue(True)
|
||||
if tag == 'ACCELERATION_RAMPING':
|
||||
self.checkBoxes['LOOKAHEAD'].Enable(True)
|
||||
self.textControls['ACCELERATION'].Enable(True)
|
||||
self.checkBoxes["LOOKAHEAD"].Enable(False)
|
||||
self.textControls["ACCELERATION"].Enable(False)
|
||||
for tag in self.accTypeKeys:
|
||||
if tag in cfgValues.keys() and cfgValues[tag]:
|
||||
self.radioButtons[tag].SetValue(True)
|
||||
if tag == "ACCELERATION_RAMPING":
|
||||
self.checkBoxes["LOOKAHEAD"].Enable(True)
|
||||
self.textControls["ACCELERATION"].Enable(True)
|
||||
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
|
||||
for tag in self.accTypeKeys:
|
||||
result[tag] = self.radioButtons[tag].GetValue()
|
||||
for tag in self.accTypeKeys:
|
||||
result[tag] = self.radioButtons[tag].GetValue()
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,216 +1,229 @@
|
|||
|
||||
import wx
|
||||
from configtool.data import BSIZESMALL, offsetChLabel, offsetTcLabel
|
||||
|
||||
|
||||
class AddHeaterDlg(wx.Dialog):
|
||||
def __init__(self, parent, names, pins, font,
|
||||
name = "", pin = "", invert = "0", pwm = "1", max_pwm = "100"):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Add heater", size = (400, 204))
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onCancel)
|
||||
def __init__(
|
||||
self,
|
||||
parent,
|
||||
names,
|
||||
pins,
|
||||
font,
|
||||
name="",
|
||||
pin="",
|
||||
invert="0",
|
||||
pwm="1",
|
||||
max_pwm="100",
|
||||
):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Add heater", size=(400, 204))
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onCancel)
|
||||
|
||||
self.names = names
|
||||
self.choices = pins
|
||||
self.names = names
|
||||
self.choices = pins
|
||||
|
||||
self.nameValid = (name != "")
|
||||
self.maxPWMValid = (max_pwm != "")
|
||||
self.pwmValid = (pwm != "")
|
||||
self.nameValid = name != ""
|
||||
self.maxPWMValid = max_pwm != ""
|
||||
self.pwmValid = pwm != ""
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
gsz = wx.GridBagSizer()
|
||||
gsz.Add((20, 20), pos = (0, 0))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
gsz = wx.GridBagSizer()
|
||||
gsz.Add((20, 20), pos=(0, 0))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Heater Name:", size = (80, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Heater Name:", size=(80, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
|
||||
self.tcName = wx.TextCtrl(self, wx.ID_ANY, name)
|
||||
self.tcName.SetFont(font)
|
||||
if not name:
|
||||
self.tcName.SetBackgroundColour("pink")
|
||||
self.tcName.Bind(wx.EVT_TEXT, self.onNameEntry)
|
||||
lsz.Add(self.tcName)
|
||||
self.tcName.SetToolTip("Enter a unique name for this heater.")
|
||||
self.tcName = wx.TextCtrl(self, wx.ID_ANY, name)
|
||||
self.tcName.SetFont(font)
|
||||
if not name:
|
||||
self.tcName.SetBackgroundColour("pink")
|
||||
self.tcName.Bind(wx.EVT_TEXT, self.onNameEntry)
|
||||
lsz.Add(self.tcName)
|
||||
self.tcName.SetToolTip("Enter a unique name for this heater.")
|
||||
|
||||
gsz.Add(lsz, pos = (1, 1))
|
||||
gsz.Add(lsz, pos=(1, 1))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Pin:", size = (80, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Pin:", size=(80, -1), style=wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
self.chPin = wx.Choice(self, wx.ID_ANY, choices = pins)
|
||||
self.chPin.SetFont(font)
|
||||
self.chPin.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
i = self.chPin.FindString(pin)
|
||||
if i == wx.NOT_FOUND:
|
||||
self.chPin.SetSelection(0)
|
||||
else:
|
||||
self.chPin.SetSelection(i)
|
||||
lsz.Add(self.chPin)
|
||||
self.chPin.SetToolTip("Choose a pin for this heater.")
|
||||
self.chPin = wx.Choice(self, wx.ID_ANY, choices=pins)
|
||||
self.chPin.SetFont(font)
|
||||
self.chPin.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
i = self.chPin.FindString(pin)
|
||||
if i == wx.NOT_FOUND:
|
||||
self.chPin.SetSelection(0)
|
||||
else:
|
||||
self.chPin.SetSelection(i)
|
||||
lsz.Add(self.chPin)
|
||||
self.chPin.SetToolTip("Choose a pin for this heater.")
|
||||
|
||||
gsz.Add(lsz, pos = (3, 1))
|
||||
gsz.Add(lsz, pos=(3, 1))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Max PWM:", size = (80, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Max PWM:", size=(80, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
self.tcMaxPWM = wx.TextCtrl(self, wx.ID_ANY, max_pwm)
|
||||
self.tcMaxPWM.SetFont(font)
|
||||
self.tcMaxPWM.Bind(wx.EVT_TEXT, self.onMaxPWM)
|
||||
lsz.Add(self.tcMaxPWM)
|
||||
self.tcMaxPWM.SetToolTip("Enter max. PWM value in [%]. Typically \n"
|
||||
"between 40 and 100. Standard is 100.\n"
|
||||
"Valid values 1 to 100.")
|
||||
self.tcMaxPWM = wx.TextCtrl(self, wx.ID_ANY, max_pwm)
|
||||
self.tcMaxPWM.SetFont(font)
|
||||
self.tcMaxPWM.Bind(wx.EVT_TEXT, self.onMaxPWM)
|
||||
lsz.Add(self.tcMaxPWM)
|
||||
self.tcMaxPWM.SetToolTip(
|
||||
"Enter max. PWM value in [%]. Typically \n"
|
||||
"between 40 and 100. Standard is 100.\n"
|
||||
"Valid values 1 to 100."
|
||||
)
|
||||
|
||||
gsz.Add(lsz, pos = (5, 1))
|
||||
gsz.Add(lsz, pos=(5, 1))
|
||||
|
||||
self.cbInv = wx.CheckBox(self, wx.ID_ANY, "Invert")
|
||||
self.cbInv.SetFont(font)
|
||||
self.cbInv.SetValue(int(invert) != 0)
|
||||
self.cbInv.SetToolTip("Invert the pin signal.")
|
||||
self.cbInv = wx.CheckBox(self, wx.ID_ANY, "Invert")
|
||||
self.cbInv.SetFont(font)
|
||||
self.cbInv.SetValue(int(invert) != 0)
|
||||
self.cbInv.SetToolTip("Invert the pin signal.")
|
||||
|
||||
gsz.Add(self.cbInv, pos = (3, 3))
|
||||
gsz.Add(self.cbInv, pos=(3, 3))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "PWM:", size = (60, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "PWM:", size=(60, -1), style=wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
self.tcPwm = wx.TextCtrl(self, wx.ID_ANY, pwm, size=(60, -1))
|
||||
self.tcPwm.SetFont(font)
|
||||
self.tcPwm.Bind(wx.EVT_TEXT, self.onPWM)
|
||||
lsz.Add(self.tcPwm)
|
||||
self.tcPwm.SetToolTip("Use Pulse Width Modulation. "
|
||||
"Hardware PWM if available or "
|
||||
"Software PWM. When FORCE_SOFTWARE_PWM "
|
||||
"is set, always software PWM for 1 and "
|
||||
"hardware PWM for >= 2.")
|
||||
self.tcPwm = wx.TextCtrl(self, wx.ID_ANY, pwm, size=(60, -1))
|
||||
self.tcPwm.SetFont(font)
|
||||
self.tcPwm.Bind(wx.EVT_TEXT, self.onPWM)
|
||||
lsz.Add(self.tcPwm)
|
||||
self.tcPwm.SetToolTip(
|
||||
"Use Pulse Width Modulation. "
|
||||
"Hardware PWM if available or "
|
||||
"Software PWM. When FORCE_SOFTWARE_PWM "
|
||||
"is set, always software PWM for 1 and "
|
||||
"hardware PWM for >= 2."
|
||||
)
|
||||
|
||||
gsz.Add((50, 15), pos = (1, 2))
|
||||
gsz.Add(lsz, pos = (1, 3))
|
||||
gsz.Add((20, 20), pos = (4, 4))
|
||||
gsz.Add((50, 15), pos=(1, 2))
|
||||
gsz.Add(lsz, pos=(1, 3))
|
||||
gsz.Add((20, 20), pos=(4, 4))
|
||||
|
||||
sz.Add(gsz)
|
||||
sz.Add((30, 30))
|
||||
sz.Add(gsz)
|
||||
sz.Add((30, 30))
|
||||
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.bSave = wx.Button(self, wx.ID_ANY, "Save", size = BSIZESMALL)
|
||||
self.bSave.SetFont(font)
|
||||
self.bSave.Bind(wx.EVT_BUTTON, self.onSave)
|
||||
bsz.Add(self.bSave)
|
||||
self.bSave = wx.Button(self, wx.ID_ANY, "Save", size=BSIZESMALL)
|
||||
self.bSave.SetFont(font)
|
||||
self.bSave.Bind(wx.EVT_BUTTON, self.onSave)
|
||||
bsz.Add(self.bSave)
|
||||
|
||||
bsz.Add(30, 100)
|
||||
bsz.Add(30, 100)
|
||||
|
||||
self.bCancel = wx.Button(self, wx.ID_ANY, "Cancel", size = BSIZESMALL)
|
||||
self.bCancel.SetFont(font)
|
||||
self.bCancel.Bind(wx.EVT_BUTTON, self.onCancel)
|
||||
bsz.Add(self.bCancel)
|
||||
self.bCancel = wx.Button(self, wx.ID_ANY, "Cancel", size=BSIZESMALL)
|
||||
self.bCancel.SetFont(font)
|
||||
self.bCancel.Bind(wx.EVT_BUTTON, self.onCancel)
|
||||
bsz.Add(self.bCancel)
|
||||
|
||||
sz.Add(bsz, flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
self.SetSizer(sz)
|
||||
sz.Add(bsz, flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
self.SetSizer(sz)
|
||||
|
||||
self.checkDlgValidity()
|
||||
self.Fit()
|
||||
self.checkDlgValidity()
|
||||
self.Fit()
|
||||
|
||||
def onNameEntry(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.nameValid = False
|
||||
else:
|
||||
if w in self.names:
|
||||
self.nameValid = False
|
||||
else:
|
||||
self.nameValid = True
|
||||
def onNameEntry(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.nameValid = False
|
||||
else:
|
||||
if w in self.names:
|
||||
self.nameValid = False
|
||||
else:
|
||||
self.nameValid = True
|
||||
|
||||
if self.nameValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
if self.nameValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
|
||||
self.checkDlgValidity()
|
||||
evt.Skip()
|
||||
self.checkDlgValidity()
|
||||
evt.Skip()
|
||||
|
||||
def onChoice(self, evt):
|
||||
pass
|
||||
def onChoice(self, evt):
|
||||
pass
|
||||
|
||||
def onMaxPWM(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.maxPWMValid = False
|
||||
else:
|
||||
if int(w) > 0 and int(w) <= 100:
|
||||
self.maxPWMValid = True
|
||||
else:
|
||||
self.maxPWMValid = False
|
||||
def onMaxPWM(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.maxPWMValid = False
|
||||
else:
|
||||
if int(w) > 0 and int(w) <= 100:
|
||||
self.maxPWMValid = True
|
||||
else:
|
||||
self.maxPWMValid = False
|
||||
|
||||
if self.maxPWMValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
if self.maxPWMValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
|
||||
self.checkDlgValidity()
|
||||
if evt is not None:
|
||||
evt.Skip()
|
||||
self.checkDlgValidity()
|
||||
if evt is not None:
|
||||
evt.Skip()
|
||||
|
||||
def onPWM(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.pwmValid = False
|
||||
else:
|
||||
if int(w) >= 0:
|
||||
self.pwmValid = True
|
||||
else:
|
||||
self.pwmValid = False
|
||||
def onPWM(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
self.pwmValid = False
|
||||
else:
|
||||
if int(w) >= 0:
|
||||
self.pwmValid = True
|
||||
else:
|
||||
self.pwmValid = False
|
||||
|
||||
if self.pwmValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
if self.pwmValid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
|
||||
self.checkDlgValidity()
|
||||
if evt is not None:
|
||||
evt.Skip()
|
||||
self.checkDlgValidity()
|
||||
if evt is not None:
|
||||
evt.Skip()
|
||||
|
||||
def checkDlgValidity(self):
|
||||
if (self.nameValid and self.maxPWMValid and self.pwmValid):
|
||||
self.bSave.Enable(True)
|
||||
else:
|
||||
self.bSave.Enable(False)
|
||||
def checkDlgValidity(self):
|
||||
if self.nameValid and self.maxPWMValid and self.pwmValid:
|
||||
self.bSave.Enable(True)
|
||||
else:
|
||||
self.bSave.Enable(False)
|
||||
|
||||
def getValues(self):
|
||||
nm = self.tcName.GetValue()
|
||||
pin = self.choices[self.chPin.GetSelection()]
|
||||
def getValues(self):
|
||||
nm = self.tcName.GetValue()
|
||||
pin = self.choices[self.chPin.GetSelection()]
|
||||
|
||||
if self.cbInv.IsChecked():
|
||||
invert = "1"
|
||||
else:
|
||||
invert = "0"
|
||||
if self.cbInv.IsChecked():
|
||||
invert = "1"
|
||||
else:
|
||||
invert = "0"
|
||||
|
||||
pwm = self.tcPwm.GetValue()
|
||||
pwm = self.tcPwm.GetValue()
|
||||
|
||||
max_pwm = self.tcMaxPWM.GetValue()
|
||||
max_pwm = self.tcMaxPWM.GetValue()
|
||||
|
||||
return (nm, pin, invert, pwm, max_pwm)
|
||||
return (nm, pin, invert, pwm, max_pwm)
|
||||
|
||||
def onSave(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
def onSave(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
def onCancel(self, evt):
|
||||
self.EndModal(wx.ID_CANCEL)
|
||||
def onCancel(self, evt):
|
||||
self.EndModal(wx.ID_CANCEL)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,488 +4,534 @@ import os
|
|||
import re
|
||||
|
||||
from sys import platform
|
||||
from configtool.data import (defineValueFormat,
|
||||
defineBoolFormat, defineHeaterFormat,
|
||||
reHelpTextStart, reHelpTextEnd,
|
||||
reStartSensors, reEndSensors, reStartHeaters,
|
||||
reEndHeaters, reCandHeatPins, reCandThermPins,
|
||||
reCandProcessors, reCandCPUClocks, reFloatAttr,
|
||||
reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reDefQSm2, reDefBool, reDefBoolBL, reDefHT,
|
||||
reDefTS, reDefTT, reSensor, reHeater3, reHeater4,
|
||||
reHeater5, reTempTable4, reTempTable7)
|
||||
from configtool.data import (
|
||||
defineValueFormat,
|
||||
defineBoolFormat,
|
||||
defineHeaterFormat,
|
||||
reHelpTextStart,
|
||||
reHelpTextEnd,
|
||||
reStartSensors,
|
||||
reEndSensors,
|
||||
reStartHeaters,
|
||||
reEndHeaters,
|
||||
reCandHeatPins,
|
||||
reCandThermPins,
|
||||
reCandProcessors,
|
||||
reCandCPUClocks,
|
||||
reFloatAttr,
|
||||
reDefine,
|
||||
reDefineBL,
|
||||
reDefQS,
|
||||
reDefQSm,
|
||||
reDefQSm2,
|
||||
reDefBool,
|
||||
reDefBoolBL,
|
||||
reDefHT,
|
||||
reDefTS,
|
||||
reDefTT,
|
||||
reSensor,
|
||||
reHeater3,
|
||||
reHeater4,
|
||||
reHeater5,
|
||||
reTempTable4,
|
||||
reTempTable7,
|
||||
)
|
||||
|
||||
|
||||
class Board:
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.configFile = None
|
||||
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.configFile = None
|
||||
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
||||
|
||||
self.cfgValues = {}
|
||||
self.heaters = []
|
||||
self.sensors = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
self.cfgValues = {}
|
||||
self.heaters = []
|
||||
self.sensors = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
|
||||
def getValues(self):
|
||||
vars = [("sensor." + x[0], x[1:]) for x in self.sensors]
|
||||
vars += [("heater." + x[0], x[1:]) for x in self.heaters]
|
||||
vars += [(x, self.cfgValues[x]) for x in self.cfgValues]
|
||||
return dict(vars)
|
||||
def getValues(self):
|
||||
vars = [("sensor." + x[0], x[1:]) for x in self.sensors]
|
||||
vars += [("heater." + x[0], x[1:]) for x in self.heaters]
|
||||
vars += [(x, self.cfgValues[x]) for x in self.cfgValues]
|
||||
return dict(vars)
|
||||
|
||||
def getCPUInfo(self):
|
||||
vF_CPU = None
|
||||
if 'F_CPU' in self.cfgValues.keys():
|
||||
vF_CPU = self.cfgValues['F_CPU'][0]
|
||||
def getCPUInfo(self):
|
||||
vF_CPU = None
|
||||
if "F_CPU" in self.cfgValues.keys():
|
||||
vF_CPU = self.cfgValues["F_CPU"][0]
|
||||
|
||||
vCPU = None
|
||||
if 'CPU' in self.cfgValues.keys():
|
||||
vCPU = self.cfgValues['CPU'][0]
|
||||
vCPU = None
|
||||
if "CPU" in self.cfgValues.keys():
|
||||
vCPU = self.cfgValues["CPU"][0]
|
||||
|
||||
return vF_CPU, vCPU
|
||||
return vF_CPU, vCPU
|
||||
|
||||
def hasData(self):
|
||||
return (self.configFile != None)
|
||||
def hasData(self):
|
||||
return self.configFile != None
|
||||
|
||||
def getFileName(self):
|
||||
return self.configFile
|
||||
def getFileName(self):
|
||||
return self.configFile
|
||||
|
||||
def loadConfigFile(self, fn):
|
||||
cfgFn = os.path.join(self.cfgDir, "board.generic.h")
|
||||
try:
|
||||
self.cfgBuffer = list(open(cfgFn))
|
||||
except:
|
||||
return False, cfgFn
|
||||
def loadConfigFile(self, fn):
|
||||
cfgFn = os.path.join(self.cfgDir, "board.generic.h")
|
||||
try:
|
||||
self.cfgBuffer = list(open(cfgFn))
|
||||
except:
|
||||
return False, cfgFn
|
||||
|
||||
try:
|
||||
self.userBuffer = list(open(fn))
|
||||
except:
|
||||
return False, fn
|
||||
try:
|
||||
self.userBuffer = list(open(fn))
|
||||
except:
|
||||
return False, fn
|
||||
|
||||
self.configFile = fn
|
||||
self.configFile = fn
|
||||
|
||||
self.sensors = []
|
||||
self.heaters = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
self.candProcessors = []
|
||||
self.candClocks = []
|
||||
self.tempTables = {}
|
||||
gatheringHelpText = False
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
self.sensors = []
|
||||
self.heaters = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
self.candProcessors = []
|
||||
self.candClocks = []
|
||||
self.tempTables = {}
|
||||
gatheringHelpText = False
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
|
||||
self.cfgValues = {}
|
||||
self.cfgNames = []
|
||||
self.helpText = {}
|
||||
self.cfgValues = {}
|
||||
self.cfgNames = []
|
||||
self.helpText = {}
|
||||
|
||||
prevLines = ""
|
||||
for ln in self.cfgBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
helpTextString = helpTextString.strip()
|
||||
# Keep paragraphs with double-newline.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n")
|
||||
# Keep indented lines, typically a list.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n ")
|
||||
helpTextString = helpTextString.replace("\n ", "\n\n ")
|
||||
# Remove all other newlines and indents.
|
||||
helpTextString = helpTextString.replace("\n ", " ")
|
||||
hk = helpKey.split()
|
||||
for k in hk:
|
||||
self.helpText[k] = helpTextString
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
continue
|
||||
else:
|
||||
helpTextString += ln
|
||||
continue
|
||||
|
||||
m = reHelpTextStart.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
gatheringHelpText = True
|
||||
helpKey = t[0]
|
||||
continue
|
||||
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
for ln in self.cfgBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
helpTextString = helpTextString.strip()
|
||||
# Keep paragraphs with double-newline.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n")
|
||||
# Keep indented lines, typically a list.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n ")
|
||||
helpTextString = helpTextString.replace("\n ", "\n\n ")
|
||||
# Remove all other newlines and indents.
|
||||
helpTextString = helpTextString.replace("\n ", " ")
|
||||
hk = helpKey.split()
|
||||
for k in hk:
|
||||
self.helpText[k] = helpTextString
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
continue
|
||||
else:
|
||||
helpTextString += ln
|
||||
continue
|
||||
|
||||
self.parseDefineName(ln)
|
||||
self.parseDefineValue(ln)
|
||||
m = reHelpTextStart.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
gatheringHelpText = True
|
||||
helpKey = t[0]
|
||||
continue
|
||||
|
||||
# Set all boolean generic configuration items to False, so items not yet
|
||||
# existing in the user configuration default to disabled.
|
||||
#
|
||||
# An alternative would be to allow both, enabled and disabled booleans
|
||||
# in board.generic.h, which then allows to set an appropriate default for
|
||||
# each #define. This was tried but conflicted with config file writing code
|
||||
# below (disabled #defines were reset to the default, even when set
|
||||
# differently in the GUI), so this would need adjustment, too.
|
||||
for k in self.cfgValues.keys():
|
||||
if isinstance(self.cfgValues[k], bool):
|
||||
self.cfgValues[k] = False
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
# Read the user configuration. This usually overwrites all of the items
|
||||
# read above, but not those missing in the user configuration, e.g.
|
||||
# when reading an older config.
|
||||
gatheringHelpText = False
|
||||
prevLines = ""
|
||||
for ln in self.userBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
continue
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
|
||||
if reHelpTextStart.match(ln):
|
||||
gatheringHelpText = True
|
||||
continue
|
||||
self.parseDefineName(ln)
|
||||
self.parseDefineValue(ln)
|
||||
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
# Set all boolean generic configuration items to False, so items not yet
|
||||
# existing in the user configuration default to disabled.
|
||||
#
|
||||
# An alternative would be to allow both, enabled and disabled booleans
|
||||
# in board.generic.h, which then allows to set an appropriate default for
|
||||
# each #define. This was tried but conflicted with config file writing code
|
||||
# below (disabled #defines were reset to the default, even when set
|
||||
# differently in the GUI), so this would need adjustment, too.
|
||||
for k in self.cfgValues.keys():
|
||||
if isinstance(self.cfgValues[k], bool):
|
||||
self.cfgValues[k] = False
|
||||
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
# Read the user configuration. This usually overwrites all of the items
|
||||
# read above, but not those missing in the user configuration, e.g.
|
||||
# when reading an older config.
|
||||
gatheringHelpText = False
|
||||
prevLines = ""
|
||||
for ln in self.userBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
continue
|
||||
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
if reHelpTextStart.match(ln):
|
||||
gatheringHelpText = True
|
||||
continue
|
||||
|
||||
if self.parseDefineValue(ln):
|
||||
continue
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
m = reDefTS.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
s = self.parseSensor(t[0])
|
||||
if s:
|
||||
self.sensors.append(s)
|
||||
continue
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
|
||||
m = reDefHT.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
s = self.parseHeater(t[0])
|
||||
if s:
|
||||
self.heaters.append(s)
|
||||
continue
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
|
||||
# Parsing done. All parsed stuff is now in these arrays and dicts.
|
||||
if self.settings.verbose >= 2:
|
||||
print(self.sensors)
|
||||
print(self.heaters)
|
||||
print(self.candHeatPins)
|
||||
print(self.candThermPins)
|
||||
print(self.candProcessors)
|
||||
print(self.candClocks)
|
||||
print(self.tempTables)
|
||||
print(self.cfgValues) # #defines with a value.
|
||||
print(self.cfgNames) # Names found in the generic file.
|
||||
if self.settings.verbose >= 3:
|
||||
print(self.helpText)
|
||||
if self.parseDefineValue(ln):
|
||||
continue
|
||||
|
||||
for k in range(len(self.sensors)):
|
||||
tn = self.sensors[k][0].upper()
|
||||
if tn in self.tempTables.keys():
|
||||
self.sensors[k][3] = self.tempTables[tn]
|
||||
else:
|
||||
self.sensors[k][3] = None
|
||||
m = reDefTS.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
s = self.parseSensor(t[0])
|
||||
if s:
|
||||
self.sensors.append(s)
|
||||
continue
|
||||
|
||||
return True, None
|
||||
m = reDefHT.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
s = self.parseHeater(t[0])
|
||||
if s:
|
||||
self.heaters.append(s)
|
||||
continue
|
||||
|
||||
def parseDefineName(self, ln):
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.cfgNames.append(t[0])
|
||||
return True
|
||||
# Parsing done. All parsed stuff is now in these arrays and dicts.
|
||||
if self.settings.verbose >= 2:
|
||||
print(self.sensors)
|
||||
print(self.heaters)
|
||||
print(self.candHeatPins)
|
||||
print(self.candThermPins)
|
||||
print(self.candProcessors)
|
||||
print(self.candClocks)
|
||||
print(self.tempTables)
|
||||
print(self.cfgValues) # #defines with a value.
|
||||
print(self.cfgNames) # Names found in the generic file.
|
||||
if self.settings.verbose >= 3:
|
||||
print(self.helpText)
|
||||
|
||||
return False
|
||||
|
||||
def parseDefineValue(self, ln):
|
||||
m = reDefQS.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
m = reDefQSm.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
tt = re.findall(reDefQSm2, t[1])
|
||||
if len(tt) == 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt[0], True
|
||||
return True
|
||||
elif len(tt) > 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt, True
|
||||
return True
|
||||
|
||||
m = reDefine.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and (t[0] in self.cfgNames):
|
||||
if reDefineBL.search(ln):
|
||||
self.cfgValues[t[0]] = t[1], True
|
||||
else:
|
||||
self.cfgValues[t[0]] = t[1], False
|
||||
return True
|
||||
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
# Accept booleans, but not those for which a value exists already.
|
||||
# Booleans already existing as values are most likely misconfigured
|
||||
# manual edits (or result of a bug).
|
||||
if len(t) == 1 and t[0] in self.cfgNames \
|
||||
and not (t[0] in self.cfgValues \
|
||||
and isinstance(self.cfgValues[t[0]], tuple)):
|
||||
if reDefBoolBL.search(ln):
|
||||
self.cfgValues[t[0]] = True
|
||||
else:
|
||||
self.cfgValues[t[0]] = False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def parseCandidateValues(self, ln):
|
||||
m = reCandThermPins.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candThermPins.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandHeatPins.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candHeatPins.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandProcessors.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candProcessors.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandCPUClocks.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candClocks.append(t[0])
|
||||
return True
|
||||
|
||||
m = reDefTT.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
s = self.parseTempTable(t[1])
|
||||
if s:
|
||||
self.tempTables[t[0]] = s
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def parseSensor(self, s):
|
||||
m = reSensor.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
return list(t)
|
||||
return None
|
||||
|
||||
def parseHeater(self, s):
|
||||
m = reHeater5.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 5:
|
||||
return list(t)
|
||||
# reHeater4 deprecated, for compatibility with old config files only.
|
||||
m = reHeater4.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
t = list(t)
|
||||
t.insert(5, '100')
|
||||
return t
|
||||
# reHeater3 deprecated, for compatibility with old config files only.
|
||||
m = reHeater3.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 3:
|
||||
t = list(t)
|
||||
t.insert(2, '0')
|
||||
t.insert(5, '100')
|
||||
return t
|
||||
# End of deprecated part.
|
||||
return None
|
||||
|
||||
def parseTempTable(self, s):
|
||||
m = reTempTable4.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
return list(t)
|
||||
m = reTempTable7.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 7:
|
||||
return list(t)
|
||||
return None
|
||||
|
||||
def saveConfigFile(self, path, values):
|
||||
if not values:
|
||||
values = self.cfgValues
|
||||
|
||||
if self.settings.verbose >= 1:
|
||||
print("Saving board: %s." % path)
|
||||
if self.settings.verbose >= 2:
|
||||
print(values)
|
||||
|
||||
fp = file(path, 'w')
|
||||
self.configFile = path
|
||||
|
||||
skipToSensorEnd = False
|
||||
skipToHeaterEnd = False
|
||||
candThermPinsWritten = False
|
||||
candHeatPinsWritten = False
|
||||
candProcessorsWritten = False
|
||||
candCPUClocksWritten = False
|
||||
|
||||
for ln in self.cfgBuffer:
|
||||
m = reStartSensors.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
fp.write("// name type pin "
|
||||
"additional\n");
|
||||
ttString = "\n"
|
||||
ttString += "// Beta algorithm r0 beta r2 vadc\n"
|
||||
ttString += "// Steinhart-Hart rp t0 r0 t1 "
|
||||
ttString += "r1 t2 r2\n"
|
||||
for s in self.sensors:
|
||||
sstr = "%-10s%-15s%-7s" % ((s[0] + ","), (s[1] + ","), (s[2] + ","))
|
||||
if s[3] is None:
|
||||
sstr += "0"
|
||||
else:
|
||||
sstr += "THERMISTOR_%s" % s[0].upper()
|
||||
tt = s[3]
|
||||
if len(tt) == 4:
|
||||
ttString += "//TEMP_TABLE %-8s (%-8s%-6s%-6s%s)\n" % \
|
||||
(s[0].upper(), (tt[0] + ","), (tt[1] + ","),
|
||||
(tt[2] + ","), tt[3])
|
||||
for k in range(len(self.sensors)):
|
||||
tn = self.sensors[k][0].upper()
|
||||
if tn in self.tempTables.keys():
|
||||
self.sensors[k][3] = self.tempTables[tn]
|
||||
else:
|
||||
ttString += "//TEMP_TABLE %-8s (%-8s%-6s%-8s%-6s%-8s%-6s%s)\n" % \
|
||||
(s[0].upper(), (tt[0] + ","), (tt[1] + ","),
|
||||
(tt[2] + ","), (tt[3] + ","), (tt[4] + ","),
|
||||
(tt[5] + ","), tt[6])
|
||||
fp.write("DEFINE_TEMP_SENSOR(%s)\n" % sstr)
|
||||
fp.write(ttString)
|
||||
skipToSensorEnd = True
|
||||
continue
|
||||
self.sensors[k][3] = None
|
||||
|
||||
if skipToSensorEnd:
|
||||
m = reEndSensors.match(ln)
|
||||
return True, None
|
||||
|
||||
def parseDefineName(self, ln):
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToSensorEnd = False
|
||||
continue
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.cfgNames.append(t[0])
|
||||
return True
|
||||
|
||||
m = reStartHeaters.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
fp.write("// name pin invert pwm max_pwm\n")
|
||||
for s in self.heaters:
|
||||
sstr = "%-10s%-9s%-8s%-7s%s" % ((s[0] + ","), (s[1] + ","),
|
||||
(s[2] + ","), s[3] + ",", s[4])
|
||||
fp.write("DEFINE_HEATER(%s)\n" % sstr)
|
||||
fp.write("\n")
|
||||
for s in self.heaters:
|
||||
fp.write(defineHeaterFormat % (s[0].upper(), s[0]))
|
||||
skipToHeaterEnd = True
|
||||
continue
|
||||
return False
|
||||
|
||||
if skipToHeaterEnd:
|
||||
m = reEndHeaters.match(ln)
|
||||
def parseDefineValue(self, ln):
|
||||
m = reDefQS.search(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToHeaterEnd = False
|
||||
continue
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
m = reDefQSm.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
tt = re.findall(reDefQSm2, t[1])
|
||||
if len(tt) == 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt[0], True
|
||||
return True
|
||||
elif len(tt) > 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt, True
|
||||
return True
|
||||
|
||||
if reCandThermPins.match(ln):
|
||||
if not candThermPinsWritten:
|
||||
for pin in self.candThermPins:
|
||||
fp.write("//#define TEMP_SENSOR_PIN " + pin + "\n")
|
||||
candThermPinsWritten = True
|
||||
continue
|
||||
m = reDefine.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and (t[0] in self.cfgNames):
|
||||
if reDefineBL.search(ln):
|
||||
self.cfgValues[t[0]] = t[1], True
|
||||
else:
|
||||
self.cfgValues[t[0]] = t[1], False
|
||||
return True
|
||||
|
||||
if reCandHeatPins.match(ln):
|
||||
if not candHeatPinsWritten:
|
||||
for pin in self.candHeatPins:
|
||||
fp.write("//#define HEATER_PIN " + pin + "\n")
|
||||
candHeatPinsWritten = True
|
||||
continue
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
# Accept booleans, but not those for which a value exists already.
|
||||
# Booleans already existing as values are most likely misconfigured
|
||||
# manual edits (or result of a bug).
|
||||
if (
|
||||
len(t) == 1
|
||||
and t[0] in self.cfgNames
|
||||
and not (
|
||||
t[0] in self.cfgValues and isinstance(self.cfgValues[t[0]], tuple)
|
||||
)
|
||||
):
|
||||
if reDefBoolBL.search(ln):
|
||||
self.cfgValues[t[0]] = True
|
||||
else:
|
||||
self.cfgValues[t[0]] = False
|
||||
return True
|
||||
|
||||
if reCandProcessors.match(ln):
|
||||
if not candProcessorsWritten:
|
||||
for pin in self.candProcessors:
|
||||
fp.write("//#define CPU_TYPE " + pin + "\n")
|
||||
candProcessorsWritten = True
|
||||
continue
|
||||
return False
|
||||
|
||||
if reCandCPUClocks.match(ln):
|
||||
if not candCPUClocksWritten:
|
||||
for pin in self.candClocks:
|
||||
fp.write("//#define F_CPU_OPT " + pin + "\n")
|
||||
candCPUClocksWritten = True
|
||||
continue
|
||||
def parseCandidateValues(self, ln):
|
||||
m = reCandThermPins.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candThermPins.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandHeatPins.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candHeatPins.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandProcessors.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candProcessors.append(t[0])
|
||||
return True
|
||||
|
||||
m = reCandCPUClocks.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candClocks.append(t[0])
|
||||
return True
|
||||
|
||||
m = reDefTT.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
s = self.parseTempTable(t[1])
|
||||
if s:
|
||||
self.tempTables[t[0]] = s
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def parseSensor(self, s):
|
||||
m = reSensor.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
return list(t)
|
||||
return None
|
||||
|
||||
def parseHeater(self, s):
|
||||
m = reHeater5.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 5:
|
||||
return list(t)
|
||||
# reHeater4 deprecated, for compatibility with old config files only.
|
||||
m = reHeater4.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
t = list(t)
|
||||
t.insert(5, "100")
|
||||
return t
|
||||
# reHeater3 deprecated, for compatibility with old config files only.
|
||||
m = reHeater3.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 3:
|
||||
t = list(t)
|
||||
t.insert(2, "0")
|
||||
t.insert(5, "100")
|
||||
return t
|
||||
# End of deprecated part.
|
||||
return None
|
||||
|
||||
def parseTempTable(self, s):
|
||||
m = reTempTable4.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 4:
|
||||
return list(t)
|
||||
m = reTempTable7.search(s)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 7:
|
||||
return list(t)
|
||||
return None
|
||||
|
||||
def saveConfigFile(self, path, values):
|
||||
if not values:
|
||||
values = self.cfgValues
|
||||
|
||||
if self.settings.verbose >= 1:
|
||||
print("Saving board: %s." % path)
|
||||
if self.settings.verbose >= 2:
|
||||
print(values)
|
||||
|
||||
fp = file(path, "w")
|
||||
self.configFile = path
|
||||
|
||||
skipToSensorEnd = False
|
||||
skipToHeaterEnd = False
|
||||
candThermPinsWritten = False
|
||||
candHeatPinsWritten = False
|
||||
candProcessorsWritten = False
|
||||
candCPUClocksWritten = False
|
||||
|
||||
for ln in self.cfgBuffer:
|
||||
m = reStartSensors.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
fp.write(
|
||||
"// name type pin " "additional\n"
|
||||
)
|
||||
ttString = "\n"
|
||||
ttString += "// Beta algorithm r0 beta r2 vadc\n"
|
||||
ttString += "// Steinhart-Hart rp t0 r0 t1 "
|
||||
ttString += "r1 t2 r2\n"
|
||||
for s in self.sensors:
|
||||
sstr = "%-10s%-15s%-7s" % ((s[0] + ","), (s[1] + ","), (s[2] + ","))
|
||||
if s[3] is None:
|
||||
sstr += "0"
|
||||
else:
|
||||
sstr += "THERMISTOR_%s" % s[0].upper()
|
||||
tt = s[3]
|
||||
if len(tt) == 4:
|
||||
ttString += "//TEMP_TABLE %-8s (%-8s%-6s%-6s%s)\n" % (
|
||||
s[0].upper(),
|
||||
(tt[0] + ","),
|
||||
(tt[1] + ","),
|
||||
(tt[2] + ","),
|
||||
tt[3],
|
||||
)
|
||||
else:
|
||||
ttString += (
|
||||
"//TEMP_TABLE %-8s (%-8s%-6s%-8s%-6s%-8s%-6s%s)\n"
|
||||
% (
|
||||
s[0].upper(),
|
||||
(tt[0] + ","),
|
||||
(tt[1] + ","),
|
||||
(tt[2] + ","),
|
||||
(tt[3] + ","),
|
||||
(tt[4] + ","),
|
||||
(tt[5] + ","),
|
||||
tt[6],
|
||||
)
|
||||
)
|
||||
fp.write("DEFINE_TEMP_SENSOR(%s)\n" % sstr)
|
||||
fp.write(ttString)
|
||||
skipToSensorEnd = True
|
||||
continue
|
||||
|
||||
if skipToSensorEnd:
|
||||
m = reEndSensors.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToSensorEnd = False
|
||||
continue
|
||||
|
||||
m = reStartHeaters.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
fp.write("// name pin invert pwm max_pwm\n")
|
||||
for s in self.heaters:
|
||||
sstr = "%-10s%-9s%-8s%-7s%s" % (
|
||||
(s[0] + ","),
|
||||
(s[1] + ","),
|
||||
(s[2] + ","),
|
||||
s[3] + ",",
|
||||
s[4],
|
||||
)
|
||||
fp.write("DEFINE_HEATER(%s)\n" % sstr)
|
||||
fp.write("\n")
|
||||
for s in self.heaters:
|
||||
fp.write(defineHeaterFormat % (s[0].upper(), s[0]))
|
||||
skipToHeaterEnd = True
|
||||
continue
|
||||
|
||||
if skipToHeaterEnd:
|
||||
m = reEndHeaters.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToHeaterEnd = False
|
||||
continue
|
||||
|
||||
if reCandThermPins.match(ln):
|
||||
if not candThermPinsWritten:
|
||||
for pin in self.candThermPins:
|
||||
fp.write("//#define TEMP_SENSOR_PIN " + pin + "\n")
|
||||
candThermPinsWritten = True
|
||||
continue
|
||||
|
||||
if reCandHeatPins.match(ln):
|
||||
if not candHeatPinsWritten:
|
||||
for pin in self.candHeatPins:
|
||||
fp.write("//#define HEATER_PIN " + pin + "\n")
|
||||
candHeatPinsWritten = True
|
||||
continue
|
||||
|
||||
if reCandProcessors.match(ln):
|
||||
if not candProcessorsWritten:
|
||||
for pin in self.candProcessors:
|
||||
fp.write("//#define CPU_TYPE " + pin + "\n")
|
||||
candProcessorsWritten = True
|
||||
continue
|
||||
|
||||
if reCandCPUClocks.match(ln):
|
||||
if not candCPUClocksWritten:
|
||||
for pin in self.candClocks:
|
||||
fp.write("//#define F_CPU_OPT " + pin + "\n")
|
||||
candCPUClocksWritten = True
|
||||
continue
|
||||
|
||||
m = reDefine.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v[1] == False:
|
||||
fp.write("//")
|
||||
fp.write(defineValueFormat % (t[0], v[0]))
|
||||
else:
|
||||
if t[0] == "RX_ENABLE_PIN" or t[0] == "TX_ENABLE_PIN":
|
||||
# Known to be absent in the GUI, also won't be added anytime soon.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Value key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
m = reDefBoolBL.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v == "" or v == False:
|
||||
fp.write("//")
|
||||
fp.write(defineBoolFormat % t[0])
|
||||
else:
|
||||
if t[0] == "MOTHERBOARD":
|
||||
# Known to be absent in the GUI, also won't be added anytime soon.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Boolean key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
m = reDefine.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v[1] == False:
|
||||
fp.write("//")
|
||||
fp.write(defineValueFormat % (t[0], v[0]))
|
||||
else:
|
||||
if t[0] == 'RX_ENABLE_PIN' or t[0] == 'TX_ENABLE_PIN':
|
||||
# Known to be absent in the GUI, also won't be added anytime soon.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Value key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
fp.close()
|
||||
|
||||
m = reDefBoolBL.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v == "" or v == False:
|
||||
fp.write("//")
|
||||
fp.write(defineBoolFormat % t[0])
|
||||
else:
|
||||
if t[0] == 'MOTHERBOARD':
|
||||
# Known to be absent in the GUI, also won't be added anytime soon.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Boolean key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
fp.write(ln)
|
||||
|
||||
fp.close()
|
||||
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,20 +1,40 @@
|
|||
|
||||
import os
|
||||
import wx
|
||||
import re
|
||||
|
||||
from sys import platform
|
||||
from configtool.decoration import Decoration
|
||||
from configtool.data import (defineValueFormat,
|
||||
defineBoolFormat, defineHeaterFormat,
|
||||
reHelpTextStart, reHelpTextEnd,
|
||||
reStartSensors, reEndSensors, reStartHeaters,
|
||||
reEndHeaters, reCandHeatPins, reCandThermPins,
|
||||
reCandProcessors, reCandCPUClocks, reFloatAttr,
|
||||
reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reDefQSm2, reDefBool, reDefBoolBL, reDefHT,
|
||||
reDefTS, reDefTT, reSensor, reHeater3, reHeater4,
|
||||
reTempTable4, reTempTable7)
|
||||
from configtool.data import (
|
||||
defineValueFormat,
|
||||
defineBoolFormat,
|
||||
defineHeaterFormat,
|
||||
reHelpTextStart,
|
||||
reHelpTextEnd,
|
||||
reStartSensors,
|
||||
reEndSensors,
|
||||
reStartHeaters,
|
||||
reEndHeaters,
|
||||
reCandHeatPins,
|
||||
reCandThermPins,
|
||||
reCandProcessors,
|
||||
reCandCPUClocks,
|
||||
reFloatAttr,
|
||||
reDefine,
|
||||
reDefineBL,
|
||||
reDefQS,
|
||||
reDefQSm,
|
||||
reDefQSm2,
|
||||
reDefBool,
|
||||
reDefBoolBL,
|
||||
reDefHT,
|
||||
reDefTS,
|
||||
reDefTT,
|
||||
reSensor,
|
||||
reHeater3,
|
||||
reHeater4,
|
||||
reTempTable4,
|
||||
reTempTable7,
|
||||
)
|
||||
from configtool.pinoutspage import PinoutsPage
|
||||
from configtool.displaypage import DisplayPage
|
||||
from configtool.sensorpage import SensorsPage
|
||||
|
|
@ -26,269 +46,302 @@ from configtool.thermistortablefile import generateTempTables
|
|||
|
||||
from configtool.board import Board
|
||||
|
||||
|
||||
class BoardPanel(wx.Panel):
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
|
||||
self.deco = Decoration()
|
||||
self.protFileLoaded = False
|
||||
self.deco = Decoration()
|
||||
self.protFileLoaded = False
|
||||
|
||||
self.settings = settings
|
||||
self.settings = settings
|
||||
|
||||
self.board = Board(self.settings)
|
||||
self.board = Board(self.settings)
|
||||
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21),
|
||||
style = wx.BK_DEFAULT)
|
||||
self.nb.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.nb.SetFont(self.settings.font)
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size=(21, 21), style=wx.BK_DEFAULT)
|
||||
self.nb.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.nb.SetFont(self.settings.font)
|
||||
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
|
||||
self.pgCpu = self.registerPage(CpuPage, "CPU")
|
||||
self.pgPins = self.registerPage(PinoutsPage, "Pinouts")
|
||||
self.pgDisplay = self.registerPage(DisplayPage, "Display")
|
||||
self.pgHeaters = self.registerPage(HeatersPage, "Heaters")
|
||||
self.pgSensors = self.registerPage(SensorsPage, "Temperature Sensors",
|
||||
heatersPage = self.pgHeaters)
|
||||
self.pgCommunications = self.registerPage(CommunicationsPage,
|
||||
"Communications")
|
||||
self.pgCpu = self.registerPage(CpuPage, "CPU")
|
||||
self.pgPins = self.registerPage(PinoutsPage, "Pinouts")
|
||||
self.pgDisplay = self.registerPage(DisplayPage, "Display")
|
||||
self.pgHeaters = self.registerPage(HeatersPage, "Heaters")
|
||||
self.pgSensors = self.registerPage(
|
||||
SensorsPage, "Temperature Sensors", heatersPage=self.pgHeaters
|
||||
)
|
||||
self.pgCommunications = self.registerPage(CommunicationsPage, "Communications")
|
||||
|
||||
sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5)
|
||||
sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5)
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.Fit()
|
||||
self.SetSizer(sz)
|
||||
self.Fit()
|
||||
|
||||
def registerPage(self, klass, label, *args, **kwargs):
|
||||
page = klass(self, self.nb, len(self.pages), *args,
|
||||
font = self.settings.font, **kwargs)
|
||||
self.nb.AddPage(page, label)
|
||||
self.pages.append(page)
|
||||
self.titles.append(label)
|
||||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
return page
|
||||
def registerPage(self, klass, label, *args, **kwargs):
|
||||
page = klass(
|
||||
self, self.nb, len(self.pages), *args, font=self.settings.font, **kwargs
|
||||
)
|
||||
self.nb.AddPage(page, label)
|
||||
self.pages.append(page)
|
||||
self.titles.append(label)
|
||||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
return page
|
||||
|
||||
def getCPUInfo(self):
|
||||
return self.board.getCPUInfo()
|
||||
def getCPUInfo(self):
|
||||
return self.board.getCPUInfo()
|
||||
|
||||
def assertModified(self, pg, flag = True):
|
||||
self.pageModified[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
def assertModified(self, pg, flag=True):
|
||||
self.pageModified[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
||||
def isModified(self):
|
||||
return (True in self.pageModified)
|
||||
def isModified(self):
|
||||
return True in self.pageModified
|
||||
|
||||
def isValid(self):
|
||||
return not (False in self.pageValid)
|
||||
def isValid(self):
|
||||
return not (False in self.pageValid)
|
||||
|
||||
def hasData(self):
|
||||
return self.board.hasData()
|
||||
def hasData(self):
|
||||
return self.board.hasData()
|
||||
|
||||
def getFileName(self):
|
||||
return self.board.getFileName()
|
||||
def getFileName(self):
|
||||
return self.board.getFileName()
|
||||
|
||||
def assertValid(self, pg, flag = True):
|
||||
self.pageValid[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
def assertValid(self, pg, flag=True):
|
||||
self.pageValid[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
||||
if False in self.pageValid:
|
||||
self.parent.enableSaveBoard(False, False)
|
||||
else:
|
||||
self.parent.enableSaveBoard(not self.protFileLoaded, True)
|
||||
if False in self.pageValid:
|
||||
self.parent.enableSaveBoard(False, False)
|
||||
else:
|
||||
self.parent.enableSaveBoard(not self.protFileLoaded, True)
|
||||
|
||||
def modifyTab(self, pg):
|
||||
if self.pageModified[pg] and not self.pageValid[pg]:
|
||||
pfx = "?* "
|
||||
elif self.pageModified[pg]:
|
||||
pfx = "* "
|
||||
elif not self.pageValid[pg]:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
def modifyTab(self, pg):
|
||||
if self.pageModified[pg] and not self.pageValid[pg]:
|
||||
pfx = "?* "
|
||||
elif self.pageModified[pg]:
|
||||
pfx = "* "
|
||||
elif not self.pageValid[pg]:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setBoardTabDecor(pfx)
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setBoardTabDecor(pfx)
|
||||
|
||||
def setHeaters(self, ht):
|
||||
self.parent.setHeaters(ht)
|
||||
def setHeaters(self, ht):
|
||||
self.parent.setHeaters(ht)
|
||||
|
||||
def onClose(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
def onClose(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
|
||||
self.Destroy()
|
||||
self.Destroy()
|
||||
|
||||
def confirmLoseChanges(self, msg):
|
||||
if True not in self.pageModified:
|
||||
return True
|
||||
def confirmLoseChanges(self, msg):
|
||||
if True not in self.pageModified:
|
||||
return True
|
||||
|
||||
dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your board "
|
||||
"configuration that will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your board "
|
||||
"configuration that will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def onLoadConfig(self, evt):
|
||||
if not self.confirmLoseChanges("load a new board configuration"):
|
||||
return
|
||||
def onLoadConfig(self, evt):
|
||||
if not self.confirmLoseChanges("load a new board configuration"):
|
||||
return
|
||||
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Board configuration (board.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Board configuration (board.*.h)|board.*.h"
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Board configuration (board.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Board configuration (board.*.h)|board.*.h"
|
||||
|
||||
dlg = wx.FileDialog(self, message = "Choose a board config file",
|
||||
defaultDir = self.dir, defaultFile = "",
|
||||
wildcard = wildcard, style = wx.FD_OPEN | wx.FD_CHANGE_DIR)
|
||||
dlg = wx.FileDialog(
|
||||
self,
|
||||
message="Choose a board config file",
|
||||
defaultDir=self.dir,
|
||||
defaultFile="",
|
||||
wildcard=wildcard,
|
||||
style=wx.FD_OPEN | wx.FD_CHANGE_DIR,
|
||||
)
|
||||
|
||||
path = None
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
path = None
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
|
||||
dlg.Destroy()
|
||||
if path is None:
|
||||
return
|
||||
dlg.Destroy()
|
||||
if path is None:
|
||||
return
|
||||
|
||||
self.dir = os.path.dirname(path)
|
||||
rc, efn = self.loadConfigFile(path)
|
||||
self.dir = os.path.dirname(path)
|
||||
rc, efn = self.loadConfigFile(path)
|
||||
|
||||
if not rc:
|
||||
dlg = wx.MessageDialog(self, "Unable to process file %s." % efn,
|
||||
"File error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
if not rc:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Unable to process file %s." % efn,
|
||||
"File error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
|
||||
def loadConfigFile(self, fn):
|
||||
ok, file = self.board.loadConfigFile(fn)
|
||||
if not ok:
|
||||
return ok, file
|
||||
def loadConfigFile(self, fn):
|
||||
ok, file = self.board.loadConfigFile(fn)
|
||||
if not ok:
|
||||
return ok, file
|
||||
|
||||
if os.path.basename(fn) in protectedFiles:
|
||||
self.parent.enableSaveBoard(False, True)
|
||||
self.protFileLoaded = True
|
||||
else:
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSaveBoard(True, True)
|
||||
if os.path.basename(fn) in protectedFiles:
|
||||
self.parent.enableSaveBoard(False, True)
|
||||
self.protFileLoaded = True
|
||||
else:
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSaveBoard(True, True)
|
||||
|
||||
self.parent.setBoardTabFile(os.path.basename(fn))
|
||||
self.pgHeaters.setCandidatePins(self.board.candHeatPins)
|
||||
self.pgSensors.setCandidatePins(self.board.candThermPins)
|
||||
self.pgCpu.setCandidateProcessors(self.board.candProcessors)
|
||||
self.pgCpu.setCandidateClocks(self.board.candClocks)
|
||||
self.parent.setBoardTabFile(os.path.basename(fn))
|
||||
self.pgHeaters.setCandidatePins(self.board.candHeatPins)
|
||||
self.pgSensors.setCandidatePins(self.board.candThermPins)
|
||||
self.pgCpu.setCandidateProcessors(self.board.candProcessors)
|
||||
self.pgCpu.setCandidateClocks(self.board.candClocks)
|
||||
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.board.cfgValues)
|
||||
pg.setHelpText(self.board.helpText)
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.board.cfgValues)
|
||||
pg.setHelpText(self.board.helpText)
|
||||
|
||||
self.pgSensors.setSensors(self.board.sensors)
|
||||
self.pgHeaters.setHeaters(self.board.heaters)
|
||||
self.pgSensors.setSensors(self.board.sensors)
|
||||
self.pgHeaters.setHeaters(self.board.heaters)
|
||||
|
||||
return True, None
|
||||
return True, None
|
||||
|
||||
def onSaveConfig(self, evt):
|
||||
path = self.getFileName()
|
||||
return self.saveConfigFile(path)
|
||||
def onSaveConfig(self, evt):
|
||||
path = self.getFileName()
|
||||
return self.saveConfigFile(path)
|
||||
|
||||
def onSaveConfigAs(self, evt):
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Board configuration (board.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Board configuration (board.*.h)|board.*.h"
|
||||
def onSaveConfigAs(self, evt):
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Board configuration (board.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Board configuration (board.*.h)|board.*.h"
|
||||
|
||||
dlg = wx.FileDialog(self, message = "Save as ...", defaultDir = self.dir,
|
||||
defaultFile = "", wildcard = wildcard,
|
||||
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
|
||||
dlg = wx.FileDialog(
|
||||
self,
|
||||
message="Save as ...",
|
||||
defaultDir=self.dir,
|
||||
defaultFile="",
|
||||
wildcard=wildcard,
|
||||
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
|
||||
)
|
||||
|
||||
val = dlg.ShowModal()
|
||||
val = dlg.ShowModal()
|
||||
|
||||
if val != wx.ID_OK:
|
||||
dlg.Destroy()
|
||||
return
|
||||
if val != wx.ID_OK:
|
||||
dlg.Destroy()
|
||||
return
|
||||
|
||||
path = dlg.GetPath()
|
||||
dlg.Destroy()
|
||||
path = dlg.GetPath()
|
||||
dlg.Destroy()
|
||||
|
||||
rc = self.saveConfigFile(path)
|
||||
if rc:
|
||||
self.parent.setBoardTabFile(os.path.basename(path))
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSaveBoard(True, True)
|
||||
return rc
|
||||
rc = self.saveConfigFile(path)
|
||||
if rc:
|
||||
self.parent.setBoardTabFile(os.path.basename(path))
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSaveBoard(True, True)
|
||||
return rc
|
||||
|
||||
def saveConfigFile(self, path):
|
||||
if os.path.basename(path) in protectedFiles:
|
||||
dlg = wx.MessageDialog(self, "It's not allowed to overwrite files "
|
||||
"distributed by Teacup. Choose another name.",
|
||||
"Protected file error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
def saveConfigFile(self, path):
|
||||
if os.path.basename(path) in protectedFiles:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"It's not allowed to overwrite files "
|
||||
"distributed by Teacup. Choose another name.",
|
||||
"Protected file error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
if not os.path.basename(path).startswith("board."):
|
||||
dlg = wx.MessageDialog(self, "Illegal file name: %s.\n"
|
||||
"File name must begin with \"board.\"" % path,
|
||||
"Illegal file name", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
if not os.path.basename(path).startswith("board."):
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Illegal file name: %s.\n" 'File name must begin with "board."' % path,
|
||||
"Illegal file name",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
values = {}
|
||||
for pg in self.pages:
|
||||
v1 = pg.getValues()
|
||||
for k in v1.keys():
|
||||
values[k] = v1[k]
|
||||
values = {}
|
||||
for pg in self.pages:
|
||||
v1 = pg.getValues()
|
||||
for k in v1.keys():
|
||||
values[k] = v1[k]
|
||||
|
||||
ext = os.path.splitext(os.path.basename(path))[1]
|
||||
self.dir = os.path.dirname(path)
|
||||
ext = os.path.splitext(os.path.basename(path))[1]
|
||||
self.dir = os.path.dirname(path)
|
||||
|
||||
if ext == "":
|
||||
path += ".h"
|
||||
if ext == "":
|
||||
path += ".h"
|
||||
|
||||
try:
|
||||
self.board.saveConfigFile(path, values)
|
||||
except:
|
||||
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
|
||||
"File error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
try:
|
||||
self.board.saveConfigFile(path, values)
|
||||
except:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Unable to write to file %s." % path,
|
||||
"File error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
return self.generateTempTables()
|
||||
return self.generateTempTables()
|
||||
|
||||
def generateTempTables(self):
|
||||
if not generateTempTables(self.board.sensors, self.settings):
|
||||
dlg = wx.MessageDialog(self, "Error writing to file thermistortable.h.",
|
||||
"File error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
def generateTempTables(self):
|
||||
if not generateTempTables(self.board.sensors, self.settings):
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Error writing to file thermistortable.h.",
|
||||
"File error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import wx.lib.newevent
|
||||
import thread, shlex, subprocess
|
||||
import os, re
|
||||
|
|
@ -6,7 +5,7 @@ from os.path import isfile, join
|
|||
from sys import platform
|
||||
|
||||
if platform.startswith("win"):
|
||||
from _subprocess import STARTF_USESHOWWINDOW
|
||||
from _subprocess import STARTF_USESHOWWINDOW
|
||||
|
||||
(scriptEvent, EVT_SCRIPT_UPDATE) = wx.lib.newevent.NewEvent()
|
||||
SCRIPT_RUNNING = 1
|
||||
|
|
@ -14,447 +13,495 @@ SCRIPT_FINISHED = 2
|
|||
SCRIPT_CANCELLED = 3
|
||||
|
||||
TOOLPATHS_INSIDE_ARDUINO = [
|
||||
"hardware/tools/avr/bin/",
|
||||
"hardware/tools/" # avrdude in Arduino 1.0.x
|
||||
]
|
||||
"hardware/tools/avr/bin/",
|
||||
"hardware/tools/",
|
||||
] # avrdude in Arduino 1.0.x
|
||||
if platform.startswith("darwin"):
|
||||
# That's an OS property, the Applicaton Bundle hierarchy.
|
||||
pathsCopy = TOOLPATHS_INSIDE_ARDUINO
|
||||
TOOLPATHS_INSIDE_ARDUINO = []
|
||||
for path in pathsCopy:
|
||||
TOOLPATHS_INSIDE_ARDUINO.append("Contents/Resources/Java/" + path)
|
||||
TOOLPATHS_INSIDE_ARDUINO.append("Contents/Java/" + path)
|
||||
# That's an OS property, the Applicaton Bundle hierarchy.
|
||||
pathsCopy = TOOLPATHS_INSIDE_ARDUINO
|
||||
TOOLPATHS_INSIDE_ARDUINO = []
|
||||
for path in pathsCopy:
|
||||
TOOLPATHS_INSIDE_ARDUINO.append("Contents/Resources/Java/" + path)
|
||||
TOOLPATHS_INSIDE_ARDUINO.append("Contents/Java/" + path)
|
||||
|
||||
|
||||
class ScriptTools:
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
|
||||
def figureCommandPath(self, baseCommand):
|
||||
findConf = False
|
||||
if baseCommand == "avrdude":
|
||||
findConf = True
|
||||
def figureCommandPath(self, baseCommand):
|
||||
findConf = False
|
||||
if baseCommand == "avrdude":
|
||||
findConf = True
|
||||
|
||||
if platform.startswith("win"):
|
||||
baseCommand += ".exe"
|
||||
if platform.startswith("win"):
|
||||
baseCommand += ".exe"
|
||||
|
||||
if self.settings.arduinodir:
|
||||
cmdpath = self.settings.arduinodir
|
||||
if self.settings.arduinodir:
|
||||
cmdpath = self.settings.arduinodir
|
||||
|
||||
for pathOption in TOOLPATHS_INSIDE_ARDUINO:
|
||||
cmdpathTry = cmdpath
|
||||
for dir in pathOption.split("/"):
|
||||
cmdpathTry = os.path.join(cmdpathTry, dir)
|
||||
cmdpathTry = os.path.join(cmdpathTry, baseCommand)
|
||||
if os.path.exists(cmdpathTry):
|
||||
cmdpath = "\"" + cmdpathTry + "\""
|
||||
break
|
||||
for pathOption in TOOLPATHS_INSIDE_ARDUINO:
|
||||
cmdpathTry = cmdpath
|
||||
for dir in pathOption.split("/"):
|
||||
cmdpathTry = os.path.join(cmdpathTry, dir)
|
||||
cmdpathTry = os.path.join(cmdpathTry, baseCommand)
|
||||
if os.path.exists(cmdpathTry):
|
||||
cmdpath = '"' + cmdpathTry + '"'
|
||||
break
|
||||
|
||||
if findConf:
|
||||
confpath = cmdpath.strip("\"")
|
||||
exepos = confpath.rfind(".exe")
|
||||
if exepos >= 0:
|
||||
confpath = confpath[0:exepos]
|
||||
confpath += ".conf"
|
||||
if not os.path.exists(confpath):
|
||||
confpath = os.path.split(confpath)[0]
|
||||
confpath = os.path.split(confpath)[0]
|
||||
confpath = os.path.join(confpath, "etc")
|
||||
confpath = os.path.join(confpath, "avrdude.conf")
|
||||
if os.path.exists(confpath):
|
||||
cmdpath += " -C \"" + confpath + "\""
|
||||
if findConf:
|
||||
confpath = cmdpath.strip('"')
|
||||
exepos = confpath.rfind(".exe")
|
||||
if exepos >= 0:
|
||||
confpath = confpath[0:exepos]
|
||||
confpath += ".conf"
|
||||
if not os.path.exists(confpath):
|
||||
confpath = os.path.split(confpath)[0]
|
||||
confpath = os.path.split(confpath)[0]
|
||||
confpath = os.path.join(confpath, "etc")
|
||||
confpath = os.path.join(confpath, "avrdude.conf")
|
||||
if os.path.exists(confpath):
|
||||
cmdpath += ' -C "' + confpath + '"'
|
||||
|
||||
else:
|
||||
cmdpath = baseCommand
|
||||
# No need to search avrdude.conf in this case.
|
||||
else:
|
||||
cmdpath = baseCommand
|
||||
# No need to search avrdude.conf in this case.
|
||||
|
||||
return cmdpath
|
||||
return cmdpath
|
||||
|
||||
|
||||
class ScriptThread:
|
||||
def __init__(self, win, script):
|
||||
self.win = win
|
||||
self.running = False
|
||||
self.cancelled = False
|
||||
self.script = script
|
||||
def __init__(self, win, script):
|
||||
self.win = win
|
||||
self.running = False
|
||||
self.cancelled = False
|
||||
self.script = script
|
||||
|
||||
def Start(self):
|
||||
self.running = True
|
||||
self.cancelled = False
|
||||
thread.start_new_thread(self.Run, ())
|
||||
def Start(self):
|
||||
self.running = True
|
||||
self.cancelled = False
|
||||
thread.start_new_thread(self.Run, ())
|
||||
|
||||
def Stop(self):
|
||||
self.cancelled = True
|
||||
def Stop(self):
|
||||
self.cancelled = True
|
||||
|
||||
def IsRunning(self):
|
||||
return self.running
|
||||
def IsRunning(self):
|
||||
return self.running
|
||||
|
||||
def Run(self):
|
||||
if platform.startswith("win"):
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
|
||||
for cmd in self.script:
|
||||
evt = scriptEvent(msg = cmd, state = SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
args = shlex.split(str(cmd))
|
||||
try:
|
||||
def Run(self):
|
||||
if platform.startswith("win"):
|
||||
p = subprocess.Popen(args, stderr = subprocess.STDOUT,
|
||||
stdout = subprocess.PIPE,
|
||||
startupinfo = startupinfo)
|
||||
else:
|
||||
p = subprocess.Popen(args, stderr = subprocess.STDOUT,
|
||||
stdout = subprocess.PIPE)
|
||||
except:
|
||||
evt = scriptEvent(msg = "Exception occurred trying to run\n\n%s" % cmd,
|
||||
state = SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
obuf = ''
|
||||
while not self.cancelled:
|
||||
o = p.stdout.read(1)
|
||||
if o == '': break
|
||||
if o == '\r' or o == '\n':
|
||||
if obuf.strip() != "":
|
||||
evt = scriptEvent(msg = obuf, state = SCRIPT_RUNNING)
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
|
||||
for cmd in self.script:
|
||||
evt = scriptEvent(msg=cmd, state=SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
obuf = ''
|
||||
elif ord(o) < 32:
|
||||
pass
|
||||
else:
|
||||
obuf += o
|
||||
args = shlex.split(str(cmd))
|
||||
try:
|
||||
if platform.startswith("win"):
|
||||
p = subprocess.Popen(
|
||||
args,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdout=subprocess.PIPE,
|
||||
startupinfo=startupinfo,
|
||||
)
|
||||
else:
|
||||
p = subprocess.Popen(
|
||||
args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE
|
||||
)
|
||||
except:
|
||||
evt = scriptEvent(
|
||||
msg="Exception occurred trying to run\n\n%s" % cmd,
|
||||
state=SCRIPT_CANCELLED,
|
||||
)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
obuf = ""
|
||||
while not self.cancelled:
|
||||
o = p.stdout.read(1)
|
||||
if o == "":
|
||||
break
|
||||
if o == "\r" or o == "\n":
|
||||
if obuf.strip() != "":
|
||||
evt = scriptEvent(msg=obuf, state=SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
obuf = ""
|
||||
elif ord(o) < 32:
|
||||
pass
|
||||
else:
|
||||
obuf += o
|
||||
|
||||
if self.cancelled:
|
||||
evt = scriptEvent(msg = None, state = SCRIPT_CANCELLED)
|
||||
if self.cancelled:
|
||||
evt = scriptEvent(msg=None, state=SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
p.kill()
|
||||
self.running = False
|
||||
p.wait()
|
||||
return
|
||||
|
||||
rc = p.wait()
|
||||
if rc != 0:
|
||||
msg = "RC = " + str(rc) + " - Build terminated"
|
||||
evt = scriptEvent(msg=msg, state=SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
|
||||
evt = scriptEvent(msg="", state=SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
|
||||
evt = scriptEvent(msg=None, state=SCRIPT_FINISHED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
p.kill()
|
||||
|
||||
self.running = False
|
||||
p.wait()
|
||||
return
|
||||
|
||||
rc = p.wait()
|
||||
if rc != 0:
|
||||
msg = "RC = " + str(rc) + " - Build terminated"
|
||||
evt = scriptEvent(msg = msg, state = SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
|
||||
evt = scriptEvent(msg = "", state = SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
|
||||
evt = scriptEvent(msg = None, state = SCRIPT_FINISHED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
|
||||
self.running = False
|
||||
|
||||
|
||||
class Build(wx.Dialog):
|
||||
def __init__(self, parent, settings, f_cpu, cpu):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Build teacup",
|
||||
style = wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
self.cancelPending = False
|
||||
def __init__(self, parent, settings, f_cpu, cpu):
|
||||
wx.Dialog.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
"Build teacup",
|
||||
style=wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE,
|
||||
)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
self.cancelPending = False
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
|
||||
style = wx.TE_READONLY + wx.TE_MULTILINE)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
|
||||
wx.FONTWEIGHT_BOLD)
|
||||
tc.SetFont(f)
|
||||
self.log = tc
|
||||
tc = wx.TextCtrl(
|
||||
self, wx.ID_ANY, size=(900, 300), style=wx.TE_READONLY + wx.TE_MULTILINE
|
||||
)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
|
||||
tc.SetFont(f)
|
||||
self.log = tc
|
||||
|
||||
sz.Add((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.Add((10, 10))
|
||||
sz.Add((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
self.SetSizer(hsz)
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
builddir = join(self.root, "build")
|
||||
if not os.path.exists(builddir):
|
||||
os.makedirs(builddir)
|
||||
self.log.AppendText("Directory %s created.\n\n" % builddir)
|
||||
self.Fit()
|
||||
builddir = join(self.root, "build")
|
||||
if not os.path.exists(builddir):
|
||||
os.makedirs(builddir)
|
||||
self.log.AppendText("Directory %s created.\n\n" % builddir)
|
||||
|
||||
self.compile()
|
||||
self.compile()
|
||||
|
||||
def compile(self):
|
||||
self.generateCompileScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to compile!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.compileUpdate)
|
||||
self.t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
self.t.Start()
|
||||
|
||||
def link(self):
|
||||
self.generateLinkScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to link!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.linkUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
def report(self):
|
||||
self.script = []
|
||||
self.reportLines = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-objdump")
|
||||
elfpath = "\"" + join(self.root, "build", "teacup.elf") + "\""
|
||||
cmd = cmdpath + " -h " + elfpath
|
||||
self.script.append(cmd)
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.reportUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
def generateCompileScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-gcc")
|
||||
|
||||
cfiles = [f for f in os.listdir(self.root)
|
||||
if isfile(join(self.root,f)) and f.endswith(".c")]
|
||||
for f in cfiles:
|
||||
basename = f[:-2]
|
||||
ofile = basename + ".o"
|
||||
alfile = basename + ".al"
|
||||
opath = "\"" + join(self.root, "build", ofile) + "\""
|
||||
alpath = "\"" + join(self.root, "build", alfile) + "\""
|
||||
cpath = "\"" + join(self.root, f) + "\""
|
||||
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", alpath)
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
|
||||
cmd = cmdpath + " -c " + opts + " -o " + opath + " " + cpath
|
||||
self.script.append(cmd)
|
||||
|
||||
def generateLinkScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-gcc")
|
||||
|
||||
# This is ugly:
|
||||
# Work around a problem of avr-ld.exe coming with Arduino 1.6.4 for
|
||||
# Windows. Without this it always drops this error message:
|
||||
# collect2.exe: error: ld returned 5 exit status 255
|
||||
# Just enabling verbose messages allows ld.exe to complete without failure.
|
||||
if platform.startswith("win"):
|
||||
cmdpath += " -Wl,-V"
|
||||
|
||||
ofiles = ["\"" + join(self.root, "build", f) + "\""
|
||||
for f in os.listdir(join(self.root, "build"))
|
||||
if isfile(join(self.root, "build", f)) and f.endswith(".o")]
|
||||
opath = " ".join(ofiles)
|
||||
elfpath = "\"" + join(self.root, "build", "teacup.elf") + "\""
|
||||
hexpath = "\"" + join(self.root, "teacup.hex") + "\""
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", "teacup.elf")
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
cmd = cmdpath + " " + self.settings.ldflags + " " + opts + " -o " + \
|
||||
elfpath + " " + opath + " -lm"
|
||||
self.script.append(cmd)
|
||||
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-objcopy")
|
||||
cmd = cmdpath + " " + self.settings.objcopyflags + " " + elfpath + \
|
||||
" " + hexpath
|
||||
self.script.append(cmd)
|
||||
|
||||
def compileUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.active = False
|
||||
|
||||
if self.cancelPending:
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
self.log.AppendText("Build terminated abnormally.\n")
|
||||
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Compile completed normally.\n\n")
|
||||
self.link()
|
||||
|
||||
def linkUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText("Link terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Link completed normally.\n")
|
||||
self.report()
|
||||
|
||||
def reportUpdate(self, evt):
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
if evt.msg is not None:
|
||||
self.reportLines.append(evt.msg)
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
self.log.AppendText("Report terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.formatReport()
|
||||
self.log.AppendText("\nBuild completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def formatReportLine(self, m, name, v168, v328, v644, v1280):
|
||||
t = m.groups()
|
||||
v = int(t[0], 16)
|
||||
self.log.AppendText(("%12s: %6d bytes %6.2f%% %6.2f%%"
|
||||
" %6.2f%% %6.2f%%\n") %
|
||||
(name, v, v / float(v168 * 1024) * 100.0,
|
||||
v / float(v328 * 1024) * 100.0,
|
||||
v / float(v644 * 1024) * 100.0,
|
||||
v / float(v1280 * 1024) * 100.0))
|
||||
|
||||
def formatReport(self):
|
||||
reText = re.compile("\.text\s+([0-9a-f]+)")
|
||||
reBss = re.compile("\.bss\s+([0-9a-f]+)")
|
||||
reEEProm = re.compile("\.eeprom\s+([0-9a-f]+)")
|
||||
|
||||
self.log.AppendText("\n ATmega... '168 '328(P)"
|
||||
" '644(P) '1280\n")
|
||||
for l in self.reportLines:
|
||||
m = reText.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "FLASH", 14, 30, 62, 126)
|
||||
else:
|
||||
m = reBss.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "RAM", 1, 2, 4, 8)
|
||||
def compile(self):
|
||||
self.generateCompileScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to compile!\n")
|
||||
self.active = False
|
||||
else:
|
||||
m = reEEProm.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "EEPROM", 1, 2, 2, 4)
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.compileUpdate)
|
||||
self.t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
self.t.Start()
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
dlg = wx.MessageDialog(self, "Are you sure you want to cancel building?",
|
||||
"Build active",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
def link(self):
|
||||
self.generateLinkScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to link!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.linkUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
if rc == wx.ID_YES:
|
||||
self.cancelPending = True
|
||||
self.log.AppendText("Cancelling...\n")
|
||||
self.t.Stop()
|
||||
return
|
||||
def report(self):
|
||||
self.script = []
|
||||
self.reportLines = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-objdump")
|
||||
elfpath = '"' + join(self.root, "build", "teacup.elf") + '"'
|
||||
cmd = cmdpath + " -h " + elfpath
|
||||
self.script.append(cmd)
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.reportUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
self.EndModal(wx.ID_OK)
|
||||
def generateCompileScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-gcc")
|
||||
|
||||
cfiles = [
|
||||
f
|
||||
for f in os.listdir(self.root)
|
||||
if isfile(join(self.root, f)) and f.endswith(".c")
|
||||
]
|
||||
for f in cfiles:
|
||||
basename = f[:-2]
|
||||
ofile = basename + ".o"
|
||||
alfile = basename + ".al"
|
||||
opath = '"' + join(self.root, "build", ofile) + '"'
|
||||
alpath = '"' + join(self.root, "build", alfile) + '"'
|
||||
cpath = '"' + join(self.root, f) + '"'
|
||||
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", alpath)
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
|
||||
cmd = cmdpath + " -c " + opts + " -o " + opath + " " + cpath
|
||||
self.script.append(cmd)
|
||||
|
||||
def generateLinkScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-gcc")
|
||||
|
||||
# This is ugly:
|
||||
# Work around a problem of avr-ld.exe coming with Arduino 1.6.4 for
|
||||
# Windows. Without this it always drops this error message:
|
||||
# collect2.exe: error: ld returned 5 exit status 255
|
||||
# Just enabling verbose messages allows ld.exe to complete without failure.
|
||||
if platform.startswith("win"):
|
||||
cmdpath += " -Wl,-V"
|
||||
|
||||
ofiles = [
|
||||
'"' + join(self.root, "build", f) + '"'
|
||||
for f in os.listdir(join(self.root, "build"))
|
||||
if isfile(join(self.root, "build", f)) and f.endswith(".o")
|
||||
]
|
||||
opath = " ".join(ofiles)
|
||||
elfpath = '"' + join(self.root, "build", "teacup.elf") + '"'
|
||||
hexpath = '"' + join(self.root, "teacup.hex") + '"'
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", "teacup.elf")
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
cmd = (
|
||||
cmdpath
|
||||
+ " "
|
||||
+ self.settings.ldflags
|
||||
+ " "
|
||||
+ opts
|
||||
+ " -o "
|
||||
+ elfpath
|
||||
+ " "
|
||||
+ opath
|
||||
+ " -lm"
|
||||
)
|
||||
self.script.append(cmd)
|
||||
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avr-objcopy")
|
||||
cmd = cmdpath + " " + self.settings.objcopyflags + " " + elfpath + " " + hexpath
|
||||
self.script.append(cmd)
|
||||
|
||||
def compileUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.active = False
|
||||
|
||||
if self.cancelPending:
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
self.log.AppendText("Build terminated abnormally.\n")
|
||||
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Compile completed normally.\n\n")
|
||||
self.link()
|
||||
|
||||
def linkUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText("Link terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Link completed normally.\n")
|
||||
self.report()
|
||||
|
||||
def reportUpdate(self, evt):
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
if evt.msg is not None:
|
||||
self.reportLines.append(evt.msg)
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
self.log.AppendText("Report terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.formatReport()
|
||||
self.log.AppendText("\nBuild completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def formatReportLine(self, m, name, v168, v328, v644, v1280):
|
||||
t = m.groups()
|
||||
v = int(t[0], 16)
|
||||
self.log.AppendText(
|
||||
("%12s: %6d bytes %6.2f%% %6.2f%%" " %6.2f%% %6.2f%%\n")
|
||||
% (
|
||||
name,
|
||||
v,
|
||||
v / float(v168 * 1024) * 100.0,
|
||||
v / float(v328 * 1024) * 100.0,
|
||||
v / float(v644 * 1024) * 100.0,
|
||||
v / float(v1280 * 1024) * 100.0,
|
||||
)
|
||||
)
|
||||
|
||||
def formatReport(self):
|
||||
reText = re.compile("\.text\s+([0-9a-f]+)")
|
||||
reBss = re.compile("\.bss\s+([0-9a-f]+)")
|
||||
reEEProm = re.compile("\.eeprom\s+([0-9a-f]+)")
|
||||
|
||||
self.log.AppendText(
|
||||
"\n ATmega... '168 '328(P)" " '644(P) '1280\n"
|
||||
)
|
||||
for l in self.reportLines:
|
||||
m = reText.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "FLASH", 14, 30, 62, 126)
|
||||
else:
|
||||
m = reBss.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "RAM", 1, 2, 4, 8)
|
||||
else:
|
||||
m = reEEProm.search(l)
|
||||
if m:
|
||||
self.formatReportLine(m, "EEPROM", 1, 2, 2, 4)
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Are you sure you want to cancel building?",
|
||||
"Build active",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc == wx.ID_YES:
|
||||
self.cancelPending = True
|
||||
self.log.AppendText("Cancelling...\n")
|
||||
self.t.Stop()
|
||||
return
|
||||
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
|
||||
class Upload(wx.Dialog):
|
||||
def __init__(self, parent, settings, f_cpu, cpu):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Upload teacup",
|
||||
style = wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.baud = self.settings.uploadspeed
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
self.cancelPending = False
|
||||
def __init__(self, parent, settings, f_cpu, cpu):
|
||||
wx.Dialog.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
"Upload teacup",
|
||||
style=wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE,
|
||||
)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.baud = self.settings.uploadspeed
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
self.cancelPending = False
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
|
||||
style = wx.TE_READONLY + wx.TE_MULTILINE)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
|
||||
wx.FONTWEIGHT_BOLD)
|
||||
tc.SetFont(f)
|
||||
self.log = tc
|
||||
tc = wx.TextCtrl(
|
||||
self, wx.ID_ANY, size=(900, 300), style=wx.TE_READONLY + wx.TE_MULTILINE
|
||||
)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
|
||||
tc.SetFont(f)
|
||||
self.log = tc
|
||||
|
||||
sz.Add((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.Add((10, 10))
|
||||
sz.Add((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
self.SetSizer(hsz)
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
self.generateUploadScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to upload!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.uploadUpdate)
|
||||
self.t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
self.t.Start()
|
||||
self.Fit()
|
||||
self.generateUploadScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to upload!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.uploadUpdate)
|
||||
self.t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
self.t.Start()
|
||||
|
||||
def generateUploadScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avrdude")
|
||||
hexpath = "\"" + join(self.root, "teacup.hex") + "\""
|
||||
def generateUploadScript(self):
|
||||
self.script = []
|
||||
cmdpath = ScriptTools(self.settings).figureCommandPath("avrdude")
|
||||
hexpath = '"' + join(self.root, "teacup.hex") + '"'
|
||||
|
||||
cmd = cmdpath + " -c %s %s -b %s -p %s -P %s -U flash:w:%s:i" % \
|
||||
(self.settings.programmer, self.settings.programflags, self.baud,
|
||||
self.cpu, self.settings.port, hexpath)
|
||||
self.script.append(cmd)
|
||||
cmd = cmdpath + " -c %s %s -b %s -p %s -P %s -U flash:w:%s:i" % (
|
||||
self.settings.programmer,
|
||||
self.settings.programflags,
|
||||
self.baud,
|
||||
self.cpu,
|
||||
self.settings.port,
|
||||
hexpath,
|
||||
)
|
||||
self.script.append(cmd)
|
||||
|
||||
def uploadUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
def uploadUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.active = False
|
||||
|
||||
if self.cancelPending:
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
self.log.AppendText("Upload terminated abnormally.\n")
|
||||
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Upload completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Are you sure you want to cancel upload?",
|
||||
"Upload active",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc == wx.ID_YES:
|
||||
self.cancelPending = True
|
||||
self.log.AppendText("Cancelling...\n")
|
||||
self.t.Stop()
|
||||
return
|
||||
|
||||
if self.cancelPending:
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
self.log.AppendText("Upload terminated abnormally.\n")
|
||||
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Upload completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
dlg = wx.MessageDialog(self, "Are you sure you want to cancel upload?",
|
||||
"Upload active",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc == wx.ID_YES:
|
||||
self.cancelPending = True
|
||||
self.log.AppendText("Cancelling...\n")
|
||||
self.t.Stop()
|
||||
return
|
||||
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
|
|
|||
|
|
@ -1,296 +1,331 @@
|
|||
|
||||
import wx
|
||||
from configtool.data import (BSIZESMALL, reFloat, reInteger, offsetChLabel,
|
||||
offsetTcLabel)
|
||||
from configtool.data import BSIZESMALL, reFloat, reInteger, offsetChLabel, offsetTcLabel
|
||||
|
||||
|
||||
class CalcBelt(wx.Dialog):
|
||||
def __init__(self, parent, font, cbUse):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY,
|
||||
"Steps calculator for belt driven axes",
|
||||
size = (360, 300))
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
def __init__(self, parent, font, cbUse):
|
||||
wx.Dialog.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
"Steps calculator for belt driven axes",
|
||||
size=(360, 300),
|
||||
)
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
|
||||
self.use = cbUse
|
||||
labelWidth = 130
|
||||
self.use = cbUse
|
||||
labelWidth = 130
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Step Angle:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Step Angle:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
stepAngles = ["1.8 (200 per revolution)", "0.9 (400 per revolution)",
|
||||
"7.5 (48 per revolution)"]
|
||||
self.stepAngleValues = [200, 400, 48]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = stepAngles)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Step angle. Depends on your type of stepper motor.")
|
||||
self.tcStep = tc
|
||||
stepAngles = [
|
||||
"1.8 (200 per revolution)",
|
||||
"0.9 (400 per revolution)",
|
||||
"7.5 (48 per revolution)",
|
||||
]
|
||||
self.stepAngleValues = [200, 400, 48]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=stepAngles)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Step angle. Depends on your type of stepper motor.")
|
||||
self.tcStep = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Microstepping:",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
"Microstepping:",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
microStepping = ["1 - full step", "1/2 - half step", "1/4 - quarter step",
|
||||
"1/8", "1/16", "1/32", "1/64", "1/128"]
|
||||
self.microSteppingValues = [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = microStepping)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
tc.SetSelection(4)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Microstepping. Most boards allow to change this by "
|
||||
"setting jumpers. The value here must match the "
|
||||
"setting on the board in conjunction with the type "
|
||||
"of stepper driver chip.")
|
||||
self.tcMicroStepping = tc
|
||||
microStepping = [
|
||||
"1 - full step",
|
||||
"1/2 - half step",
|
||||
"1/4 - quarter step",
|
||||
"1/8",
|
||||
"1/16",
|
||||
"1/32",
|
||||
"1/64",
|
||||
"1/128",
|
||||
]
|
||||
self.microSteppingValues = [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=microStepping)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
tc.SetSelection(4)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip(
|
||||
"Microstepping. Most boards allow to change this by "
|
||||
"setting jumpers. The value here must match the "
|
||||
"setting on the board in conjunction with the type "
|
||||
"of stepper driver chip."
|
||||
)
|
||||
self.tcMicroStepping = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Belt Pitch (in mm):",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
"Belt Pitch (in mm):",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "2", style = wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Belt pitch. Distance between two teeth on the belt.")
|
||||
self.tcBeltPitch = tc
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "2", style=wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Belt pitch. Distance between two teeth on the belt.")
|
||||
self.tcBeltPitch = tc
|
||||
|
||||
lsz.Add((5, 5))
|
||||
lsz.Add((5, 5))
|
||||
|
||||
beltPresets = ["-", "2mm Pitch (GT2)", "MXL Pitch (2.03mm)",
|
||||
"T2.5 (2.5mm)", "3mm Pitch (GT2, HTD)",
|
||||
"5mm Pitch (T5, GTD, HTD)", "0.2\" XL belt (5.08mm)"]
|
||||
self.beltPresetValues = [-1, 2.0, 2.03, 2.5, 3.0, 5.0, 5.08]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = beltPresets)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onPresetChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Belt pitch presets.")
|
||||
self.tcPresets = tc
|
||||
beltPresets = [
|
||||
"-",
|
||||
"2mm Pitch (GT2)",
|
||||
"MXL Pitch (2.03mm)",
|
||||
"T2.5 (2.5mm)",
|
||||
"3mm Pitch (GT2, HTD)",
|
||||
"5mm Pitch (T5, GTD, HTD)",
|
||||
'0.2" XL belt (5.08mm)',
|
||||
]
|
||||
self.beltPresetValues = [-1, 2.0, 2.03, 2.5, 3.0, 5.0, 5.08]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=beltPresets)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onPresetChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Belt pitch presets.")
|
||||
self.tcPresets = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Pulley Teeth Count:",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
"Pulley Teeth Count:",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "8", style = wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlInteger)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Pulley teeth count. Count them!")
|
||||
self.tcPulleyTeeth = tc
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "8", style=wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlInteger)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Pulley teeth count. Count them!")
|
||||
self.tcPulleyTeeth = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((30, 30))
|
||||
sz.Add(lsz)
|
||||
sz.Add((30, 30))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Result:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Result:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size = (260, -1),
|
||||
style = wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResult = tc
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size=(260, -1), style=wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResult = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Resolution:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
sz.Add(lsz)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Resolution:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size = (260, -1),
|
||||
style = wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResolution = tc
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size=(260, -1), style=wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResolution = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add(lsz)
|
||||
|
||||
sz.Add((20, 20))
|
||||
sz.Add((20, 20))
|
||||
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for X", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForX, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForX = b
|
||||
bsz.Add((5, 5))
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for X", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForX, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForX = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Y", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForY, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForY = b
|
||||
bsz.Add((5, 5))
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Y", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForY, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForY = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Z", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForZ, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForZ = b
|
||||
bsz.Add((5, 5))
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Z", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForZ, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForZ = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for E", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForE, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForE = b
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for E", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForE, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForE = b
|
||||
|
||||
sz.Add(bsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(bsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
self.enableUseButtons(False)
|
||||
self.enableUseButtons(False)
|
||||
|
||||
self.SetSizer(hsz)
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
self.Fit()
|
||||
|
||||
self.calculate()
|
||||
self.calculate()
|
||||
|
||||
def calculate(self):
|
||||
self.tcResult.SetLabel("")
|
||||
self.tcResolution.SetLabel("")
|
||||
self.enableUseButtons(False)
|
||||
s = self.tcStep.GetSelection()
|
||||
sv = self.stepAngleValues[s]
|
||||
|
||||
def calculate(self):
|
||||
self.tcResult.SetLabel("")
|
||||
self.tcResolution.SetLabel("")
|
||||
self.enableUseButtons(False)
|
||||
s = self.tcStep.GetSelection()
|
||||
sv = self.stepAngleValues[s]
|
||||
try:
|
||||
bp = float(self.tcBeltPitch.GetValue())
|
||||
except:
|
||||
return
|
||||
|
||||
try:
|
||||
bp = float(self.tcBeltPitch.GetValue())
|
||||
except:
|
||||
return
|
||||
try:
|
||||
pt = int(self.tcPulleyTeeth.GetValue())
|
||||
except:
|
||||
return
|
||||
|
||||
try:
|
||||
pt = int(self.tcPulleyTeeth.GetValue())
|
||||
except:
|
||||
return
|
||||
s = self.tcMicroStepping.GetSelection()
|
||||
msv = self.microSteppingValues[s]
|
||||
|
||||
s = self.tcMicroStepping.GetSelection()
|
||||
msv = self.microSteppingValues[s]
|
||||
length = pt * bp
|
||||
steps = sv * msv
|
||||
|
||||
length = pt * bp
|
||||
steps = sv * msv
|
||||
resultmm = steps / length
|
||||
self.result = int(resultmm * 1000.0)
|
||||
|
||||
resultmm = steps / length
|
||||
self.result = int(resultmm * 1000.0)
|
||||
self.tcResult.SetLabel("%d steps/m (%.3f steps/mm)" % (self.result, resultmm))
|
||||
self.tcResolution.SetLabel("%.3f micrometers" % (length / steps * 1000.0))
|
||||
self.enableUseButtons(True)
|
||||
|
||||
self.tcResult.SetLabel("%d steps/m (%.3f steps/mm)" %
|
||||
(self.result, resultmm))
|
||||
self.tcResolution.SetLabel("%.3f micrometers" % (length / steps * 1000.0))
|
||||
self.enableUseButtons(True)
|
||||
def enableUseButtons(self, flag):
|
||||
self.bUseForX.Enable(flag)
|
||||
self.bUseForY.Enable(flag)
|
||||
self.bUseForZ.Enable(flag)
|
||||
self.bUseForE.Enable(flag)
|
||||
|
||||
def enableUseButtons(self, flag):
|
||||
self.bUseForX.Enable(flag)
|
||||
self.bUseForY.Enable(flag)
|
||||
self.bUseForZ.Enable(flag)
|
||||
self.bUseForE.Enable(flag)
|
||||
def onUseForX(self, evt):
|
||||
self.use("STEPS_PER_M_X", self.result)
|
||||
|
||||
def onUseForX(self, evt):
|
||||
self.use('STEPS_PER_M_X', self.result)
|
||||
def onUseForY(self, evt):
|
||||
self.use("STEPS_PER_M_Y", self.result)
|
||||
|
||||
def onUseForY(self, evt):
|
||||
self.use('STEPS_PER_M_Y', self.result)
|
||||
def onUseForZ(self, evt):
|
||||
self.use("STEPS_PER_M_Z", self.result)
|
||||
|
||||
def onUseForZ(self, evt):
|
||||
self.use('STEPS_PER_M_Z', self.result)
|
||||
def onUseForE(self, evt):
|
||||
self.use("STEPS_PER_M_E", self.result)
|
||||
|
||||
def onUseForE(self, evt):
|
||||
self.use('STEPS_PER_M_E', self.result)
|
||||
def onPresetChoice(self, evt):
|
||||
s = self.tcPresets.GetSelection()
|
||||
sv = self.beltPresetValues[s]
|
||||
if sv < 0:
|
||||
return
|
||||
|
||||
def onPresetChoice(self, evt):
|
||||
s = self.tcPresets.GetSelection()
|
||||
sv = self.beltPresetValues[s]
|
||||
if sv < 0:
|
||||
return
|
||||
s = "%f" % sv
|
||||
s = s.rstrip("0")
|
||||
if s[-1] == ".":
|
||||
s += "0"
|
||||
self.tcBeltPitch.SetValue(s)
|
||||
|
||||
s = "%f" % sv
|
||||
s = s.rstrip("0")
|
||||
if s[-1] == ".":
|
||||
s += "0"
|
||||
self.tcBeltPitch.SetValue(s)
|
||||
def onChoice(self, evt):
|
||||
self.calculate()
|
||||
|
||||
def onChoice(self, evt):
|
||||
self.calculate()
|
||||
def onTextCtrlInteger(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reInteger.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
def onTextCtrlInteger(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reInteger.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
def onTextCtrlFloat(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
def onTextCtrlFloat(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
|
||||
def onExit(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
def onExit(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
|
|
|||
|
|
@ -1,296 +1,339 @@
|
|||
|
||||
import wx
|
||||
from configtool.data import BSIZESMALL, reFloat, offsetChLabel, offsetTcLabel
|
||||
|
||||
|
||||
class CalcScrew(wx.Dialog):
|
||||
def __init__(self, parent, font, cbUse):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY,
|
||||
"Steps calculator for screw driven axes",
|
||||
size = (400, 204))
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
def __init__(self, parent, font, cbUse):
|
||||
wx.Dialog.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
"Steps calculator for screw driven axes",
|
||||
size=(400, 204),
|
||||
)
|
||||
self.SetFont(font)
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
|
||||
self.use = cbUse
|
||||
labelWidth = 150
|
||||
self.use = cbUse
|
||||
labelWidth = 150
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Step Angle:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Step Angle:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
stepAngles = ["1.8 (200 per revolution)", "0.9 (400 per revolution)",
|
||||
"7.5 (48 per revolution)"]
|
||||
self.stepAngleValues = [200, 400, 48]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = stepAngles)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Step angle. Depends on your type of stepper motor.")
|
||||
self.tcStep = tc
|
||||
stepAngles = [
|
||||
"1.8 (200 per revolution)",
|
||||
"0.9 (400 per revolution)",
|
||||
"7.5 (48 per revolution)",
|
||||
]
|
||||
self.stepAngleValues = [200, 400, 48]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=stepAngles)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Step angle. Depends on your type of stepper motor.")
|
||||
self.tcStep = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Microstepping:",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
"Microstepping:",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
microStepping = ["1 - full step", "1/2 - half step", "1/4 - quarter step",
|
||||
"1/8", "1/16", "1/32", "1/64", "1/128"]
|
||||
self.microSteppingValues = [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = microStepping)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
tc.SetSelection(4)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Microstepping. Most boards allow to change this by "
|
||||
"setting jumpers. The value here must match the "
|
||||
"setting on the board in conjunction with the type "
|
||||
"of stepper driver chip.")
|
||||
self.tcMicroStepping = tc
|
||||
microStepping = [
|
||||
"1 - full step",
|
||||
"1/2 - half step",
|
||||
"1/4 - quarter step",
|
||||
"1/8",
|
||||
"1/16",
|
||||
"1/32",
|
||||
"1/64",
|
||||
"1/128",
|
||||
]
|
||||
self.microSteppingValues = [1, 2, 4, 8, 16, 32, 64, 128]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=microStepping)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
tc.SetSelection(4)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip(
|
||||
"Microstepping. Most boards allow to change this by "
|
||||
"setting jumpers. The value here must match the "
|
||||
"setting on the board in conjunction with the type "
|
||||
"of stepper driver chip."
|
||||
)
|
||||
self.tcMicroStepping = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Screw Pitch (mm/rev):",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
"Screw Pitch (mm/rev):",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "2", style = wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Screw pitch. Defined by the pitch of the screw.")
|
||||
self.tcScrewPitch = tc
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "2", style=wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Screw pitch. Defined by the pitch of the screw.")
|
||||
self.tcScrewPitch = tc
|
||||
|
||||
lsz.Add((5, 5))
|
||||
lsz.Add((5, 5))
|
||||
|
||||
screwPresets = ["-", "M8 - metric (1.25 mm/rev)", "M6 - metric (1 mm/rev)",
|
||||
"M5 - metric (0.8 mm/rev)", "12 (12 mm/rev)",
|
||||
"16 (16 mm/rev)", "25 (25 mm/rev)",
|
||||
"5/15\"-18 imperial coarse (1.41111 mm/rev)",
|
||||
"3/16\"-20 imperial (1.270 mm/rev)",
|
||||
"1/4\"-16 ACME (1.5875 mm/rev)"]
|
||||
self.screwPresetValues = [-1, 1.25, 1.00, 0.8, 12.0, 16.0, 25.0, 1.41111,
|
||||
1.270, 1.5875]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices = screwPresets)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onPresetChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Screw pitch presets.")
|
||||
self.tcPresets = tc
|
||||
screwPresets = [
|
||||
"-",
|
||||
"M8 - metric (1.25 mm/rev)",
|
||||
"M6 - metric (1 mm/rev)",
|
||||
"M5 - metric (0.8 mm/rev)",
|
||||
"12 (12 mm/rev)",
|
||||
"16 (16 mm/rev)",
|
||||
"25 (25 mm/rev)",
|
||||
'5/15"-18 imperial coarse (1.41111 mm/rev)',
|
||||
'3/16"-20 imperial (1.270 mm/rev)',
|
||||
'1/4"-16 ACME (1.5875 mm/rev)',
|
||||
]
|
||||
self.screwPresetValues = [
|
||||
-1,
|
||||
1.25,
|
||||
1.00,
|
||||
0.8,
|
||||
12.0,
|
||||
16.0,
|
||||
25.0,
|
||||
1.41111,
|
||||
1.270,
|
||||
1.5875,
|
||||
]
|
||||
tc = wx.Choice(self, wx.ID_ANY, choices=screwPresets)
|
||||
tc.SetFont(font)
|
||||
tc.SetSelection(0)
|
||||
tc.Bind(wx.EVT_CHOICE, self.onPresetChoice)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Screw pitch presets.")
|
||||
self.tcPresets = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Gear Ratio:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Gear Ratio:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "1", size = (40, -1), style = wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Gear ratio. 1:1 if there is no gear.")
|
||||
self.tcRatioTop = tc
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "1", size=(40, -1), style=wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Gear ratio. 1:1 if there is no gear.")
|
||||
self.tcRatioTop = tc
|
||||
|
||||
lsz.Add((5, 5))
|
||||
st = wx.StaticText(self, wx.ID_ANY, ":")
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
lsz.Add((5, 5))
|
||||
st = wx.StaticText(self, wx.ID_ANY, ":")
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "1", size = (40, -1), style = wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Gear ratio. 1:1 if there is no gear.")
|
||||
self.tcRatioBottom = tc
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "1", size=(40, -1), style=wx.TE_RIGHT)
|
||||
tc.SetFont(font)
|
||||
tc.Bind(wx.EVT_TEXT, self.onTextCtrlFloat)
|
||||
lsz.Add(tc)
|
||||
tc.SetToolTip("Gear ratio. 1:1 if there is no gear.")
|
||||
self.tcRatioBottom = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((30, 30))
|
||||
sz.Add(lsz)
|
||||
sz.Add((30, 30))
|
||||
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Result:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Result:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size = (300, -1),
|
||||
style = wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResult = tc
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size=(300, -1), style=wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResult = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, "Resolution:", size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
sz.Add(lsz)
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self, wx.ID_ANY, "Resolution:", size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
st.SetFont(font)
|
||||
lsz.Add(st)
|
||||
lsz.Add((5, 5))
|
||||
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size = (300, -1),
|
||||
style = wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResolution = tc
|
||||
tc = wx.StaticText(self, wx.ID_ANY, "", size=(300, -1), style=wx.ALIGN_LEFT)
|
||||
tc.SetFont(font)
|
||||
lsz.Add(tc)
|
||||
self.tcResolution = tc
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add(lsz)
|
||||
|
||||
sz.Add((20, 20))
|
||||
sz.Add((20, 20))
|
||||
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for X", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForX, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForX = b
|
||||
bsz.Add((5, 5))
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for X", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForX, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForX = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Y", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForY, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForY = b
|
||||
bsz.Add((5, 5))
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Y", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForY, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForY = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Z", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForZ, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForZ = b
|
||||
bsz.Add((5, 5))
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for Z", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForZ, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForZ = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for E", size = BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForE, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForE = b
|
||||
b = wx.Button(self, wx.ID_ANY, "Use for E", size=BSIZESMALL)
|
||||
b.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onUseForE, b)
|
||||
bsz.Add(b)
|
||||
self.bUseForE = b
|
||||
|
||||
sz.Add(bsz, flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(bsz, flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
self.enableUseButtons(False)
|
||||
self.enableUseButtons(False)
|
||||
|
||||
self.SetSizer(hsz)
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
self.Fit()
|
||||
|
||||
self.calculate()
|
||||
self.calculate()
|
||||
|
||||
def calculate(self):
|
||||
self.tcResult.SetLabel("")
|
||||
self.tcResolution.SetLabel("")
|
||||
self.enableUseButtons(False)
|
||||
s = self.tcStep.GetSelection()
|
||||
sv = self.stepAngleValues[s]
|
||||
def calculate(self):
|
||||
self.tcResult.SetLabel("")
|
||||
self.tcResolution.SetLabel("")
|
||||
self.enableUseButtons(False)
|
||||
s = self.tcStep.GetSelection()
|
||||
sv = self.stepAngleValues[s]
|
||||
|
||||
try:
|
||||
sp = float(self.tcScrewPitch.GetValue())
|
||||
except:
|
||||
return
|
||||
try:
|
||||
sp = float(self.tcScrewPitch.GetValue())
|
||||
except:
|
||||
return
|
||||
|
||||
try:
|
||||
ratioA = float(self.tcRatioTop.GetValue())
|
||||
except:
|
||||
return
|
||||
try:
|
||||
ratioA = float(self.tcRatioTop.GetValue())
|
||||
except:
|
||||
return
|
||||
|
||||
try:
|
||||
ratioB = float(self.tcRatioBottom.GetValue())
|
||||
except:
|
||||
return
|
||||
try:
|
||||
ratioB = float(self.tcRatioBottom.GetValue())
|
||||
except:
|
||||
return
|
||||
|
||||
s = self.tcMicroStepping.GetSelection()
|
||||
msv = self.microSteppingValues[s]
|
||||
s = self.tcMicroStepping.GetSelection()
|
||||
msv = self.microSteppingValues[s]
|
||||
|
||||
ratio = ratioA / ratioB
|
||||
steps = sv * msv
|
||||
ratio = ratioA / ratioB
|
||||
steps = sv * msv
|
||||
|
||||
resultmm = steps / sp / ratio
|
||||
self.result = int(resultmm * 1000.0)
|
||||
resultmm = steps / sp / ratio
|
||||
self.result = int(resultmm * 1000.0)
|
||||
|
||||
self.tcResult.SetLabel("%d steps/m (%.3f steps/mm)" %
|
||||
(self.result, resultmm))
|
||||
self.tcResolution.SetLabel("%.3f micrometers" % (1.0 / resultmm * 1000.0))
|
||||
self.enableUseButtons(True)
|
||||
self.tcResult.SetLabel("%d steps/m (%.3f steps/mm)" % (self.result, resultmm))
|
||||
self.tcResolution.SetLabel("%.3f micrometers" % (1.0 / resultmm * 1000.0))
|
||||
self.enableUseButtons(True)
|
||||
|
||||
def enableUseButtons(self, flag):
|
||||
self.bUseForX.Enable(flag)
|
||||
self.bUseForY.Enable(flag)
|
||||
self.bUseForZ.Enable(flag)
|
||||
self.bUseForE.Enable(flag)
|
||||
def enableUseButtons(self, flag):
|
||||
self.bUseForX.Enable(flag)
|
||||
self.bUseForY.Enable(flag)
|
||||
self.bUseForZ.Enable(flag)
|
||||
self.bUseForE.Enable(flag)
|
||||
|
||||
def onUseForX(self, evt):
|
||||
self.use('STEPS_PER_M_X', self.result)
|
||||
def onUseForX(self, evt):
|
||||
self.use("STEPS_PER_M_X", self.result)
|
||||
|
||||
def onUseForY(self, evt):
|
||||
self.use('STEPS_PER_M_Y', self.result)
|
||||
def onUseForY(self, evt):
|
||||
self.use("STEPS_PER_M_Y", self.result)
|
||||
|
||||
def onUseForZ(self, evt):
|
||||
self.use('STEPS_PER_M_Z', self.result)
|
||||
def onUseForZ(self, evt):
|
||||
self.use("STEPS_PER_M_Z", self.result)
|
||||
|
||||
def onUseForE(self, evt):
|
||||
self.use('STEPS_PER_M_E', self.result)
|
||||
def onUseForE(self, evt):
|
||||
self.use("STEPS_PER_M_E", self.result)
|
||||
|
||||
def onPresetChoice(self, evt):
|
||||
s = self.tcPresets.GetSelection()
|
||||
sv = self.screwPresetValues[s]
|
||||
if sv < 0:
|
||||
return
|
||||
def onPresetChoice(self, evt):
|
||||
s = self.tcPresets.GetSelection()
|
||||
sv = self.screwPresetValues[s]
|
||||
if sv < 0:
|
||||
return
|
||||
|
||||
s = "%f" % sv
|
||||
s = s.rstrip("0")
|
||||
if s[-1] == ".":
|
||||
s += "0"
|
||||
self.tcScrewPitch.SetValue(s)
|
||||
s = "%f" % sv
|
||||
s = s.rstrip("0")
|
||||
if s[-1] == ".":
|
||||
s += "0"
|
||||
self.tcScrewPitch.SetValue(s)
|
||||
|
||||
def onChoice(self, evt):
|
||||
self.calculate()
|
||||
def onChoice(self, evt):
|
||||
self.calculate()
|
||||
|
||||
def onTextCtrlFloat(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
def onTextCtrlFloat(self, evt):
|
||||
tc = evt.GetEventObject()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = False
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
self.calculate()
|
||||
evt.Skip()
|
||||
|
||||
def onExit(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
def onExit(self, evt):
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
|
|
|||
|
|
@ -1,62 +1,65 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
|
||||
|
||||
class CommunicationsPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
self.defaultBaud = '115200'
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
self.defaultBaud = "115200"
|
||||
|
||||
self.bauds = ['19200', '38400', '57600', '115200', '230400', '250000']
|
||||
self.bauds = ["19200", "38400", "57600", "115200", "230400", "250000"]
|
||||
|
||||
self.labels = {'XONXOFF': "XON/XOFF Flow Control", 'BAUD': "Baud Rate:",
|
||||
'USB_SERIAL': "USB Serial"}
|
||||
self.labels = {
|
||||
"XONXOFF": "XON/XOFF Flow Control",
|
||||
"BAUD": "Baud Rate:",
|
||||
"USB_SERIAL": "USB Serial",
|
||||
}
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos = (0, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos=(0, 0))
|
||||
|
||||
k = 'USB_SERIAL'
|
||||
cb = self.addCheckBox(k, self.onUSBCheckBox)
|
||||
sz.Add(cb, pos = (1, 1))
|
||||
k = "USB_SERIAL"
|
||||
cb = self.addCheckBox(k, self.onUSBCheckBox)
|
||||
sz.Add(cb, pos=(1, 1))
|
||||
|
||||
ch = self.addChoice('BAUD', self.bauds, self.bauds.index(self.defaultBaud),
|
||||
80, self.onChoice)
|
||||
sz.Add(ch, pos = (1, 3))
|
||||
ch = self.addChoice(
|
||||
"BAUD", self.bauds, self.bauds.index(self.defaultBaud), 80, self.onChoice
|
||||
)
|
||||
sz.Add(ch, pos=(1, 3))
|
||||
|
||||
cb = self.addCheckBox('XONXOFF', self.onCheckBox)
|
||||
sz.Add(cb, pos = (3, 3))
|
||||
cb = self.addCheckBox("XONXOFF", self.onCheckBox)
|
||||
sz.Add(cb, pos=(3, 3))
|
||||
|
||||
sz.Add((100, 10), pos = (2, 2))
|
||||
sz.Add((100, 10), pos=(2, 2))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def onUSBCheckBox(self, evt):
|
||||
self.assertModified(True)
|
||||
f = not self.checkBoxes['USB_SERIAL'].IsChecked()
|
||||
self.checkBoxes['XONXOFF'].Enable(f)
|
||||
self.choices['BAUD'].Enable(f)
|
||||
evt.Skip()
|
||||
def onUSBCheckBox(self, evt):
|
||||
self.assertModified(True)
|
||||
f = not self.checkBoxes["USB_SERIAL"].IsChecked()
|
||||
self.checkBoxes["XONXOFF"].Enable(f)
|
||||
self.choices["BAUD"].Enable(f)
|
||||
evt.Skip()
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
|
||||
k = 'BAUD'
|
||||
self.setChoice(k, cfgValues, self.defaultBaud)
|
||||
k = "BAUD"
|
||||
self.setChoice(k, cfgValues, self.defaultBaud)
|
||||
|
||||
if self.checkBoxes['USB_SERIAL'].IsChecked():
|
||||
self.checkBoxes['XONXOFF'].Enable(False)
|
||||
self.choices['BAUD'].Enable(False)
|
||||
if self.checkBoxes["USB_SERIAL"].IsChecked():
|
||||
self.checkBoxes["XONXOFF"].Enable(False)
|
||||
self.choices["BAUD"].Enable(False)
|
||||
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
|
||||
if result['USB_SERIAL']:
|
||||
result['BAUD'] = result['BAUD'][0], False
|
||||
result['XONXOFF'] = False
|
||||
if result["USB_SERIAL"]:
|
||||
result["BAUD"] = result["BAUD"][0], False
|
||||
result["XONXOFF"] = False
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,53 +1,51 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
|
||||
|
||||
class CpuPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
|
||||
self.labels = {'F_CPU': "CPU Clock Rate:", 'CPU': "Processor Type:"}
|
||||
self.clocks = []
|
||||
self.processors = []
|
||||
self.labels = {"F_CPU": "CPU Clock Rate:", "CPU": "Processor Type:"}
|
||||
self.clocks = []
|
||||
self.processors = []
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos = (0, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos=(0, 0))
|
||||
|
||||
k = 'F_CPU'
|
||||
ch = self.addChoice(k, self.clocks, 0, 100, self.onChoice, size = (140, -1))
|
||||
sz.Add(ch, pos = (1, 1))
|
||||
sz.Add((100, 10), pos = (1, 2))
|
||||
k = "F_CPU"
|
||||
ch = self.addChoice(k, self.clocks, 0, 100, self.onChoice, size=(140, -1))
|
||||
sz.Add(ch, pos=(1, 1))
|
||||
sz.Add((100, 10), pos=(1, 2))
|
||||
|
||||
k = 'CPU'
|
||||
ch = self.addChoice(k, self.processors, 0, 100, self.onChoice,
|
||||
size = (140, -1))
|
||||
sz.Add(ch, pos = (1, 3))
|
||||
k = "CPU"
|
||||
ch = self.addChoice(k, self.processors, 0, 100, self.onChoice, size=(140, -1))
|
||||
sz.Add(ch, pos=(1, 3))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def setCandidateProcessors(self, plist):
|
||||
k = 'CPU'
|
||||
self.choices[k].Clear()
|
||||
for p in plist:
|
||||
self.choices[k].Append(p)
|
||||
self.processors = plist
|
||||
def setCandidateProcessors(self, plist):
|
||||
k = "CPU"
|
||||
self.choices[k].Clear()
|
||||
for p in plist:
|
||||
self.choices[k].Append(p)
|
||||
self.processors = plist
|
||||
|
||||
def setCandidateClocks(self, clist):
|
||||
k = 'F_CPU'
|
||||
self.choices[k].Clear()
|
||||
for c in clist:
|
||||
self.choices[k].Append(c)
|
||||
self.clocks = clist
|
||||
def setCandidateClocks(self, clist):
|
||||
k = "F_CPU"
|
||||
self.choices[k].Clear()
|
||||
for c in clist:
|
||||
self.choices[k].Append(c)
|
||||
self.clocks = clist
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
|
||||
if len(self.clocks) > 0:
|
||||
self.setChoice('F_CPU', cfgValues, self.clocks[0])
|
||||
if len(self.processors) > 0:
|
||||
self.setChoice('CPU', cfgValues, self.processors[0])
|
||||
if len(self.clocks) > 0:
|
||||
self.setChoice("F_CPU", cfgValues, self.clocks[0])
|
||||
if len(self.processors) > 0:
|
||||
self.setChoice("CPU", cfgValues, self.processors[0])
|
||||
|
|
|
|||
|
|
@ -1,47 +1,61 @@
|
|||
|
||||
import re
|
||||
from sys import platform
|
||||
|
||||
|
||||
supportedCPUs = ['ATmega168', 'ATmega328P', 'ATmega644', 'ATmega644P',
|
||||
'ATmega644PA', 'ATmega1280', 'ATmega1284', 'ATmega1284P',
|
||||
'ATmega2560', 'AT90USB1286']
|
||||
supportedCPUs = [
|
||||
"ATmega168",
|
||||
"ATmega328P",
|
||||
"ATmega644",
|
||||
"ATmega644P",
|
||||
"ATmega644PA",
|
||||
"ATmega1280",
|
||||
"ATmega1284",
|
||||
"ATmega1284P",
|
||||
"ATmega2560",
|
||||
"AT90USB1286",
|
||||
]
|
||||
|
||||
# Note: this is a kludge and works for ATmegas, only. Smaller ATmegas have a
|
||||
# lot fewer pins, so this list provides a lot of clutter for them. ARMs
|
||||
# have entirely different names. The right way would be to fetch pin
|
||||
# names from the compiler environment and/or header files.
|
||||
pinNames = ["AIO%d" % x for x in range(16)] + \
|
||||
["DIO%d" % x for x in range(64)] + \
|
||||
["P%c%d" % (c, x) for c in range(ord('A'), ord('L') + 1) \
|
||||
for x in range(8)]
|
||||
pinNames = (
|
||||
["AIO%d" % x for x in range(16)]
|
||||
+ ["DIO%d" % x for x in range(64)]
|
||||
+ ["P%c%d" % (c, x) for c in range(ord("A"), ord("L") + 1) for x in range(8)]
|
||||
)
|
||||
|
||||
sensorTypes = {'MAX6675': "TT_MAX6675", 'Thermistor': "TT_THERMISTOR",
|
||||
'AD595': "TT_AD595", 'PT100': "TT_PT100",
|
||||
'Intercom': "TT_INTERCOM", 'MCP3008': "TT_MCP3008"}
|
||||
sensorTypes = {
|
||||
"MAX6675": "TT_MAX6675",
|
||||
"Thermistor": "TT_THERMISTOR",
|
||||
"AD595": "TT_AD595",
|
||||
"PT100": "TT_PT100",
|
||||
"Intercom": "TT_INTERCOM",
|
||||
"MCP3008": "TT_MCP3008",
|
||||
}
|
||||
|
||||
BSIZE = (100, 60)
|
||||
BSIZESMALL = (90, 30)
|
||||
|
||||
|
||||
if platform.startswith("win"):
|
||||
offsetTcLabel = 4
|
||||
offsetChLabel = 4
|
||||
offsetTcLabel = 4
|
||||
offsetChLabel = 4
|
||||
else:
|
||||
offsetTcLabel = 6
|
||||
offsetChLabel = 8
|
||||
offsetTcLabel = 6
|
||||
offsetChLabel = 8
|
||||
|
||||
TYPE_GENERAL = 0
|
||||
TYPE_FLOAT = 1
|
||||
|
||||
reDefQSm = re.compile("\s*#define\s+(\S+)\s+(.*)")
|
||||
reDefQSm2 = re.compile("\s*(\"[^\"]*\")")
|
||||
reDefQSm2 = re.compile('\s*("[^"]*")')
|
||||
|
||||
reInclude = re.compile("^\s*#include\s+\"([^\"]*)")
|
||||
reInclude = re.compile('^\s*#include\s+"([^"]*)')
|
||||
reFloatAttr = re.compile("/\*\s*float\s*\*/")
|
||||
reDefine = re.compile("\s*#define\s+(\w+)\s+(\S+)")
|
||||
reDefineBL = re.compile("^\s*#define\s+(\w+)\s+(\S+)")
|
||||
reDefQS = re.compile("\s*#define\s+(\w+)\s+(\"[^\"]*\")")
|
||||
reDefQS = re.compile('\s*#define\s+(\w+)\s+("[^"]*")')
|
||||
reDefTS = re.compile("\s*(DEFINE_TEMP_SENSOR\\([^)]*\\))")
|
||||
reDefHT = re.compile("\s*(DEFINE_HEATER\\([^)]*\\))")
|
||||
reDefTT = re.compile("^\s*//\s*TEMP_TABLE\s+(\S+)\s+(\\(.*\\))")
|
||||
|
|
@ -64,16 +78,22 @@ reSensor = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
|
|||
# reHeater3 and reHeater4 deprecated, for compatibility with old config files only.
|
||||
reHeater3 = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
|
||||
reHeater4 = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
|
||||
reHeater5 = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
|
||||
reTempTable4 = re.compile(".*\\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*\\)")
|
||||
reTempTable7 = re.compile(".*\\(\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*\\)")
|
||||
reHeater5 = re.compile(
|
||||
".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)"
|
||||
)
|
||||
reTempTable4 = re.compile(
|
||||
".*\\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*\\)"
|
||||
)
|
||||
reTempTable7 = re.compile(
|
||||
".*\\(\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*,\s*(\d*.?\d*)\s*,\s*(\d+)\s*\\)"
|
||||
)
|
||||
|
||||
reInteger = re.compile("^\d+U?L?$")
|
||||
reFloat = re.compile("^\d+(\.\d*)?$")
|
||||
|
||||
defineValueFormat = "#define %-24s %s\n"
|
||||
defineBoolFormat = "#define %s\n"
|
||||
defineHeaterFormat = "#define HEATER_%s HEATER_%s\n"
|
||||
defineValueFormat = "#define %-24s %s\n"
|
||||
defineBoolFormat = "#define %s\n"
|
||||
defineHeaterFormat = "#define HEATER_%s HEATER_%s\n"
|
||||
defineDCExtruderFormat = "#define %-24s HEATER_%s\n"
|
||||
|
||||
reHomingOpts = re.compile("^\s*//\s*#define\s+HOMING_OPT\s+(\w+)")
|
||||
|
|
|
|||
|
|
@ -5,64 +5,66 @@ import os.path
|
|||
|
||||
|
||||
class Decoration(object):
|
||||
def __new__(type, *args):
|
||||
# Make it a Singleton.
|
||||
if not '_the_instance' in type.__dict__:
|
||||
type._the_instance = object.__new__(type)
|
||||
def __new__(type, *args):
|
||||
# Make it a Singleton.
|
||||
if not "_the_instance" in type.__dict__:
|
||||
type._the_instance = object.__new__(type)
|
||||
|
||||
return type._the_instance
|
||||
return type._the_instance
|
||||
|
||||
def __init__(self):
|
||||
if not '_ready' in dir(self):
|
||||
self._ready = True
|
||||
# It's a Singleton. Initialisations go in here.
|
||||
self.backPic = None
|
||||
self.backPicOffset = (0, -25)
|
||||
def __init__(self):
|
||||
if not "_ready" in dir(self):
|
||||
self._ready = True
|
||||
# It's a Singleton. Initialisations go in here.
|
||||
self.backPic = None
|
||||
self.backPicOffset = (0, -25)
|
||||
|
||||
if not self.backPic:
|
||||
backPicPath = os.path.join("configtool", "background.png")
|
||||
if os.path.exists(backPicPath):
|
||||
backPic = wx.Bitmap(backPicPath)
|
||||
if backPic.IsOk():
|
||||
self.backPic = backPic
|
||||
else:
|
||||
print("Background picture %s damaged." % backPicPath)
|
||||
else:
|
||||
print("Background picture %s doesn't exist." % backPicPath)
|
||||
if not self.backPic:
|
||||
backPicPath = os.path.join("configtool", "background.png")
|
||||
if os.path.exists(backPicPath):
|
||||
backPic = wx.Bitmap(backPicPath)
|
||||
if backPic.IsOk():
|
||||
self.backPic = backPic
|
||||
else:
|
||||
print("Background picture %s damaged." % backPicPath)
|
||||
else:
|
||||
print("Background picture %s doesn't exist." % backPicPath)
|
||||
|
||||
def getBackgroundColour(self):
|
||||
return wx.Colour(237, 237, 237)
|
||||
def getBackgroundColour(self):
|
||||
return wx.Colour(237, 237, 237)
|
||||
|
||||
# On wxFrames, bind this to wx.EVT_ERASE_BACKGROUND
|
||||
# On wxPanels, bind this to wx.EVT_PAINT
|
||||
def onPaintBackground(self, evt):
|
||||
client = evt.GetEventObject()
|
||||
topLevel = client.GetTopLevelParent()
|
||||
# On wxFrames, bind this to wx.EVT_ERASE_BACKGROUND
|
||||
# On wxPanels, bind this to wx.EVT_PAINT
|
||||
def onPaintBackground(self, evt):
|
||||
client = evt.GetEventObject()
|
||||
topLevel = client.GetTopLevelParent()
|
||||
|
||||
try:
|
||||
dc = evt.GetDC()
|
||||
except:
|
||||
dc = wx.PaintDC(client)
|
||||
try:
|
||||
dc = evt.GetDC()
|
||||
except:
|
||||
dc = wx.PaintDC(client)
|
||||
|
||||
if dc:
|
||||
# Now draw the background picture with pseudo-transparency. This is,
|
||||
# each background is drawn with the same picture, without transparency,
|
||||
# and offsetted just right to have all backgrounds in the same position
|
||||
# relative to the *toplevel* window, not relative to the current
|
||||
# subwindow as usual.
|
||||
if dc:
|
||||
# Now draw the background picture with pseudo-transparency. This is,
|
||||
# each background is drawn with the same picture, without transparency,
|
||||
# and offsetted just right to have all backgrounds in the same position
|
||||
# relative to the *toplevel* window, not relative to the current
|
||||
# subwindow as usual.
|
||||
|
||||
# Align bottom right.
|
||||
offX, offY = topLevel.GetClientSize() - self.backPic.GetSize() + \
|
||||
self.backPicOffset
|
||||
# Align bottom right.
|
||||
offX, offY = (
|
||||
topLevel.GetClientSize() - self.backPic.GetSize() + self.backPicOffset
|
||||
)
|
||||
|
||||
if client != topLevel:
|
||||
# Note: trying to figure this additional offset via various
|
||||
# .GetScreenPosition() or .GetPosition() or whatever is hopeless.
|
||||
# Of many many tries only this worked on Linux.
|
||||
offX, offY = \
|
||||
client.ScreenToClient(topLevel.ClientToScreen((offX, offY)))
|
||||
if client != topLevel:
|
||||
# Note: trying to figure this additional offset via various
|
||||
# .GetScreenPosition() or .GetPosition() or whatever is hopeless.
|
||||
# Of many many tries only this worked on Linux.
|
||||
offX, offY = client.ScreenToClient(
|
||||
topLevel.ClientToScreen((offX, offY))
|
||||
)
|
||||
|
||||
if self.backPic:
|
||||
dc.DrawBitmap(self.backPic, offX, offY)
|
||||
if self.backPic:
|
||||
dc.DrawBitmap(self.backPic, offX, offY)
|
||||
|
||||
evt.Skip()
|
||||
evt.Skip()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
# coding=utf-8
|
||||
|
||||
import wx
|
||||
|
|
@ -6,76 +5,86 @@ from configtool.page import Page
|
|||
|
||||
|
||||
class DisplayPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
|
||||
self.labels = {'DISPLAY_BUS': "Display Bus:",
|
||||
'DISPLAY_TYPE': "Display Type:",
|
||||
'DISPLAY_BUS_4BIT': "Direct with 4 pins",
|
||||
'DISPLAY_BUS_8BIT': "Direct with 8 pins",
|
||||
'DISPLAY_BUS_I2C': "I²C ( = TWI)",
|
||||
'DISPLAY_BUS_SPI': "SPI",
|
||||
'DISPLAY_TYPE_SSD1306': "SSD1306 O-LED, 128x32 pixels",
|
||||
'DISPLAY_TYPE_HD44780': "HD44780 or 1602A, 16x2 characters",
|
||||
'DISPLAY_RS_PIN': "RS pin",
|
||||
'DISPLAY_RW_PIN': "R/W pin",
|
||||
'DISPLAY_E_PIN': "E pin",
|
||||
'DISPLAY_D4_PIN': "D4 pin",
|
||||
'DISPLAY_D5_PIN': "D5 pin",
|
||||
'DISPLAY_D6_PIN': "D6 pin",
|
||||
'DISPLAY_D7_PIN': "D7 pin"}
|
||||
self.labels = {
|
||||
"DISPLAY_BUS": "Display Bus:",
|
||||
"DISPLAY_TYPE": "Display Type:",
|
||||
"DISPLAY_BUS_4BIT": "Direct with 4 pins",
|
||||
"DISPLAY_BUS_8BIT": "Direct with 8 pins",
|
||||
"DISPLAY_BUS_I2C": "I²C ( = TWI)",
|
||||
"DISPLAY_BUS_SPI": "SPI",
|
||||
"DISPLAY_TYPE_SSD1306": "SSD1306 O-LED, 128x32 pixels",
|
||||
"DISPLAY_TYPE_HD44780": "HD44780 or 1602A, 16x2 characters",
|
||||
"DISPLAY_RS_PIN": "RS pin",
|
||||
"DISPLAY_RW_PIN": "R/W pin",
|
||||
"DISPLAY_E_PIN": "E pin",
|
||||
"DISPLAY_D4_PIN": "D4 pin",
|
||||
"DISPLAY_D5_PIN": "D5 pin",
|
||||
"DISPLAY_D6_PIN": "D6 pin",
|
||||
"DISPLAY_D7_PIN": "D7 pin",
|
||||
}
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos = (0, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos=(0, 0))
|
||||
|
||||
ch = self.addBoolChoice('DISPLAY_BUS', True, 100, self.onBusChoice,
|
||||
size = (160, -1))
|
||||
sz.Add(ch, pos = (1, 1))
|
||||
sz.Add((100, 10), pos = (1, 2))
|
||||
ch = self.addBoolChoice(
|
||||
"DISPLAY_BUS", True, 100, self.onBusChoice, size=(160, -1)
|
||||
)
|
||||
sz.Add(ch, pos=(1, 1))
|
||||
sz.Add((100, 10), pos=(1, 2))
|
||||
|
||||
ch = self.addBoolChoice('DISPLAY_TYPE', False, 100, self.onChoice,
|
||||
size = (240, -1))
|
||||
sz.Add(ch, pos = (1, 3))
|
||||
ch = self.addBoolChoice(
|
||||
"DISPLAY_TYPE", False, 100, self.onChoice, size=(240, -1)
|
||||
)
|
||||
sz.Add(ch, pos=(1, 3))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Direct 4-bit Bus Pins:")
|
||||
b.SetFont(font)
|
||||
self.pinbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
self.pinbox.Add((5, 5))
|
||||
for k in ('DISPLAY_RS_PIN', 'DISPLAY_RW_PIN', 'DISPLAY_E_PIN',
|
||||
'DISPLAY_D4_PIN', 'DISPLAY_D5_PIN', 'DISPLAY_D6_PIN',
|
||||
'DISPLAY_D7_PIN'):
|
||||
tc = self.addPinChoice(k, 200)
|
||||
self.pinbox.Add(tc)
|
||||
self.pinbox.Add((5, 5))
|
||||
sz.Add(self.pinbox, pos = (3, 1))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Direct 4-bit Bus Pins:")
|
||||
b.SetFont(font)
|
||||
self.pinbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
self.pinbox.Add((5, 5))
|
||||
for k in (
|
||||
"DISPLAY_RS_PIN",
|
||||
"DISPLAY_RW_PIN",
|
||||
"DISPLAY_E_PIN",
|
||||
"DISPLAY_D4_PIN",
|
||||
"DISPLAY_D5_PIN",
|
||||
"DISPLAY_D6_PIN",
|
||||
"DISPLAY_D7_PIN",
|
||||
):
|
||||
tc = self.addPinChoice(k, 200)
|
||||
self.pinbox.Add(tc)
|
||||
self.pinbox.Add((5, 5))
|
||||
sz.Add(self.pinbox, pos=(3, 1))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def onBusChoice(self, evt):
|
||||
choice = self.boolChoices['DISPLAY_BUS']
|
||||
if choice.GetClientData(choice.GetSelection()):
|
||||
self.boolChoices['DISPLAY_TYPE'].Enable(True)
|
||||
else:
|
||||
self.boolChoices['DISPLAY_TYPE'].Enable(False)
|
||||
self.adjustPinVisibility()
|
||||
def onBusChoice(self, evt):
|
||||
choice = self.boolChoices["DISPLAY_BUS"]
|
||||
if choice.GetClientData(choice.GetSelection()):
|
||||
self.boolChoices["DISPLAY_TYPE"].Enable(True)
|
||||
else:
|
||||
self.boolChoices["DISPLAY_TYPE"].Enable(False)
|
||||
self.adjustPinVisibility()
|
||||
|
||||
Page.onChoice(self, evt)
|
||||
Page.onChoice(self, evt)
|
||||
|
||||
def adjustPinVisibility(self):
|
||||
visible = False
|
||||
def adjustPinVisibility(self):
|
||||
visible = False
|
||||
|
||||
choice = self.boolChoices['DISPLAY_BUS']
|
||||
if choice.GetSelection() >= 0:
|
||||
selection = choice.GetClientData(choice.GetSelection())
|
||||
if selection == 'DISPLAY_BUS_4BIT':
|
||||
visible = True
|
||||
choice = self.boolChoices["DISPLAY_BUS"]
|
||||
if choice.GetSelection() >= 0:
|
||||
selection = choice.GetClientData(choice.GetSelection())
|
||||
if selection == "DISPLAY_BUS_4BIT":
|
||||
visible = True
|
||||
|
||||
self.pinbox.ShowItems(visible)
|
||||
self.pinbox.ShowItems(visible)
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
self.adjustPinVisibility()
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
self.adjustPinVisibility()
|
||||
|
|
|
|||
1219
configtool/gui.py
1219
configtool/gui.py
File diff suppressed because it is too large
Load Diff
|
|
@ -1,87 +1,89 @@
|
|||
|
||||
import wx
|
||||
|
||||
|
||||
class HeaterList(wx.ListCtrl):
|
||||
def __init__(self, parent, font):
|
||||
self.parent = parent
|
||||
self.currentItem = None
|
||||
wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
|
||||
size = (95 + 75 + 55 + 55 + 95 + 4, 100),
|
||||
style = wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES |
|
||||
wx.LC_VRULES)
|
||||
self.SetFont(font)
|
||||
def __init__(self, parent, font):
|
||||
self.parent = parent
|
||||
self.currentItem = None
|
||||
wx.ListCtrl.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
size=(95 + 75 + 55 + 55 + 95 + 4, 100),
|
||||
style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES | wx.LC_VRULES,
|
||||
)
|
||||
self.SetFont(font)
|
||||
|
||||
self.valid = []
|
||||
self.heaterList = []
|
||||
self.valid = []
|
||||
self.heaterList = []
|
||||
|
||||
self.InsertColumn(0, "Name")
|
||||
self.InsertColumn(1, "Pin")
|
||||
self.InsertColumn(2, "Invert")
|
||||
self.InsertColumn(3, "PWM")
|
||||
self.InsertColumn(4, "Max PWM [%]")
|
||||
self.SetColumnWidth(0, 95)
|
||||
self.SetColumnWidth(1, 75)
|
||||
self.SetColumnWidth(2, 55)
|
||||
self.SetColumnWidth(3, 55)
|
||||
self.SetColumnWidth(4, 95)
|
||||
self.InsertColumn(0, "Name")
|
||||
self.InsertColumn(1, "Pin")
|
||||
self.InsertColumn(2, "Invert")
|
||||
self.InsertColumn(3, "PWM")
|
||||
self.InsertColumn(4, "Max PWM [%]")
|
||||
self.SetColumnWidth(0, 95)
|
||||
self.SetColumnWidth(1, 75)
|
||||
self.SetColumnWidth(2, 55)
|
||||
self.SetColumnWidth(3, 55)
|
||||
self.SetColumnWidth(4, 95)
|
||||
|
||||
self.SetItemCount(0)
|
||||
self.SetItemCount(0)
|
||||
|
||||
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
|
||||
|
||||
def updateList(self, heaterList):
|
||||
self.heaterList = heaterList
|
||||
self.valid = [True] * len(heaterList)
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
i = self.GetFirstSelected()
|
||||
while i != -1:
|
||||
self.Select(i, False)
|
||||
i = self.GetFirstSelected()
|
||||
def updateList(self, heaterList):
|
||||
self.heaterList = heaterList
|
||||
self.valid = [True] * len(heaterList)
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
i = self.GetFirstSelected()
|
||||
while i != -1:
|
||||
self.Select(i, False)
|
||||
i = self.GetFirstSelected()
|
||||
|
||||
self.SetItemCount(len(heaterList))
|
||||
self.SetItemCount(len(heaterList))
|
||||
|
||||
def setRowValidity(self, i, flag = False):
|
||||
if i < 0 or i >= len(self.heaterList):
|
||||
return
|
||||
def setRowValidity(self, i, flag=False):
|
||||
if i < 0 or i >= len(self.heaterList):
|
||||
return
|
||||
|
||||
self.valid[i] = flag
|
||||
self.Refresh()
|
||||
self.valid[i] = flag
|
||||
self.Refresh()
|
||||
|
||||
def setTableValidity(self, flag = False):
|
||||
for i in range(len(self.heaterList)):
|
||||
self.setRowValidity(i, flag)
|
||||
def setTableValidity(self, flag=False):
|
||||
for i in range(len(self.heaterList)):
|
||||
self.setRowValidity(i, flag)
|
||||
|
||||
def OnItemSelected(self, event):
|
||||
self.currentItem = event.m_itemIndex
|
||||
self.parent.setItemSelected(self.currentItem)
|
||||
def OnItemSelected(self, event):
|
||||
self.currentItem = event.m_itemIndex
|
||||
self.parent.setItemSelected(self.currentItem)
|
||||
|
||||
def OnItemDeselected(self, event):
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
def OnItemDeselected(self, event):
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
|
||||
def getColumnText(self, index, col):
|
||||
item = self.GetItem(index, col)
|
||||
return item.GetText()
|
||||
def getColumnText(self, index, col):
|
||||
item = self.GetItem(index, col)
|
||||
return item.GetText()
|
||||
|
||||
def OnGetItemText(self, item, col):
|
||||
if item < 0 or item >= len(self.heaterList):
|
||||
return "Error - no heaters."
|
||||
def OnGetItemText(self, item, col):
|
||||
if item < 0 or item >= len(self.heaterList):
|
||||
return "Error - no heaters."
|
||||
|
||||
s = self.heaterList[item]
|
||||
s = self.heaterList[item]
|
||||
|
||||
if col == 0:
|
||||
return s[0]
|
||||
elif col == 1:
|
||||
return s[1]
|
||||
elif col == 2:
|
||||
if s[2] == "1":
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
elif col == 3:
|
||||
return s[3]
|
||||
elif col == 4:
|
||||
return s[4]
|
||||
if col == 0:
|
||||
return s[0]
|
||||
elif col == 1:
|
||||
return s[1]
|
||||
elif col == 2:
|
||||
if s[2] == "1":
|
||||
return "True"
|
||||
else:
|
||||
return "False"
|
||||
elif col == 3:
|
||||
return s[3]
|
||||
elif col == 4:
|
||||
return s[4]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
from configtool.data import pinNames, BSIZESMALL
|
||||
|
|
@ -7,183 +6,191 @@ from configtool.addheaterdlg import AddHeaterDlg
|
|||
|
||||
|
||||
class HeatersPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.font = font
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.font = font
|
||||
self.id = idPg
|
||||
|
||||
self.labels = {'FORCE_SOFTWARE_PWM':"Force software PWM"}
|
||||
self.labels = {"FORCE_SOFTWARE_PWM": "Force software PWM"}
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((30, 30), pos = (0, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((30, 30), pos=(0, 0))
|
||||
|
||||
self.heaters = []
|
||||
self.validPins = pinNames
|
||||
self.heaters = []
|
||||
self.validPins = pinNames
|
||||
|
||||
self.lb = HeaterList(self, font)
|
||||
sz.Add(self.lb, pos = (1, 1))
|
||||
sz.Add((20, 20), pos = (1, 2))
|
||||
self.lb = HeaterList(self, font)
|
||||
sz.Add(self.lb, pos=(1, 1))
|
||||
sz.Add((20, 20), pos=(1, 2))
|
||||
|
||||
k = 'FORCE_SOFTWARE_PWM'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
k = "FORCE_SOFTWARE_PWM"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
|
||||
sz.Add(cb, pos = (2, 1))
|
||||
sz.Add((20, 20), pos = (2, 2))
|
||||
sz.Add(cb, pos=(2, 1))
|
||||
sz.Add((20, 20), pos=(2, 2))
|
||||
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size = BSIZESMALL)
|
||||
self.bAdd.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bAdd.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
|
||||
self.bAdd.SetToolTip("Add a heater to the configuration.")
|
||||
bsz.Add(self.bAdd)
|
||||
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size=BSIZESMALL)
|
||||
self.bAdd.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bAdd.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
|
||||
self.bAdd.SetToolTip("Add a heater to the configuration.")
|
||||
bsz.Add(self.bAdd)
|
||||
|
||||
bsz.Add((10, 10))
|
||||
bsz.Add((10, 10))
|
||||
|
||||
self.bModify = wx.Button(self, wx.ID_ANY, "Modify", size = BSIZESMALL)
|
||||
self.bModify.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bModify.SetFont(font)
|
||||
self.bModify.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doModify, self.bModify)
|
||||
self.bModify.SetToolTip("Modify the selected heater.")
|
||||
bsz.Add(self.bModify)
|
||||
self.bModify = wx.Button(self, wx.ID_ANY, "Modify", size=BSIZESMALL)
|
||||
self.bModify.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bModify.SetFont(font)
|
||||
self.bModify.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doModify, self.bModify)
|
||||
self.bModify.SetToolTip("Modify the selected heater.")
|
||||
bsz.Add(self.bModify)
|
||||
|
||||
bsz.Add((10, 10))
|
||||
bsz.Add((10, 10))
|
||||
|
||||
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size = BSIZESMALL)
|
||||
self.bDelete.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bDelete.SetFont(font)
|
||||
self.bDelete.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
|
||||
self.bDelete.SetToolTip("Remove the selected heater from the "
|
||||
"configuration.")
|
||||
bsz.Add(self.bDelete)
|
||||
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size=BSIZESMALL)
|
||||
self.bDelete.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bDelete.SetFont(font)
|
||||
self.bDelete.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
|
||||
self.bDelete.SetToolTip("Remove the selected heater from the " "configuration.")
|
||||
bsz.Add(self.bDelete)
|
||||
|
||||
sz.Add(bsz, pos = (1, 3))
|
||||
sz.Add(bsz, pos=(1, 3))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def enableAll(self, flag = True):
|
||||
self.bAdd.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
def enableAll(self, flag=True):
|
||||
self.bAdd.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
|
||||
def setItemSelected(self, n):
|
||||
self.selection = n
|
||||
if n is None:
|
||||
self.bDelete.Enable(False)
|
||||
self.bModify.Enable(False)
|
||||
else:
|
||||
self.bDelete.Enable(True)
|
||||
self.bModify.Enable(True)
|
||||
def setItemSelected(self, n):
|
||||
self.selection = n
|
||||
if n is None:
|
||||
self.bDelete.Enable(False)
|
||||
self.bModify.Enable(False)
|
||||
else:
|
||||
self.bDelete.Enable(True)
|
||||
self.bModify.Enable(True)
|
||||
|
||||
def getFreePins(self):
|
||||
freePins = [] + self.validPins
|
||||
usedPins = []
|
||||
for s in self.heaters:
|
||||
usedPins.append(s[1])
|
||||
def getFreePins(self):
|
||||
freePins = [] + self.validPins
|
||||
usedPins = []
|
||||
for s in self.heaters:
|
||||
usedPins.append(s[1])
|
||||
|
||||
for p in usedPins:
|
||||
if p in freePins:
|
||||
freePins.remove(p)
|
||||
for p in usedPins:
|
||||
if p in freePins:
|
||||
freePins.remove(p)
|
||||
|
||||
return freePins
|
||||
return freePins
|
||||
|
||||
def doAdd(self, evt):
|
||||
nm = []
|
||||
for s in self.heaters:
|
||||
nm.append(s[0])
|
||||
def doAdd(self, evt):
|
||||
nm = []
|
||||
for s in self.heaters:
|
||||
nm.append(s[0])
|
||||
|
||||
dlg = AddHeaterDlg(self, nm, self.getFreePins(), self.font)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
ht = dlg.getValues()
|
||||
dlg = AddHeaterDlg(self, nm, self.getFreePins(), self.font)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
ht = dlg.getValues()
|
||||
|
||||
dlg.Destroy()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
|
||||
self.heaters.append(ht)
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
self.heaters.append(ht)
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
|
||||
def doModify(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
def doModify(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
|
||||
nm = []
|
||||
for s in self.heaters:
|
||||
nm.append(s[0])
|
||||
nm = []
|
||||
for s in self.heaters:
|
||||
nm.append(s[0])
|
||||
|
||||
h = self.heaters[self.selection]
|
||||
h = self.heaters[self.selection]
|
||||
|
||||
dlg = AddHeaterDlg(self, nm, [h[1]] + self.getFreePins(), self.font,
|
||||
name = h[0], pin = h[1], invert = h[2], pwm = h[3], max_pwm = h[4])
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
ht = dlg.getValues()
|
||||
dlg = AddHeaterDlg(
|
||||
self,
|
||||
nm,
|
||||
[h[1]] + self.getFreePins(),
|
||||
self.font,
|
||||
name=h[0],
|
||||
pin=h[1],
|
||||
invert=h[2],
|
||||
pwm=h[3],
|
||||
max_pwm=h[4],
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
ht = dlg.getValues()
|
||||
|
||||
dlg.Destroy()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
|
||||
self.heaters[self.selection] = ht
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
self.heaters[self.selection] = ht
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
|
||||
def doDelete(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
def doDelete(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
|
||||
self.assertModified(True)
|
||||
self.assertModified(True)
|
||||
|
||||
del self.heaters[self.selection]
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
del self.heaters[self.selection]
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
self.assertModified(True)
|
||||
|
||||
def setHeaters(self, heaters):
|
||||
self.heaters = heaters
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
def setHeaters(self, heaters):
|
||||
self.heaters = heaters
|
||||
self.lb.updateList(self.heaters)
|
||||
self.validateTable()
|
||||
self.parent.setHeaters(self.heaters)
|
||||
|
||||
def setCandidatePins(self, plist):
|
||||
if not plist or len(plist) == 0:
|
||||
self.validPins = pinNames
|
||||
else:
|
||||
self.validPins = plist
|
||||
def setCandidatePins(self, plist):
|
||||
if not plist or len(plist) == 0:
|
||||
self.validPins = pinNames
|
||||
else:
|
||||
self.validPins = plist
|
||||
|
||||
self.validateTable()
|
||||
self.validateTable()
|
||||
|
||||
def heaterNames(self):
|
||||
heaterNames = []
|
||||
for heater in self.heaters:
|
||||
heaterNames.append(heater[0])
|
||||
def heaterNames(self):
|
||||
heaterNames = []
|
||||
for heater in self.heaters:
|
||||
heaterNames.append(heater[0])
|
||||
|
||||
return heaterNames
|
||||
return heaterNames
|
||||
|
||||
def validateTable(self):
|
||||
self.lb.setTableValidity(True)
|
||||
self.setFieldValidity('HEATERLIST', True)
|
||||
for i in range(len(self.heaters)):
|
||||
if self.heaters[i][1] not in self.validPins:
|
||||
self.lb.setRowValidity(i, False)
|
||||
self.setFieldValidity('HEATERLIST', False)
|
||||
def validateTable(self):
|
||||
self.lb.setTableValidity(True)
|
||||
self.setFieldValidity("HEATERLIST", True)
|
||||
for i in range(len(self.heaters)):
|
||||
if self.heaters[i][1] not in self.validPins:
|
||||
self.lb.setRowValidity(i, False)
|
||||
self.setFieldValidity("HEATERLIST", False)
|
||||
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
|
||||
k = 'DEFINE_HEATER'
|
||||
if k in ht.keys():
|
||||
self.bAdd.SetToolTip(ht[k])
|
||||
k = "DEFINE_HEATER"
|
||||
if k in ht.keys():
|
||||
self.bAdd.SetToolTip(ht[k])
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import wx
|
||||
from configtool.data import BSIZE
|
||||
from configtool.page import Page
|
||||
|
|
@ -7,238 +6,264 @@ from configtool.calcscrew import CalcScrew
|
|||
|
||||
|
||||
class MechanicalPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.id = idPg
|
||||
self.parent = parent
|
||||
self.font = font
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.id = idPg
|
||||
self.parent = parent
|
||||
self.font = font
|
||||
|
||||
self.spmKeys = ['STEPS_PER_M_X', 'STEPS_PER_M_Y', 'STEPS_PER_M_Z',
|
||||
'STEPS_PER_M_E']
|
||||
self.spmKeys = [
|
||||
"STEPS_PER_M_X",
|
||||
"STEPS_PER_M_Y",
|
||||
"STEPS_PER_M_Z",
|
||||
"STEPS_PER_M_E",
|
||||
]
|
||||
|
||||
self.mfrKeys = ['MAXIMUM_FEEDRATE_X', 'MAXIMUM_FEEDRATE_Y',
|
||||
'MAXIMUM_FEEDRATE_Z', 'MAXIMUM_FEEDRATE_E']
|
||||
self.mfrKeys = [
|
||||
"MAXIMUM_FEEDRATE_X",
|
||||
"MAXIMUM_FEEDRATE_Y",
|
||||
"MAXIMUM_FEEDRATE_Z",
|
||||
"MAXIMUM_FEEDRATE_E",
|
||||
]
|
||||
|
||||
self.msrKeys = ['SEARCH_FEEDRATE_X', 'SEARCH_FEEDRATE_Y',
|
||||
'SEARCH_FEEDRATE_Z']
|
||||
self.msrKeys = ["SEARCH_FEEDRATE_X", "SEARCH_FEEDRATE_Y", "SEARCH_FEEDRATE_Z"]
|
||||
|
||||
self.eclKeys = ['ENDSTOP_CLEARANCE_X', 'ENDSTOP_CLEARANCE_Y',
|
||||
'ENDSTOP_CLEARANCE_Z']
|
||||
self.eclKeys = [
|
||||
"ENDSTOP_CLEARANCE_X",
|
||||
"ENDSTOP_CLEARANCE_Y",
|
||||
"ENDSTOP_CLEARANCE_Z",
|
||||
]
|
||||
|
||||
self.minmaxKeys = ['X_MIN', 'X_MAX', 'Y_MIN', 'Y_MAX', 'Z_MIN', 'Z_MAX']
|
||||
self.minmaxKeys = ["X_MIN", "X_MAX", "Y_MIN", "Y_MAX", "Z_MIN", "Z_MAX"]
|
||||
|
||||
self.kinematicsKeys = ['KINEMATICS_STRAIGHT', 'KINEMATICS_COREXY']
|
||||
self.kinematicsKeys = ["KINEMATICS_STRAIGHT", "KINEMATICS_COREXY"]
|
||||
|
||||
self.homingKeys = [('HOMING_STEP1', 2), ('HOMING_STEP2', 2),
|
||||
('HOMING_STEP3', 2), ('HOMING_STEP4', 2)]
|
||||
self.homingKeys = [
|
||||
("HOMING_STEP1", 2),
|
||||
("HOMING_STEP2", 2),
|
||||
("HOMING_STEP3", 2),
|
||||
("HOMING_STEP4", 2),
|
||||
]
|
||||
|
||||
self.labels = {'STEPS_PER_M_X': "X:", 'STEPS_PER_M_Y': "Y:",
|
||||
'STEPS_PER_M_Z': "Z:", 'STEPS_PER_M_E' : "E:",
|
||||
'MAXIMUM_FEEDRATE_X': "X:", 'MAXIMUM_FEEDRATE_Y': "Y:",
|
||||
'MAXIMUM_FEEDRATE_Z': "Z:", 'MAXIMUM_FEEDRATE_E': "E:",
|
||||
'SEARCH_FEEDRATE_X': "X:", 'SEARCH_FEEDRATE_Y': "Y:",
|
||||
'SEARCH_FEEDRATE_Z': "Z:",
|
||||
'ENDSTOP_CLEARANCE_X': "X:", 'ENDSTOP_CLEARANCE_Y': "Y:",
|
||||
'ENDSTOP_CLEARANCE_Z': "Z:",
|
||||
'X_MIN': "Min X:", 'X_MAX': "Max X:", 'Y_MIN': "Min Y:",
|
||||
'Y_MAX': "Max Y:", 'Z_MIN': "Min Z:", 'Z_MAX': "Max Z:",
|
||||
'E_ABSOLUTE': "Absolute E Coordinates",
|
||||
'KINEMATICS_STRAIGHT': "Straight",
|
||||
'KINEMATICS_COREXY': "CoreXY",
|
||||
'HOMING_STEP1': "Step 1:",
|
||||
'HOMING_STEP2': "Step 2:",
|
||||
'HOMING_STEP3': "Step 3:",
|
||||
'HOMING_STEP4': "Step 4:",
|
||||
'none': "-",
|
||||
'x_negative': "X min",
|
||||
'x_positive': "X max",
|
||||
'y_negative': "Y min",
|
||||
'y_positive': "Y max",
|
||||
'z_negative': "Z min",
|
||||
'z_positive': "Z max"}
|
||||
self.labels = {
|
||||
"STEPS_PER_M_X": "X:",
|
||||
"STEPS_PER_M_Y": "Y:",
|
||||
"STEPS_PER_M_Z": "Z:",
|
||||
"STEPS_PER_M_E": "E:",
|
||||
"MAXIMUM_FEEDRATE_X": "X:",
|
||||
"MAXIMUM_FEEDRATE_Y": "Y:",
|
||||
"MAXIMUM_FEEDRATE_Z": "Z:",
|
||||
"MAXIMUM_FEEDRATE_E": "E:",
|
||||
"SEARCH_FEEDRATE_X": "X:",
|
||||
"SEARCH_FEEDRATE_Y": "Y:",
|
||||
"SEARCH_FEEDRATE_Z": "Z:",
|
||||
"ENDSTOP_CLEARANCE_X": "X:",
|
||||
"ENDSTOP_CLEARANCE_Y": "Y:",
|
||||
"ENDSTOP_CLEARANCE_Z": "Z:",
|
||||
"X_MIN": "Min X:",
|
||||
"X_MAX": "Max X:",
|
||||
"Y_MIN": "Min Y:",
|
||||
"Y_MAX": "Max Y:",
|
||||
"Z_MIN": "Min Z:",
|
||||
"Z_MAX": "Max Z:",
|
||||
"E_ABSOLUTE": "Absolute E Coordinates",
|
||||
"KINEMATICS_STRAIGHT": "Straight",
|
||||
"KINEMATICS_COREXY": "CoreXY",
|
||||
"HOMING_STEP1": "Step 1:",
|
||||
"HOMING_STEP2": "Step 2:",
|
||||
"HOMING_STEP3": "Step 3:",
|
||||
"HOMING_STEP4": "Step 4:",
|
||||
"none": "-",
|
||||
"x_negative": "X min",
|
||||
"x_positive": "X max",
|
||||
"y_negative": "Y min",
|
||||
"y_positive": "Y max",
|
||||
"z_negative": "Z min",
|
||||
"z_positive": "Z max",
|
||||
}
|
||||
|
||||
labelWidth = 40;
|
||||
labelWidthHoming = 60;
|
||||
labelWidth = 40
|
||||
labelWidthHoming = 60
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos = (0, 0))
|
||||
sz.Add((90, 10), pos = (0, 4))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos=(0, 0))
|
||||
sz.Add((90, 10), pos=(0, 4))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Steps Per Meter")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.spmKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Steps Per Meter")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.spmKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 1))
|
||||
sz.Add(sbox, pos=(1, 1))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Feedrate")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.mfrKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Feedrate")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.mfrKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 5))
|
||||
sz.Add(sbox, pos=(1, 5))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Search Feedrate")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.msrKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Search Feedrate")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.msrKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 7))
|
||||
sz.Add(sbox, pos=(1, 7))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Endstop Clearance")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.eclKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Endstop Clearance")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.eclKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (3, 5))
|
||||
sz.Add(sbox, pos=(3, 5))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Travel Limits")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.minmaxKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth + 20, self.onTextCtrlFloat)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Travel Limits")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k in self.minmaxKeys:
|
||||
tc = self.addTextCtrl(k, labelWidth + 20, self.onTextCtrlFloat)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (3, 7))
|
||||
sz.Add(sbox, pos=(3, 7))
|
||||
|
||||
vsz = wx.BoxSizer(wx.VERTICAL)
|
||||
vsz = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Kinematics")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
style = wx.RB_GROUP
|
||||
for k in self.kinematicsKeys:
|
||||
rb = self.addRadioButton(k, style, self.onKinematicsSelect, b)
|
||||
style = 0
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Kinematics")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
style = wx.RB_GROUP
|
||||
for k in self.kinematicsKeys:
|
||||
rb = self.addRadioButton(k, style, self.onKinematicsSelect, b)
|
||||
style = 0
|
||||
|
||||
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
vsz.Add(sbox, 1, wx.LEFT, 10)
|
||||
vsz.Add(sbox, 1, wx.LEFT, 10)
|
||||
|
||||
cb = self.addCheckBox('E_ABSOLUTE', self.onCheckBox)
|
||||
cb = self.addCheckBox("E_ABSOLUTE", self.onCheckBox)
|
||||
|
||||
vsz.Add(cb, 1, wx.LEFT, 10)
|
||||
vsz.Add(cb, 1, wx.LEFT, 10)
|
||||
|
||||
sz.Add(vsz, pos = (3, 1))
|
||||
sz.Add(vsz, pos=(3, 1))
|
||||
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Calculate\nBelt Driven", size = BSIZE)
|
||||
b.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
b.SetFont(font)
|
||||
b.SetToolTip("Open the calculator for axes that are belt-driven.")
|
||||
self.Bind(wx.EVT_BUTTON, self.onCalcBelt, b)
|
||||
self.bCalcBelt = b
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Calculate\nBelt Driven", size=BSIZE)
|
||||
b.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
b.SetFont(font)
|
||||
b.SetToolTip("Open the calculator for axes that are belt-driven.")
|
||||
self.Bind(wx.EVT_BUTTON, self.onCalcBelt, b)
|
||||
self.bCalcBelt = b
|
||||
|
||||
bsz.Add(b, 1, wx.ALL, 5)
|
||||
b = wx.Button(self, wx.ID_ANY, "Calculate\nScrew Driven", size = BSIZE)
|
||||
b.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
b.SetFont(font)
|
||||
bsz.Add(b, 1, wx.ALL, 5)
|
||||
b.SetToolTip("Open the calculator for axes that are screw-driven.")
|
||||
self.Bind(wx.EVT_BUTTON, self.onCalcScrew, b)
|
||||
self.bCalcScrew = b
|
||||
bsz.Add(b, 1, wx.ALL, 5)
|
||||
b = wx.Button(self, wx.ID_ANY, "Calculate\nScrew Driven", size=BSIZE)
|
||||
b.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
b.SetFont(font)
|
||||
bsz.Add(b, 1, wx.ALL, 5)
|
||||
b.SetToolTip("Open the calculator for axes that are screw-driven.")
|
||||
self.Bind(wx.EVT_BUTTON, self.onCalcScrew, b)
|
||||
self.bCalcScrew = b
|
||||
|
||||
sz.Add(bsz, pos = (1, 3))
|
||||
sz.Add(bsz, pos=(1, 3))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Homing Order")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in self.homingKeys:
|
||||
if ctype == 2:
|
||||
tc = self.addChoice(k, [], 0, labelWidthHoming, self.onChoice)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
sz.Add(sbox, pos = (3, 3))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Homing Order")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in self.homingKeys:
|
||||
if ctype == 2:
|
||||
tc = self.addChoice(k, [], 0, labelWidthHoming, self.onChoice)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
sz.Add(sbox, pos=(3, 3))
|
||||
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
|
||||
def enableAll(self, flag = True):
|
||||
self.bCalcBelt.Enable(flag)
|
||||
self.bCalcScrew.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
def enableAll(self, flag=True):
|
||||
self.bCalcBelt.Enable(flag)
|
||||
self.bCalcScrew.Enable(flag)
|
||||
Page.enableAll(self, flag)
|
||||
|
||||
def onKinematicsSelect(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
def onKinematicsSelect(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onCalcBelt(self, evt):
|
||||
dlg = CalcBelt(self, self.font, self.cbCalcBelt)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
def onCalcBelt(self, evt):
|
||||
dlg = CalcBelt(self, self.font, self.cbCalcBelt)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
def cbCalcBelt(self, field, value):
|
||||
s = "%d" % value
|
||||
self.textControls[field].SetValue(s)
|
||||
def cbCalcBelt(self, field, value):
|
||||
s = "%d" % value
|
||||
self.textControls[field].SetValue(s)
|
||||
|
||||
def onCalcScrew(self, evt):
|
||||
dlg = CalcScrew(self, self.font, self.cbCalcScrew)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
def onCalcScrew(self, evt):
|
||||
dlg = CalcScrew(self, self.font, self.cbCalcScrew)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
def cbCalcScrew(self, field, value):
|
||||
s = "%d" % value
|
||||
self.textControls[field].SetValue(s)
|
||||
def cbCalcScrew(self, field, value):
|
||||
s = "%d" % value
|
||||
self.textControls[field].SetValue(s)
|
||||
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
if 'KINEMATICS' in ht.keys():
|
||||
for k in self.kinematicsKeys:
|
||||
self.radioButtons[k].SetToolTip(ht['KINEMATICS'])
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
if "KINEMATICS" in ht.keys():
|
||||
for k in self.kinematicsKeys:
|
||||
self.radioButtons[k].SetToolTip(ht["KINEMATICS"])
|
||||
|
||||
def prepareHomingValues(self, name, i, cfgValues):
|
||||
self.choices[name].Clear()
|
||||
for p in cfgValues['HOMING_OPTS']:
|
||||
self.choices[name].Append(self.labels[p])
|
||||
i = cfgValues['HOMING_OPTS'].index(cfgValues[name])
|
||||
self.choices[name].SetSelection(i)
|
||||
def prepareHomingValues(self, name, i, cfgValues):
|
||||
self.choices[name].Clear()
|
||||
for p in cfgValues["HOMING_OPTS"]:
|
||||
self.choices[name].Append(self.labels[p])
|
||||
i = cfgValues["HOMING_OPTS"].index(cfgValues[name])
|
||||
self.choices[name].SetSelection(i)
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
|
||||
self.prepareHomingValues('HOMING_STEP1', 0, cfgValues)
|
||||
self.prepareHomingValues('HOMING_STEP2', 1, cfgValues)
|
||||
self.prepareHomingValues('HOMING_STEP3', 2, cfgValues)
|
||||
self.prepareHomingValues('HOMING_STEP4', 3, cfgValues)
|
||||
self.prepareHomingValues("HOMING_STEP1", 0, cfgValues)
|
||||
self.prepareHomingValues("HOMING_STEP2", 1, cfgValues)
|
||||
self.prepareHomingValues("HOMING_STEP3", 2, cfgValues)
|
||||
self.prepareHomingValues("HOMING_STEP4", 3, cfgValues)
|
||||
|
||||
for tag in self.kinematicsKeys:
|
||||
if tag in cfgValues.keys() and cfgValues[tag]:
|
||||
self.radioButtons[tag].SetValue(True)
|
||||
for tag in self.kinematicsKeys:
|
||||
if tag in cfgValues.keys() and cfgValues[tag]:
|
||||
self.radioButtons[tag].SetValue(True)
|
||||
|
||||
def getHomingValue(self, name, result):
|
||||
return (self.labels.keys()[self.labels.values().index(result[name][0])], True)
|
||||
def getHomingValue(self, name, result):
|
||||
return (self.labels.keys()[self.labels.values().index(result[name][0])], True)
|
||||
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
|
||||
for tag in self.kinematicsKeys:
|
||||
result[tag] = self.radioButtons[tag].GetValue()
|
||||
for tag in self.kinematicsKeys:
|
||||
result[tag] = self.radioButtons[tag].GetValue()
|
||||
|
||||
result['HOMING_STEP1'] = self.getHomingValue('HOMING_STEP1', result)
|
||||
result['HOMING_STEP2'] = self.getHomingValue('HOMING_STEP2', result)
|
||||
result['HOMING_STEP3'] = self.getHomingValue('HOMING_STEP3', result)
|
||||
result['HOMING_STEP4'] = self.getHomingValue('HOMING_STEP4', result)
|
||||
result["HOMING_STEP1"] = self.getHomingValue("HOMING_STEP1", result)
|
||||
result["HOMING_STEP2"] = self.getHomingValue("HOMING_STEP2", result)
|
||||
result["HOMING_STEP3"] = self.getHomingValue("HOMING_STEP3", result)
|
||||
result["HOMING_STEP4"] = self.getHomingValue("HOMING_STEP4", result)
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,233 +1,240 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
from configtool.data import reFloat
|
||||
|
||||
|
||||
class MiscellaneousPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
self.font = font
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
self.font = font
|
||||
|
||||
self.labels = {'USE_INTERNAL_PULLUPS': "Use Internal Pullups",
|
||||
'BED_LEVELING': "Enable dynamic bed leveling",
|
||||
'Z_AUTODISABLE': "Z Autodisable",
|
||||
'EECONFIG': "Enable EEPROM Storage",
|
||||
'BANG_BANG': "Enable",
|
||||
'BANG_BANG_ON': "On PWM Level:",
|
||||
'BANG_BANG_OFF': "Off PWM Level:",
|
||||
'REPORT_TARGET_TEMPS': "Report Target Temperatures",
|
||||
'MOVEBUFFER_SIZE': "Movebuffer Size:",
|
||||
'DC_EXTRUDER': "Heater:", 'DC_EXTRUDER_PWM': "PWM:",
|
||||
'USE_WATCHDOG': "Use the Watchdog Timer",
|
||||
'TH_COUNT': "Temperature History Size:",
|
||||
'FAST_PWM': "Fast PWM",
|
||||
'ENDSTOP_STEPS': "Endstop Steps:",
|
||||
'PID_SCALE': "PID Scaling Factor:",
|
||||
'TEMP_HYSTERESIS': "Temperature Hysteresis:",
|
||||
'TEMP_RESIDENCY_TIME': "Temperature Residency Time:",
|
||||
'TEMP_EWMA': "Temperature EWMA:",
|
||||
'HEATER_SANITY_CHECK': "Heater Sanity Check"}
|
||||
self.labels = {
|
||||
"USE_INTERNAL_PULLUPS": "Use Internal Pullups",
|
||||
"BED_LEVELING": "Enable dynamic bed leveling",
|
||||
"Z_AUTODISABLE": "Z Autodisable",
|
||||
"EECONFIG": "Enable EEPROM Storage",
|
||||
"BANG_BANG": "Enable",
|
||||
"BANG_BANG_ON": "On PWM Level:",
|
||||
"BANG_BANG_OFF": "Off PWM Level:",
|
||||
"REPORT_TARGET_TEMPS": "Report Target Temperatures",
|
||||
"MOVEBUFFER_SIZE": "Movebuffer Size:",
|
||||
"DC_EXTRUDER": "Heater:",
|
||||
"DC_EXTRUDER_PWM": "PWM:",
|
||||
"USE_WATCHDOG": "Use the Watchdog Timer",
|
||||
"TH_COUNT": "Temperature History Size:",
|
||||
"FAST_PWM": "Fast PWM",
|
||||
"ENDSTOP_STEPS": "Endstop Steps:",
|
||||
"PID_SCALE": "PID Scaling Factor:",
|
||||
"TEMP_HYSTERESIS": "Temperature Hysteresis:",
|
||||
"TEMP_RESIDENCY_TIME": "Temperature Residency Time:",
|
||||
"TEMP_EWMA": "Temperature EWMA:",
|
||||
"HEATER_SANITY_CHECK": "Heater Sanity Check",
|
||||
}
|
||||
|
||||
self.heaterNameNone = "<none>"
|
||||
self.heaterNames = [self.heaterNameNone]
|
||||
self.boardHeaters = []
|
||||
self.processors = []
|
||||
self.heaterNameNone = "<none>"
|
||||
self.heaterNames = [self.heaterNameNone]
|
||||
self.boardHeaters = []
|
||||
self.processors = []
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos = (0, 0))
|
||||
sz.Add((40, 40), pos = (0, 2))
|
||||
sz.Add((40, 40), pos = (0, 4))
|
||||
sz.Add((20, 30), pos = (1, 0))
|
||||
sz.Add((20, 30), pos = (2, 0))
|
||||
sz.Add((20, 30), pos = (3, 0))
|
||||
sz.Add((20, 30), pos = (4, 0))
|
||||
sz.Add((20, 30), pos = (5, 0))
|
||||
sz.Add((20, 30), pos = (6, 0))
|
||||
sz.Add((20, 30), pos = (7, 0))
|
||||
sz.Add((20, 30), pos = (8, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((20, 40), pos=(0, 0))
|
||||
sz.Add((40, 40), pos=(0, 2))
|
||||
sz.Add((40, 40), pos=(0, 4))
|
||||
sz.Add((20, 30), pos=(1, 0))
|
||||
sz.Add((20, 30), pos=(2, 0))
|
||||
sz.Add((20, 30), pos=(3, 0))
|
||||
sz.Add((20, 30), pos=(4, 0))
|
||||
sz.Add((20, 30), pos=(5, 0))
|
||||
sz.Add((20, 30), pos=(6, 0))
|
||||
sz.Add((20, 30), pos=(7, 0))
|
||||
sz.Add((20, 30), pos=(8, 0))
|
||||
|
||||
labelWidth = 140
|
||||
labelWidth = 140
|
||||
|
||||
k = 'EECONFIG'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (1, 1))
|
||||
k = "EECONFIG"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(1, 1))
|
||||
|
||||
k = 'USE_INTERNAL_PULLUPS'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (2, 1))
|
||||
k = "USE_INTERNAL_PULLUPS"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(2, 1))
|
||||
|
||||
k = 'USE_WATCHDOG'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (3, 1))
|
||||
k = "USE_WATCHDOG"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(3, 1))
|
||||
|
||||
k = 'FAST_PWM'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (4, 1))
|
||||
k = "FAST_PWM"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(4, 1))
|
||||
|
||||
k = 'HEATER_SANITY_CHECK'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (5, 1))
|
||||
k = "HEATER_SANITY_CHECK"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(5, 1))
|
||||
|
||||
k = 'REPORT_TARGET_TEMPS'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (6, 1))
|
||||
k = "REPORT_TARGET_TEMPS"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(6, 1))
|
||||
|
||||
k = 'Z_AUTODISABLE'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (7, 1))
|
||||
k = "Z_AUTODISABLE"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(7, 1))
|
||||
|
||||
k = 'BED_LEVELING'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (8, 1))
|
||||
k = "BED_LEVELING"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos=(8, 1))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "BANG BANG Bed Control")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "BANG BANG Bed Control")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'BANG_BANG'
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 60)
|
||||
sbox.Add((5, 20))
|
||||
k = "BANG_BANG"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 60)
|
||||
sbox.Add((5, 20))
|
||||
|
||||
k = 'BANG_BANG_ON'
|
||||
tc = self.addTextCtrl(k, 100, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
k = "BANG_BANG_ON"
|
||||
tc = self.addTextCtrl(k, 100, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'BANG_BANG_OFF'
|
||||
tc = self.addTextCtrl(k, 100, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
k = "BANG_BANG_OFF"
|
||||
tc = self.addTextCtrl(k, 100, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 3), span = (5, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add(sbox, pos=(1, 3), span=(5, 1), flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "DC Motor Extruder")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "DC Motor Extruder")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'DC_EXTRUDER'
|
||||
ch = self.addChoice(k, self.heaterNames, 0, 60, self.onChoice)
|
||||
sbox.Add(ch)
|
||||
sbox.Add((5, 5))
|
||||
k = "DC_EXTRUDER"
|
||||
ch = self.addChoice(k, self.heaterNames, 0, 60, self.onChoice)
|
||||
sbox.Add(ch)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
k = 'DC_EXTRUDER_PWM'
|
||||
tc = self.addTextCtrl(k, 60, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
k = "DC_EXTRUDER_PWM"
|
||||
tc = self.addTextCtrl(k, 60, self.onTextCtrlInteger)
|
||||
sbox.Add(tc)
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (6, 3), span=(3, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add(sbox, pos=(6, 3), span=(3, 1), flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
labelWidth = 190;
|
||||
labelWidth = 190
|
||||
|
||||
k = 'MOVEBUFFER_SIZE'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (1, 5))
|
||||
k = "MOVEBUFFER_SIZE"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(1, 5))
|
||||
|
||||
k = 'TH_COUNT'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (2, 5))
|
||||
k = "TH_COUNT"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(2, 5))
|
||||
|
||||
k = 'ENDSTOP_STEPS'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (3, 5))
|
||||
k = "ENDSTOP_STEPS"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(3, 5))
|
||||
|
||||
k = 'PID_SCALE'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (4, 5))
|
||||
k = "PID_SCALE"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(4, 5))
|
||||
|
||||
k = 'TEMP_HYSTERESIS'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (6, 5))
|
||||
k = "TEMP_HYSTERESIS"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(6, 5))
|
||||
|
||||
k = 'TEMP_RESIDENCY_TIME'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (7, 5))
|
||||
k = "TEMP_RESIDENCY_TIME"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(7, 5))
|
||||
|
||||
k = 'TEMP_EWMA'
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos = (8, 5))
|
||||
k = "TEMP_EWMA"
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlInteger)
|
||||
sz.Add(tc, pos=(8, 5))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def setHeaters(self, hlist):
|
||||
k = 'DC_EXTRUDER'
|
||||
v = self.choices[k].GetSelection()
|
||||
currentChoice = self.heaterNames[v]
|
||||
self.boardHeaters = [s[0] for s in hlist]
|
||||
self.heaterNames = [self.heaterNameNone] + self.boardHeaters
|
||||
self.choices[k].Clear()
|
||||
self.choices[k].SetFont(self.font)
|
||||
for h in self.heaterNames:
|
||||
self.choices[k].Append(h)
|
||||
def setHeaters(self, hlist):
|
||||
k = "DC_EXTRUDER"
|
||||
v = self.choices[k].GetSelection()
|
||||
currentChoice = self.heaterNames[v]
|
||||
self.boardHeaters = [s[0] for s in hlist]
|
||||
self.heaterNames = [self.heaterNameNone] + self.boardHeaters
|
||||
self.choices[k].Clear()
|
||||
self.choices[k].SetFont(self.font)
|
||||
for h in self.heaterNames:
|
||||
self.choices[k].Append(h)
|
||||
|
||||
try:
|
||||
v = self.heaterNames.index(currentChoice)
|
||||
except:
|
||||
v = 0
|
||||
dlg = wx.MessageDialog(self,
|
||||
"Printer: Miscellaneous tab:\nDC Extruder heater "
|
||||
"\"%s\" not defined for this board. Please check."
|
||||
% currentChoice, "Warning",
|
||||
wx.OK + wx.ICON_WARNING)
|
||||
try:
|
||||
v = self.heaterNames.index(currentChoice)
|
||||
except:
|
||||
v = 0
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Printer: Miscellaneous tab:\nDC Extruder heater "
|
||||
'"%s" not defined for this board. Please check.' % currentChoice,
|
||||
"Warning",
|
||||
wx.OK + wx.ICON_WARNING,
|
||||
)
|
||||
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
self.choices[k].SetSelection(v)
|
||||
self.choices[k].SetSelection(v)
|
||||
|
||||
def setOriginalHeater(self, h):
|
||||
k = 'DC_EXTRUDER'
|
||||
if h and h.startswith("HEATER_"):
|
||||
hname = h[len("HEATER_"):]
|
||||
else:
|
||||
hname = h
|
||||
if hname and len(self.boardHeaters) != 0:
|
||||
if hname not in self.boardHeaters:
|
||||
dlg = wx.MessageDialog(self,
|
||||
"Printer: Miscellaneous tab:\nDC Extruder "
|
||||
"heater \"%s\" not defined for this board. "
|
||||
"Please check."
|
||||
% hname, "Warning", wx.OK + wx.ICON_WARNING)
|
||||
def setOriginalHeater(self, h):
|
||||
k = "DC_EXTRUDER"
|
||||
if h and h.startswith("HEATER_"):
|
||||
hname = h[len("HEATER_") :]
|
||||
else:
|
||||
hname = h
|
||||
if hname and len(self.boardHeaters) != 0:
|
||||
if hname not in self.boardHeaters:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Printer: Miscellaneous tab:\nDC Extruder "
|
||||
'heater "%s" not defined for this board. '
|
||||
"Please check." % hname,
|
||||
"Warning",
|
||||
wx.OK + wx.ICON_WARNING,
|
||||
)
|
||||
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
self.heaterNames = [self.heaterNameNone] + self.boardHeaters
|
||||
else:
|
||||
self.heaterNames = [self.heaterNameNone]
|
||||
if hname and hname != self.heaterNameNone:
|
||||
self.heaterNames.append(hname)
|
||||
self.choices[k].Clear()
|
||||
self.choices[k].SetFont(self.font)
|
||||
for ht in self.heaterNames:
|
||||
self.choices[k].Append(ht)
|
||||
if hname:
|
||||
try:
|
||||
v = self.heaterNames.index(hname)
|
||||
except:
|
||||
v = 0
|
||||
else:
|
||||
v = 0
|
||||
self.choices[k].SetSelection(v)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
self.heaterNames = [self.heaterNameNone] + self.boardHeaters
|
||||
else:
|
||||
self.heaterNames = [self.heaterNameNone]
|
||||
if hname and hname != self.heaterNameNone:
|
||||
self.heaterNames.append(hname)
|
||||
self.choices[k].Clear()
|
||||
self.choices[k].SetFont(self.font)
|
||||
for ht in self.heaterNames:
|
||||
self.choices[k].Append(ht)
|
||||
if hname:
|
||||
try:
|
||||
v = self.heaterNames.index(hname)
|
||||
except:
|
||||
v = 0
|
||||
else:
|
||||
v = 0
|
||||
self.choices[k].SetSelection(v)
|
||||
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
|
||||
k = 'DC_EXTRUDER'
|
||||
s = self.choices[k].GetSelection()
|
||||
v = self.choices[k].GetString(s)
|
||||
if v == self.heaterNameNone:
|
||||
if k in self.choicesOriginal.keys():
|
||||
result[k] = self.choicesOriginal[k][0], False
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = "HEATER_%s" % v, True
|
||||
k = "DC_EXTRUDER"
|
||||
s = self.choices[k].GetSelection()
|
||||
v = self.choices[k].GetString(s)
|
||||
if v == self.heaterNameNone:
|
||||
if k in self.choicesOriginal.keys():
|
||||
result[k] = self.choicesOriginal[k][0], False
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = "HEATER_%s" % v, True
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -3,352 +3,370 @@ from __future__ import print_function
|
|||
import wx
|
||||
|
||||
from configtool.decoration import Decoration
|
||||
from configtool.data import (reInteger, reFloat, offsetChLabel, offsetTcLabel,
|
||||
pinNames)
|
||||
from configtool.data import reInteger, reFloat, offsetChLabel, offsetTcLabel, pinNames
|
||||
|
||||
|
||||
class Page:
|
||||
def __init__(self, font):
|
||||
self.modified = False
|
||||
self.valid = True
|
||||
self.fieldValid = {}
|
||||
self.textControls = {}
|
||||
self.textControlsOriginal = {}
|
||||
self.checkBoxes = {}
|
||||
self.radioButtons = {}
|
||||
self.radioButtonBoxes = {}
|
||||
self.choices = {}
|
||||
self.choicesOriginal = {}
|
||||
self.boolChoices = {}
|
||||
self.deco = Decoration()
|
||||
self.font = font
|
||||
def __init__(self, font):
|
||||
self.modified = False
|
||||
self.valid = True
|
||||
self.fieldValid = {}
|
||||
self.textControls = {}
|
||||
self.textControlsOriginal = {}
|
||||
self.checkBoxes = {}
|
||||
self.radioButtons = {}
|
||||
self.radioButtonBoxes = {}
|
||||
self.choices = {}
|
||||
self.choicesOriginal = {}
|
||||
self.boolChoices = {}
|
||||
self.deco = Decoration()
|
||||
self.font = font
|
||||
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
|
||||
def enableAll(self, flag = True):
|
||||
for c in self.textControls.keys():
|
||||
self.textControls[c].Enable(flag)
|
||||
for c in self.checkBoxes.keys():
|
||||
self.checkBoxes[c].Enable(flag)
|
||||
for c in self.radioButtons.keys():
|
||||
self.radioButtons[c].Enable(flag)
|
||||
for c in self.choices.keys():
|
||||
self.choices[c].Enable(flag)
|
||||
def enableAll(self, flag=True):
|
||||
for c in self.textControls.keys():
|
||||
self.textControls[c].Enable(flag)
|
||||
for c in self.checkBoxes.keys():
|
||||
self.checkBoxes[c].Enable(flag)
|
||||
for c in self.radioButtons.keys():
|
||||
self.radioButtons[c].Enable(flag)
|
||||
for c in self.choices.keys():
|
||||
self.choices[c].Enable(flag)
|
||||
|
||||
def addTextCtrl(self, name, labelWidth, validator):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, self.labels[name] + " ",
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
def addTextCtrl(self, name, labelWidth, validator):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
self.labels[name] + " ",
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetTcLabel)
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "", style = wx.TE_RIGHT, name = name)
|
||||
tc.SetFont(self.font)
|
||||
self.fieldValid[name] = True
|
||||
tc.Bind(wx.EVT_TEXT, validator)
|
||||
self.textControls[name] = tc
|
||||
lsz.Add(tc)
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_RIGHT, name=name)
|
||||
tc.SetFont(self.font)
|
||||
self.fieldValid[name] = True
|
||||
tc.Bind(wx.EVT_TEXT, validator)
|
||||
self.textControls[name] = tc
|
||||
lsz.Add(tc)
|
||||
|
||||
return lsz
|
||||
return lsz
|
||||
|
||||
def addCheckBox(self, name, validator):
|
||||
if name in self.labels.keys():
|
||||
lbl = self.labels[name]
|
||||
else:
|
||||
lbl = name
|
||||
cb = wx.CheckBox(self, wx.ID_ANY, lbl)
|
||||
cb.SetFont(self.font)
|
||||
cb.Bind(wx.EVT_CHECKBOX, validator)
|
||||
self.checkBoxes[name] = cb
|
||||
|
||||
return cb
|
||||
|
||||
def addRadioButton(self, name, style, validator, sbox = None):
|
||||
rb = wx.RadioButton(self, wx.ID_ANY, self.labels[name], style = style)
|
||||
rb.SetFont(self.font)
|
||||
self.Bind(wx.EVT_RADIOBUTTON, validator, rb)
|
||||
self.radioButtons[name] = rb
|
||||
if sbox is not None:
|
||||
self.radioButtonBoxes[name] = sbox
|
||||
|
||||
return rb
|
||||
|
||||
def addChoice(self, name, choices, selection, labelWidth, validator,
|
||||
size = (-1, -1)):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
ch = wx.Choice(self, wx.ID_ANY, choices = choices, size = size, name = name)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.Bind(wx.EVT_CHOICE, validator)
|
||||
ch.SetSelection(selection)
|
||||
lsz.Add(ch)
|
||||
self.choices[name] = ch
|
||||
|
||||
return lsz
|
||||
|
||||
def addPinChoice(self, name, labelWidth):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
ch = wx.Choice(self, wx.ID_ANY, name = name, style = wx.CB_SORT)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.AppendItems(["-"] + pinNames)
|
||||
ch.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
self.choices[name] = ch
|
||||
lsz.Add(ch)
|
||||
|
||||
return lsz
|
||||
|
||||
# addChoice handles #defines with value, this handles choices for
|
||||
# sets of boolean #defines.
|
||||
def addBoolChoice(self, name, allowBlank, labelWidth, validator,
|
||||
size = (-1, -1)):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
|
||||
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
ch = wx.Choice(self, wx.ID_ANY, size = size, name = name)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.Bind(wx.EVT_CHOICE, validator)
|
||||
|
||||
if allowBlank:
|
||||
ch.Append("(none)")
|
||||
ch.SetSelection(0)
|
||||
|
||||
lsz.Add(ch)
|
||||
self.boolChoices[name] = ch
|
||||
|
||||
return lsz
|
||||
|
||||
def setChoice(self, name, cfgValues, default):
|
||||
if name in cfgValues.keys() and cfgValues[name][1] == True:
|
||||
bv = cfgValues[name][0]
|
||||
else:
|
||||
bv = default
|
||||
|
||||
s = self.choices[name].FindString(bv)
|
||||
if s < 0:
|
||||
s = self.choices[name].FindString(default)
|
||||
if s < 0:
|
||||
s = 0
|
||||
|
||||
self.choices[name].SetSelection(s)
|
||||
|
||||
def onTextCtrlInteger(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
name = tc.GetName()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = True
|
||||
else:
|
||||
m = reInteger.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
self.setFieldValidity(name, valid)
|
||||
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
evt.Skip()
|
||||
|
||||
def onTextCtrlFloat(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
name = tc.GetName()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = True
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
self.setFieldValidity(name, valid)
|
||||
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
evt.Skip()
|
||||
|
||||
def onTextCtrlPin(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
self.validatePin(tc)
|
||||
evt.Skip()
|
||||
|
||||
def onTextCtrl(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onChoice(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onCheckBox(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def setHelpText(self, ht):
|
||||
for k in self.textControls.keys():
|
||||
if k in ht.keys():
|
||||
self.textControls[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
if k in ht.keys():
|
||||
self.checkBoxes[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.radioButtons.keys():
|
||||
if k in ht.keys():
|
||||
self.radioButtons[k].SetToolTip(ht[k])
|
||||
if k in self.radioButtonBoxes.keys():
|
||||
self.radioButtonBoxes[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.choices.keys():
|
||||
if k in ht.keys():
|
||||
self.choices[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
for candidate in ht.keys():
|
||||
if candidate.startswith(k):
|
||||
self.boolChoices[k].SetToolTip(ht[candidate])
|
||||
break
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
self.assertValid(True)
|
||||
self.enableAll(True)
|
||||
for k in self.fieldValid.keys():
|
||||
self.fieldValid[k] = True
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
if k in cfgValues.keys() and cfgValues[k]:
|
||||
self.checkBoxes[k].SetValue(True)
|
||||
else:
|
||||
self.checkBoxes[k].SetValue(False)
|
||||
|
||||
for k in self.textControls.keys():
|
||||
if k in cfgValues.keys():
|
||||
self.textControlsOriginal[k] = cfgValues[k]
|
||||
if cfgValues[k][1] == True:
|
||||
self.textControls[k].SetValue(str(cfgValues[k][0]))
|
||||
def addCheckBox(self, name, validator):
|
||||
if name in self.labels.keys():
|
||||
lbl = self.labels[name]
|
||||
else:
|
||||
self.textControls[k].SetValue("")
|
||||
else:
|
||||
print("Key " + k + " not found in config data.")
|
||||
lbl = name
|
||||
cb = wx.CheckBox(self, wx.ID_ANY, lbl)
|
||||
cb.SetFont(self.font)
|
||||
cb.Bind(wx.EVT_CHECKBOX, validator)
|
||||
self.checkBoxes[name] = cb
|
||||
|
||||
for k in self.choices.keys():
|
||||
if k in cfgValues.keys():
|
||||
self.choicesOriginal[k] = cfgValues[k]
|
||||
self.setChoice(k, cfgValues, "-")
|
||||
else:
|
||||
print("Key " + k + " not found in config data.")
|
||||
return cb
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
choice = self.boolChoices[k]
|
||||
def addRadioButton(self, name, style, validator, sbox=None):
|
||||
rb = wx.RadioButton(self, wx.ID_ANY, self.labels[name], style=style)
|
||||
rb.SetFont(self.font)
|
||||
self.Bind(wx.EVT_RADIOBUTTON, validator, rb)
|
||||
self.radioButtons[name] = rb
|
||||
if sbox is not None:
|
||||
self.radioButtonBoxes[name] = sbox
|
||||
|
||||
# Remove items left behind from the previous configuration.
|
||||
while (choice.GetCount() and
|
||||
not choice.GetString(choice.GetCount() - 1).startswith('(')):
|
||||
choice.Delete(choice.GetCount() - 1)
|
||||
return rb
|
||||
|
||||
# Add items found in this configuration.
|
||||
for cfg in cfgValues.keys():
|
||||
if cfg.startswith(k):
|
||||
if cfg in self.labels.keys():
|
||||
choice.Append(self.labels[cfg])
|
||||
else:
|
||||
choice.Append(cfg)
|
||||
def addChoice(self, name, choices, selection, labelWidth, validator, size=(-1, -1)):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
self.labels[name],
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
# As we want to write the configuration name later, not the user
|
||||
# friendly string, we store the configuration name as client data.
|
||||
n = choice.GetCount() - 1
|
||||
choice.SetClientData(n, cfg)
|
||||
ch = wx.Choice(self, wx.ID_ANY, choices=choices, size=size, name=name)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.Bind(wx.EVT_CHOICE, validator)
|
||||
ch.SetSelection(selection)
|
||||
lsz.Add(ch)
|
||||
self.choices[name] = ch
|
||||
|
||||
if cfgValues[cfg]:
|
||||
choice.SetSelection(n)
|
||||
return lsz
|
||||
|
||||
self.assertModified(False)
|
||||
def addPinChoice(self, name, labelWidth):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
self.labels[name],
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
def getValues(self):
|
||||
self.assertModified(False)
|
||||
result = {}
|
||||
ch = wx.Choice(self, wx.ID_ANY, name=name, style=wx.CB_SORT)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.AppendItems(["-"] + pinNames)
|
||||
ch.Bind(wx.EVT_CHOICE, self.onChoice)
|
||||
self.choices[name] = ch
|
||||
lsz.Add(ch)
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
cb = self.checkBoxes[k]
|
||||
result[k] = cb.IsChecked()
|
||||
return lsz
|
||||
|
||||
for k in self.textControls.keys():
|
||||
v = self.textControls[k].GetValue()
|
||||
if v == "":
|
||||
if k in self.textControlsOriginal.keys():
|
||||
result[k] = self.textControlsOriginal[k][0], False
|
||||
# addChoice handles #defines with value, this handles choices for
|
||||
# sets of boolean #defines.
|
||||
def addBoolChoice(self, name, allowBlank, labelWidth, validator, size=(-1, -1)):
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
st = wx.StaticText(
|
||||
self,
|
||||
wx.ID_ANY,
|
||||
self.labels[name],
|
||||
size=(labelWidth, -1),
|
||||
style=wx.ALIGN_RIGHT,
|
||||
)
|
||||
st.SetFont(self.font)
|
||||
lsz.Add(st, 1, wx.TOP, offsetChLabel)
|
||||
|
||||
ch = wx.Choice(self, wx.ID_ANY, size=size, name=name)
|
||||
ch.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
ch.SetFont(self.font)
|
||||
ch.Bind(wx.EVT_CHOICE, validator)
|
||||
|
||||
if allowBlank:
|
||||
ch.Append("(none)")
|
||||
ch.SetSelection(0)
|
||||
|
||||
lsz.Add(ch)
|
||||
self.boolChoices[name] = ch
|
||||
|
||||
return lsz
|
||||
|
||||
def setChoice(self, name, cfgValues, default):
|
||||
if name in cfgValues.keys() and cfgValues[name][1] == True:
|
||||
bv = cfgValues[name][0]
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = v, True
|
||||
bv = default
|
||||
|
||||
for k in self.radioButtons.keys():
|
||||
result[k] = self.radioButtons[k].GetValue(), True
|
||||
s = self.choices[name].FindString(bv)
|
||||
if s < 0:
|
||||
s = self.choices[name].FindString(default)
|
||||
if s < 0:
|
||||
s = 0
|
||||
|
||||
for k in self.choices.keys():
|
||||
v = self.choices[k].GetSelection()
|
||||
s = self.choices[k].GetString(v)
|
||||
if s == "-":
|
||||
if k in self.choicesOriginal.keys():
|
||||
result[k] = self.choicesOriginal[k][0], False
|
||||
self.choices[name].SetSelection(s)
|
||||
|
||||
def onTextCtrlInteger(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
name = tc.GetName()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = True
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = s, True
|
||||
m = reInteger.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
choice = self.boolChoices[k]
|
||||
for i in range(choice.GetCount()):
|
||||
s = choice.GetClientData(i)
|
||||
if s:
|
||||
result[s] = (i == choice.GetSelection())
|
||||
self.setFieldValidity(name, valid)
|
||||
|
||||
return result
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
evt.Skip()
|
||||
|
||||
def assertModified(self, flag):
|
||||
if flag != self.modified:
|
||||
self.parent.assertModified(self.id, flag)
|
||||
self.modified = flag
|
||||
def onTextCtrlFloat(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
name = tc.GetName()
|
||||
w = tc.GetValue().strip()
|
||||
if w == "":
|
||||
valid = True
|
||||
else:
|
||||
m = reFloat.match(w)
|
||||
if m:
|
||||
valid = True
|
||||
else:
|
||||
valid = False
|
||||
|
||||
def setFieldValidity(self, name, flag):
|
||||
self.fieldValid[name] = flag
|
||||
self.setFieldValidity(name, valid)
|
||||
|
||||
pgValid = True
|
||||
for k in self.fieldValid.keys():
|
||||
if not self.fieldValid[k]:
|
||||
pgValid = False
|
||||
break
|
||||
if valid:
|
||||
tc.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))
|
||||
else:
|
||||
tc.SetBackgroundColour("pink")
|
||||
tc.Refresh()
|
||||
evt.Skip()
|
||||
|
||||
self.assertValid(pgValid)
|
||||
def onTextCtrlPin(self, evt):
|
||||
self.assertModified(True)
|
||||
tc = evt.GetEventObject()
|
||||
self.validatePin(tc)
|
||||
evt.Skip()
|
||||
|
||||
def assertValid(self, flag):
|
||||
if flag != self.valid:
|
||||
self.parent.assertValid(self.id, flag)
|
||||
self.valid = flag
|
||||
def onTextCtrl(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onChoice(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onCheckBox(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def setHelpText(self, ht):
|
||||
for k in self.textControls.keys():
|
||||
if k in ht.keys():
|
||||
self.textControls[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
if k in ht.keys():
|
||||
self.checkBoxes[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.radioButtons.keys():
|
||||
if k in ht.keys():
|
||||
self.radioButtons[k].SetToolTip(ht[k])
|
||||
if k in self.radioButtonBoxes.keys():
|
||||
self.radioButtonBoxes[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.choices.keys():
|
||||
if k in ht.keys():
|
||||
self.choices[k].SetToolTip(ht[k])
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
for candidate in ht.keys():
|
||||
if candidate.startswith(k):
|
||||
self.boolChoices[k].SetToolTip(ht[candidate])
|
||||
break
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
self.assertValid(True)
|
||||
self.enableAll(True)
|
||||
for k in self.fieldValid.keys():
|
||||
self.fieldValid[k] = True
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
if k in cfgValues.keys() and cfgValues[k]:
|
||||
self.checkBoxes[k].SetValue(True)
|
||||
else:
|
||||
self.checkBoxes[k].SetValue(False)
|
||||
|
||||
for k in self.textControls.keys():
|
||||
if k in cfgValues.keys():
|
||||
self.textControlsOriginal[k] = cfgValues[k]
|
||||
if cfgValues[k][1] == True:
|
||||
self.textControls[k].SetValue(str(cfgValues[k][0]))
|
||||
else:
|
||||
self.textControls[k].SetValue("")
|
||||
else:
|
||||
print("Key " + k + " not found in config data.")
|
||||
|
||||
for k in self.choices.keys():
|
||||
if k in cfgValues.keys():
|
||||
self.choicesOriginal[k] = cfgValues[k]
|
||||
self.setChoice(k, cfgValues, "-")
|
||||
else:
|
||||
print("Key " + k + " not found in config data.")
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
choice = self.boolChoices[k]
|
||||
|
||||
# Remove items left behind from the previous configuration.
|
||||
while choice.GetCount() and not choice.GetString(
|
||||
choice.GetCount() - 1
|
||||
).startswith("("):
|
||||
choice.Delete(choice.GetCount() - 1)
|
||||
|
||||
# Add items found in this configuration.
|
||||
for cfg in cfgValues.keys():
|
||||
if cfg.startswith(k):
|
||||
if cfg in self.labels.keys():
|
||||
choice.Append(self.labels[cfg])
|
||||
else:
|
||||
choice.Append(cfg)
|
||||
|
||||
# As we want to write the configuration name later, not the user
|
||||
# friendly string, we store the configuration name as client data.
|
||||
n = choice.GetCount() - 1
|
||||
choice.SetClientData(n, cfg)
|
||||
|
||||
if cfgValues[cfg]:
|
||||
choice.SetSelection(n)
|
||||
|
||||
self.assertModified(False)
|
||||
|
||||
def getValues(self):
|
||||
self.assertModified(False)
|
||||
result = {}
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
cb = self.checkBoxes[k]
|
||||
result[k] = cb.IsChecked()
|
||||
|
||||
for k in self.textControls.keys():
|
||||
v = self.textControls[k].GetValue()
|
||||
if v == "":
|
||||
if k in self.textControlsOriginal.keys():
|
||||
result[k] = self.textControlsOriginal[k][0], False
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = v, True
|
||||
|
||||
for k in self.radioButtons.keys():
|
||||
result[k] = self.radioButtons[k].GetValue(), True
|
||||
|
||||
for k in self.choices.keys():
|
||||
v = self.choices[k].GetSelection()
|
||||
s = self.choices[k].GetString(v)
|
||||
if s == "-":
|
||||
if k in self.choicesOriginal.keys():
|
||||
result[k] = self.choicesOriginal[k][0], False
|
||||
else:
|
||||
result[k] = "", False
|
||||
else:
|
||||
result[k] = s, True
|
||||
|
||||
for k in self.boolChoices.keys():
|
||||
choice = self.boolChoices[k]
|
||||
for i in range(choice.GetCount()):
|
||||
s = choice.GetClientData(i)
|
||||
if s:
|
||||
result[s] = i == choice.GetSelection()
|
||||
|
||||
return result
|
||||
|
||||
def assertModified(self, flag):
|
||||
if flag != self.modified:
|
||||
self.parent.assertModified(self.id, flag)
|
||||
self.modified = flag
|
||||
|
||||
def setFieldValidity(self, name, flag):
|
||||
self.fieldValid[name] = flag
|
||||
|
||||
pgValid = True
|
||||
for k in self.fieldValid.keys():
|
||||
if not self.fieldValid[k]:
|
||||
pgValid = False
|
||||
break
|
||||
|
||||
self.assertValid(pgValid)
|
||||
|
||||
def assertValid(self, flag):
|
||||
if flag != self.valid:
|
||||
self.parent.assertValid(self.id, flag)
|
||||
self.valid = flag
|
||||
|
|
|
|||
|
|
@ -1,183 +1,211 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
|
||||
|
||||
class PinoutsPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.id = idPg
|
||||
|
||||
pinXkeys = [('X_STEP_PIN', 2), ('X_DIR_PIN', 2), ('X_MIN_PIN', 2),
|
||||
('X_MAX_PIN', 2), ('X_ENABLE_PIN', 2), ('X_INVERT_DIR', 1),
|
||||
('X_INVERT_MIN', 1), ('X_INVERT_MAX', 1),
|
||||
('X_INVERT_ENABLE', 1)]
|
||||
pinYkeys = [('Y_STEP_PIN', 2), ('Y_DIR_PIN', 2), ('Y_MIN_PIN', 2),
|
||||
('Y_MAX_PIN', 2), ('Y_ENABLE_PIN', 2), ('Y_INVERT_DIR', 1),
|
||||
('Y_INVERT_MIN', 1), ('Y_INVERT_MAX', 1),
|
||||
('Y_INVERT_ENABLE', 1)]
|
||||
pinZkeys = [('Z_STEP_PIN', 2), ('Z_DIR_PIN', 2), ('Z_MIN_PIN', 2),
|
||||
('Z_MAX_PIN', 2), ('Z_ENABLE_PIN', 2), ('Z_INVERT_DIR', 1),
|
||||
('Z_INVERT_MIN', 1), ('Z_INVERT_MAX', 1),
|
||||
('Z_INVERT_ENABLE', 1)]
|
||||
pinEkeys = [('E_STEP_PIN', 2), ('E_DIR_PIN', 2), ('E_ENABLE_PIN', 2),
|
||||
('E_INVERT_DIR', 1), ('E_INVERT_ENABLE', 1)]
|
||||
pinXkeys = [
|
||||
("X_STEP_PIN", 2),
|
||||
("X_DIR_PIN", 2),
|
||||
("X_MIN_PIN", 2),
|
||||
("X_MAX_PIN", 2),
|
||||
("X_ENABLE_PIN", 2),
|
||||
("X_INVERT_DIR", 1),
|
||||
("X_INVERT_MIN", 1),
|
||||
("X_INVERT_MAX", 1),
|
||||
("X_INVERT_ENABLE", 1),
|
||||
]
|
||||
pinYkeys = [
|
||||
("Y_STEP_PIN", 2),
|
||||
("Y_DIR_PIN", 2),
|
||||
("Y_MIN_PIN", 2),
|
||||
("Y_MAX_PIN", 2),
|
||||
("Y_ENABLE_PIN", 2),
|
||||
("Y_INVERT_DIR", 1),
|
||||
("Y_INVERT_MIN", 1),
|
||||
("Y_INVERT_MAX", 1),
|
||||
("Y_INVERT_ENABLE", 1),
|
||||
]
|
||||
pinZkeys = [
|
||||
("Z_STEP_PIN", 2),
|
||||
("Z_DIR_PIN", 2),
|
||||
("Z_MIN_PIN", 2),
|
||||
("Z_MAX_PIN", 2),
|
||||
("Z_ENABLE_PIN", 2),
|
||||
("Z_INVERT_DIR", 1),
|
||||
("Z_INVERT_MIN", 1),
|
||||
("Z_INVERT_MAX", 1),
|
||||
("Z_INVERT_ENABLE", 1),
|
||||
]
|
||||
pinEkeys = [
|
||||
("E_STEP_PIN", 2),
|
||||
("E_DIR_PIN", 2),
|
||||
("E_ENABLE_PIN", 2),
|
||||
("E_INVERT_DIR", 1),
|
||||
("E_INVERT_ENABLE", 1),
|
||||
]
|
||||
|
||||
self.labels = {'X_STEP_PIN': "Step Pin:", 'X_DIR_PIN': "Direction Pin:",
|
||||
'X_MIN_PIN': "Minimum Pin:", 'X_MAX_PIN': "Maximum Pin:",
|
||||
'X_ENABLE_PIN': "Enable Pin:",
|
||||
'X_INVERT_DIR': "Invert Direction",
|
||||
'X_INVERT_MIN': "Invert Minimum",
|
||||
'X_INVERT_MAX': "Invert Maximum",
|
||||
'X_INVERT_ENABLE': "Invert Enable",
|
||||
self.labels = {
|
||||
"X_STEP_PIN": "Step Pin:",
|
||||
"X_DIR_PIN": "Direction Pin:",
|
||||
"X_MIN_PIN": "Minimum Pin:",
|
||||
"X_MAX_PIN": "Maximum Pin:",
|
||||
"X_ENABLE_PIN": "Enable Pin:",
|
||||
"X_INVERT_DIR": "Invert Direction",
|
||||
"X_INVERT_MIN": "Invert Minimum",
|
||||
"X_INVERT_MAX": "Invert Maximum",
|
||||
"X_INVERT_ENABLE": "Invert Enable",
|
||||
"Y_STEP_PIN": "Step Pin:",
|
||||
"Y_DIR_PIN": "Direction Pin:",
|
||||
"Y_MIN_PIN": "Minimum Pin:",
|
||||
"Y_MAX_PIN": "Maximum Pin:",
|
||||
"Y_ENABLE_PIN": "Enable Pin:",
|
||||
"Y_INVERT_DIR": "Invert Direction",
|
||||
"Y_INVERT_MIN": "Invert Minimum",
|
||||
"Y_INVERT_MAX": "Invert Maximum",
|
||||
"Y_INVERT_ENABLE": "Invert Enable",
|
||||
"Z_STEP_PIN": "Step Pin:",
|
||||
"Z_DIR_PIN": "Direction Pin:",
|
||||
"Z_MIN_PIN": "Minimum Pin:",
|
||||
"Z_MAX_PIN": "Maximum Pin:",
|
||||
"Z_ENABLE_PIN": "Enable Pin:",
|
||||
"Z_INVERT_DIR": "Invert Direction",
|
||||
"Z_INVERT_MIN": "Invert Minimum",
|
||||
"Z_INVERT_MAX": "Invert Maximum",
|
||||
"Z_INVERT_ENABLE": "Invert Enable",
|
||||
"E_STEP_PIN": "Step Pin:",
|
||||
"E_DIR_PIN": "Direction Pin:",
|
||||
"E_ENABLE_PIN": "Enable Pin:",
|
||||
"E_INVERT_DIR": "Invert Direction",
|
||||
"E_INVERT_ENABLE": "Invert Enable",
|
||||
"PS_ON_PIN": "PSU On Pin:",
|
||||
"PS_INVERT_ON": "Invert PSU On Pin",
|
||||
"PS_MOSFET_PIN": "PSU MOSFET Pin:",
|
||||
"STEPPER_ENABLE_PIN": "Stepper Enable Pin:",
|
||||
"STEPPER_INVERT_ENABLE": "Stepper Invert Enable",
|
||||
"SD_CARD_SELECT_PIN": "SD Card Pin:",
|
||||
"DEBUG_LED_PIN": "Debug LED Pin:",
|
||||
}
|
||||
|
||||
'Y_STEP_PIN': "Step Pin:", 'Y_DIR_PIN': "Direction Pin:",
|
||||
'Y_MIN_PIN': "Minimum Pin:", 'Y_MAX_PIN': "Maximum Pin:",
|
||||
'Y_ENABLE_PIN': "Enable Pin:",
|
||||
'Y_INVERT_DIR': "Invert Direction",
|
||||
'Y_INVERT_MIN': "Invert Minimum",
|
||||
'Y_INVERT_MAX': "Invert Maximum",
|
||||
'Y_INVERT_ENABLE': "Invert Enable",
|
||||
labelWidth = 120
|
||||
|
||||
'Z_STEP_PIN': "Step Pin:", 'Z_DIR_PIN': "Direction Pin:",
|
||||
'Z_MIN_PIN': "Minimum Pin:", 'Z_MAX_PIN': "Maximum Pin:",
|
||||
'Z_ENABLE_PIN': "Enable Pin:",
|
||||
'Z_INVERT_DIR': "Invert Direction",
|
||||
'Z_INVERT_MIN': "Invert Minimum",
|
||||
'Z_INVERT_MAX': "Invert Maximum",
|
||||
'Z_INVERT_ENABLE': "Invert Enable",
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos=(0, 0))
|
||||
|
||||
'E_STEP_PIN': "Step Pin:", 'E_DIR_PIN': "Direction Pin:",
|
||||
'E_ENABLE_PIN': "Enable Pin:",
|
||||
'E_INVERT_DIR': "Invert Direction",
|
||||
'E_INVERT_ENABLE': "Invert Enable",
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "X Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinXkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
|
||||
'PS_ON_PIN': "PSU On Pin:",
|
||||
'PS_INVERT_ON': "Invert PSU On Pin",
|
||||
'PS_MOSFET_PIN': "PSU MOSFET Pin:",
|
||||
sbox.Add((5, 5))
|
||||
|
||||
'STEPPER_ENABLE_PIN': "Stepper Enable Pin:",
|
||||
'STEPPER_INVERT_ENABLE': "Stepper Invert Enable",
|
||||
sz.Add(sbox, pos=(1, 1))
|
||||
|
||||
'SD_CARD_SELECT_PIN': "SD Card Pin:",
|
||||
'DEBUG_LED_PIN': "Debug LED Pin:"}
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Y Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinYkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
|
||||
labelWidth = 120
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos = (0, 0))
|
||||
sz.Add(sbox, pos=(1, 3))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "X Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinXkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Z Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinZkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos=(1, 5))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "E Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinEkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos=(1, 7))
|
||||
|
||||
k = "STEPPER_ENABLE_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth + 20)
|
||||
sz.Add(tc, pos=(3, 1))
|
||||
|
||||
sz.Add((10, 10), pos=(4, 1))
|
||||
|
||||
k = "STEPPER_INVERT_ENABLE"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
sz.Add(cb, pos=(5, 1), flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 1))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Y Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinYkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
k = "PS_ON_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
sz.Add(tc, pos=(3, 3))
|
||||
|
||||
k = "PS_INVERT_ON"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
sz.Add(cb, pos=(5, 3), flag=wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 3))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Z Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinZkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
k = "PS_MOSFET_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
sz.Add(tc, pos=(7, 3))
|
||||
|
||||
sbox.Add((5, 5))
|
||||
|
||||
sz.Add(sbox, pos = (1, 5))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "E Axis")
|
||||
b.SetFont(font)
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
sbox.Add((5, 5))
|
||||
for k, ctype in pinEkeys:
|
||||
if ctype == 0:
|
||||
tc = self.addTextCtrl(k, labelWidth, self.onTextCtrlPin)
|
||||
sbox.Add(tc)
|
||||
elif ctype == 2:
|
||||
k = "SD_CARD_SELECT_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sbox.Add(tc)
|
||||
else:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sbox.Add(cb, 1, wx.LEFT, 30)
|
||||
sz.Add(tc, pos=(3, 7))
|
||||
|
||||
sbox.Add((5, 5))
|
||||
k = "DEBUG_LED_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos=(5, 7))
|
||||
|
||||
sz.Add(sbox, pos = (1, 7))
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
k = "STEPPER_ENABLE_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth + 20)
|
||||
sz.Add(tc, pos = (3, 1))
|
||||
|
||||
sz.Add((10, 10), pos = (4, 1))
|
||||
|
||||
k = "STEPPER_INVERT_ENABLE"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (5, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
k = "PS_ON_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos = (3, 3))
|
||||
|
||||
k = "PS_INVERT_ON"
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
sz.Add(cb, pos = (5, 3), flag = wx.ALIGN_CENTER_HORIZONTAL)
|
||||
|
||||
k = "PS_MOSFET_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos = (7, 3))
|
||||
|
||||
k = "SD_CARD_SELECT_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos = (3, 7))
|
||||
|
||||
k = "DEBUG_LED_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos = (5, 7))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def onChoice(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
def onChoice(self, evt):
|
||||
self.assertModified(True)
|
||||
evt.Skip()
|
||||
|
|
|
|||
|
|
@ -4,314 +4,333 @@ import os
|
|||
import re
|
||||
|
||||
from sys import platform
|
||||
from configtool.data import (defineValueFormat, defineBoolFormat,
|
||||
reHelpTextStart, reHelpTextEnd,
|
||||
reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reDefQSm2, reDefBool, reDefBoolBL,
|
||||
reHomingOpts, reStartHoming, reEndHoming,
|
||||
reDefHoming, reHoming4)
|
||||
from configtool.data import (
|
||||
defineValueFormat,
|
||||
defineBoolFormat,
|
||||
reHelpTextStart,
|
||||
reHelpTextEnd,
|
||||
reDefine,
|
||||
reDefineBL,
|
||||
reDefQS,
|
||||
reDefQSm,
|
||||
reDefQSm2,
|
||||
reDefBool,
|
||||
reDefBoolBL,
|
||||
reHomingOpts,
|
||||
reStartHoming,
|
||||
reEndHoming,
|
||||
reDefHoming,
|
||||
reHoming4,
|
||||
)
|
||||
|
||||
|
||||
class Printer:
|
||||
def __init__(self, settings):
|
||||
self.configFile = None
|
||||
def __init__(self, settings):
|
||||
self.configFile = None
|
||||
|
||||
self.cfgValues = {}
|
||||
self.settings = settings
|
||||
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
||||
self.cfgValues = {}
|
||||
self.settings = settings
|
||||
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
||||
|
||||
def getValues(self):
|
||||
vars = [(x, self.cfgValues[x]) for x in self.cfgValues]
|
||||
return dict(vars)
|
||||
def getValues(self):
|
||||
vars = [(x, self.cfgValues[x]) for x in self.cfgValues]
|
||||
return dict(vars)
|
||||
|
||||
def hasData(self):
|
||||
return (self.configFile != None)
|
||||
def hasData(self):
|
||||
return self.configFile != None
|
||||
|
||||
def getFileName(self):
|
||||
return self.configFile
|
||||
def getFileName(self):
|
||||
return self.configFile
|
||||
|
||||
def loadConfigFile(self, fn):
|
||||
cfgFn = os.path.join(self.cfgDir, "printer.generic.h")
|
||||
try:
|
||||
self.cfgBuffer = list(open(cfgFn))
|
||||
except:
|
||||
return False, cfgFn
|
||||
def loadConfigFile(self, fn):
|
||||
cfgFn = os.path.join(self.cfgDir, "printer.generic.h")
|
||||
try:
|
||||
self.cfgBuffer = list(open(cfgFn))
|
||||
except:
|
||||
return False, cfgFn
|
||||
|
||||
try:
|
||||
self.userBuffer = list(open(fn))
|
||||
except:
|
||||
return False, fn
|
||||
try:
|
||||
self.userBuffer = list(open(fn))
|
||||
except:
|
||||
return False, fn
|
||||
|
||||
self.configFile = fn
|
||||
self.configFile = fn
|
||||
|
||||
gatheringHelpText = False
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
gatheringHelpText = False
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
|
||||
self.cfgValues = {}
|
||||
self.cfgNames = []
|
||||
self.helpText = {}
|
||||
self.cfgValues = {}
|
||||
self.cfgNames = []
|
||||
self.helpText = {}
|
||||
|
||||
prevLines = ""
|
||||
for ln in self.cfgBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
helpTextString = helpTextString.strip()
|
||||
# Keep paragraphs with double-newline.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n")
|
||||
# Keep indented lines, typically a list.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n ")
|
||||
helpTextString = helpTextString.replace("\n ", "\n\n ")
|
||||
# Remove all other newlines and indents.
|
||||
helpTextString = helpTextString.replace("\n ", " ")
|
||||
hk = helpKey.split()
|
||||
for k in hk:
|
||||
self.helpText[k] = helpTextString
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
continue
|
||||
else:
|
||||
helpTextString += ln
|
||||
continue
|
||||
|
||||
m = reHelpTextStart.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
gatheringHelpText = True
|
||||
helpKey = t[0]
|
||||
continue
|
||||
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
for ln in self.cfgBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
helpTextString = helpTextString.strip()
|
||||
# Keep paragraphs with double-newline.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n")
|
||||
# Keep indented lines, typically a list.
|
||||
helpTextString = helpTextString.replace("\n\n ", "\n\n ")
|
||||
helpTextString = helpTextString.replace("\n ", "\n\n ")
|
||||
# Remove all other newlines and indents.
|
||||
helpTextString = helpTextString.replace("\n ", " ")
|
||||
hk = helpKey.split()
|
||||
for k in hk:
|
||||
self.helpText[k] = helpTextString
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
continue
|
||||
else:
|
||||
helpTextString += ln
|
||||
continue
|
||||
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
m = reHelpTextStart.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
gatheringHelpText = True
|
||||
helpKey = t[0]
|
||||
continue
|
||||
|
||||
if self.parseHoming(ln):
|
||||
continue
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
self.parseDefineName(ln)
|
||||
self.parseDefineValue(ln)
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
|
||||
# Set all boolean generic configuration items to False, so items not yet
|
||||
# existing in the user configuration default to disabled.
|
||||
for k in self.cfgValues.keys():
|
||||
if isinstance(self.cfgValues[k], bool):
|
||||
self.cfgValues[k] = False
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
|
||||
# Read the user configuration. This usually overwrites all of the items
|
||||
# read above, but not those missing in the user configuration, e.g.
|
||||
# when reading an older config.
|
||||
gatheringHelpText = False
|
||||
prevLines = ""
|
||||
for ln in self.userBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
continue
|
||||
if self.parseHoming(ln):
|
||||
continue
|
||||
|
||||
if reHelpTextStart.match(ln):
|
||||
gatheringHelpText = True
|
||||
continue
|
||||
self.parseDefineName(ln)
|
||||
self.parseDefineValue(ln)
|
||||
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
# Set all boolean generic configuration items to False, so items not yet
|
||||
# existing in the user configuration default to disabled.
|
||||
for k in self.cfgValues.keys():
|
||||
if isinstance(self.cfgValues[k], bool):
|
||||
self.cfgValues[k] = False
|
||||
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
# Read the user configuration. This usually overwrites all of the items
|
||||
# read above, but not those missing in the user configuration, e.g.
|
||||
# when reading an older config.
|
||||
gatheringHelpText = False
|
||||
prevLines = ""
|
||||
for ln in self.userBuffer:
|
||||
if gatheringHelpText:
|
||||
if reHelpTextEnd.match(ln):
|
||||
gatheringHelpText = False
|
||||
continue
|
||||
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
if reHelpTextStart.match(ln):
|
||||
gatheringHelpText = True
|
||||
continue
|
||||
|
||||
if self.parseHoming(ln):
|
||||
continue
|
||||
if ln.rstrip().endswith("\\"):
|
||||
prevLines += ln.rstrip()[:-1]
|
||||
continue
|
||||
|
||||
self.parseDefineValue(ln)
|
||||
if prevLines != "":
|
||||
ln = prevLines + ln
|
||||
prevLines = ""
|
||||
|
||||
# Parsing done. All parsed stuff is now in these array and dicts.
|
||||
if self.settings.verbose >= 2:
|
||||
print(self.cfgValues) # #defines with a value.
|
||||
print(self.cfgNames) # Names found in the generic file.
|
||||
if self.settings.verbose >= 3:
|
||||
print(self.helpText)
|
||||
if self.parseCandidateValues(ln):
|
||||
continue
|
||||
|
||||
return True, None
|
||||
if self.parseHoming(ln):
|
||||
continue
|
||||
|
||||
def parseDefineName(self, ln):
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.cfgNames.append(t[0])
|
||||
return True
|
||||
self.parseDefineValue(ln)
|
||||
|
||||
return False
|
||||
# Parsing done. All parsed stuff is now in these array and dicts.
|
||||
if self.settings.verbose >= 2:
|
||||
print(self.cfgValues) # #defines with a value.
|
||||
print(self.cfgNames) # Names found in the generic file.
|
||||
if self.settings.verbose >= 3:
|
||||
print(self.helpText)
|
||||
|
||||
def parseCandidateValues(self, ln):
|
||||
m = reHomingOpts.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
if 'HOMING_OPTS' in self.cfgValues:
|
||||
if t[0] not in self.cfgValues['HOMING_OPTS']:
|
||||
self.cfgValues['HOMING_OPTS'].append(t[0])
|
||||
else:
|
||||
self.cfgValues['HOMING_OPTS'] = [t[0]]
|
||||
return True
|
||||
return True, None
|
||||
|
||||
def parseHoming(self, ln):
|
||||
m = reDefHoming.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
n = reHoming4.search(t[0])
|
||||
if n:
|
||||
u = n.groups()
|
||||
if len(u) == 4:
|
||||
t2 = []
|
||||
for x in u:
|
||||
t2.append(x)
|
||||
|
||||
self.cfgValues['HOMING_STEP1'] = t2[0]
|
||||
self.cfgValues['HOMING_STEP2'] = t2[1]
|
||||
self.cfgValues['HOMING_STEP3'] = t2[2]
|
||||
self.cfgValues['HOMING_STEP4'] = t2[3]
|
||||
|
||||
return True
|
||||
return None
|
||||
return True
|
||||
|
||||
def parseDefineValue(self, ln):
|
||||
m = reDefQS.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
m = reDefQSm.search(ln)
|
||||
def parseDefineName(self, ln):
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
tt = re.findall(reDefQSm2, t[1])
|
||||
if len(tt) == 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt[0], True
|
||||
return True
|
||||
elif len(tt) > 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt, True
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.cfgNames.append(t[0])
|
||||
return True
|
||||
|
||||
m = reDefine.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and (t[0] in self.cfgNames):
|
||||
if reDefineBL.search(ln):
|
||||
self.cfgValues[t[0]] = t[1], True
|
||||
else:
|
||||
self.cfgValues[t[0]] = t[1], False
|
||||
return True
|
||||
return False
|
||||
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
# Accept booleans, but not those for which a value exists already.
|
||||
# Booleans already existing as values are most likely misconfigured
|
||||
# manual edits (or result of a bug).
|
||||
if len(t) == 1 and t[0] in self.cfgNames \
|
||||
and not (t[0] in self.cfgValues \
|
||||
and isinstance(self.cfgValues[t[0]], tuple)):
|
||||
if reDefBoolBL.search(ln):
|
||||
self.cfgValues[t[0]] = True
|
||||
else:
|
||||
self.cfgValues[t[0]] = False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def saveConfigFile(self, path, values):
|
||||
if not values:
|
||||
values = self.cfgValues
|
||||
|
||||
if self.settings.verbose >= 1:
|
||||
print("Saving printer: %s." % path)
|
||||
if self.settings.verbose >= 2:
|
||||
print(values)
|
||||
|
||||
fp = file(path, 'w')
|
||||
self.configFile = path
|
||||
|
||||
skipToHomingEnd = False
|
||||
|
||||
for ln in self.cfgBuffer:
|
||||
m = reStartHoming.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
sstr = "%s, %s, %s, %s" % ((values['HOMING_STEP1']),
|
||||
(values['HOMING_STEP2']),
|
||||
(values['HOMING_STEP3']),
|
||||
(values['HOMING_STEP4']))
|
||||
fp.write("DEFINE_HOMING(%s)\n" % sstr)
|
||||
skipToHomingEnd = True
|
||||
continue
|
||||
|
||||
if skipToHomingEnd:
|
||||
m = reEndHoming.match(ln)
|
||||
def parseCandidateValues(self, ln):
|
||||
m = reHomingOpts.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToHomingEnd = False
|
||||
continue
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
if "HOMING_OPTS" in self.cfgValues:
|
||||
if t[0] not in self.cfgValues["HOMING_OPTS"]:
|
||||
self.cfgValues["HOMING_OPTS"].append(t[0])
|
||||
else:
|
||||
self.cfgValues["HOMING_OPTS"] = [t[0]]
|
||||
return True
|
||||
|
||||
def parseHoming(self, ln):
|
||||
m = reDefHoming.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
n = reHoming4.search(t[0])
|
||||
if n:
|
||||
u = n.groups()
|
||||
if len(u) == 4:
|
||||
t2 = []
|
||||
for x in u:
|
||||
t2.append(x)
|
||||
|
||||
self.cfgValues["HOMING_STEP1"] = t2[0]
|
||||
self.cfgValues["HOMING_STEP2"] = t2[1]
|
||||
self.cfgValues["HOMING_STEP3"] = t2[2]
|
||||
self.cfgValues["HOMING_STEP4"] = t2[3]
|
||||
|
||||
return True
|
||||
return None
|
||||
return True
|
||||
|
||||
def parseDefineValue(self, ln):
|
||||
m = reDefQS.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2:
|
||||
m = reDefQSm.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
tt = re.findall(reDefQSm2, t[1])
|
||||
if len(tt) == 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt[0], True
|
||||
return True
|
||||
elif len(tt) > 1 and (t[0] in self.cfgNames):
|
||||
self.cfgValues[t[0]] = tt, True
|
||||
return True
|
||||
|
||||
m = reDefine.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and (t[0] in self.cfgNames):
|
||||
if reDefineBL.search(ln):
|
||||
self.cfgValues[t[0]] = t[1], True
|
||||
else:
|
||||
self.cfgValues[t[0]] = t[1], False
|
||||
return True
|
||||
|
||||
m = reDefBool.search(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
# Accept booleans, but not those for which a value exists already.
|
||||
# Booleans already existing as values are most likely misconfigured
|
||||
# manual edits (or result of a bug).
|
||||
if (
|
||||
len(t) == 1
|
||||
and t[0] in self.cfgNames
|
||||
and not (
|
||||
t[0] in self.cfgValues and isinstance(self.cfgValues[t[0]], tuple)
|
||||
)
|
||||
):
|
||||
if reDefBoolBL.search(ln):
|
||||
self.cfgValues[t[0]] = True
|
||||
else:
|
||||
self.cfgValues[t[0]] = False
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def saveConfigFile(self, path, values):
|
||||
if not values:
|
||||
values = self.cfgValues
|
||||
|
||||
if self.settings.verbose >= 1:
|
||||
print("Saving printer: %s." % path)
|
||||
if self.settings.verbose >= 2:
|
||||
print(values)
|
||||
|
||||
fp = file(path, "w")
|
||||
self.configFile = path
|
||||
|
||||
skipToHomingEnd = False
|
||||
|
||||
for ln in self.cfgBuffer:
|
||||
m = reStartHoming.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
sstr = "%s, %s, %s, %s" % (
|
||||
(values["HOMING_STEP1"]),
|
||||
(values["HOMING_STEP2"]),
|
||||
(values["HOMING_STEP3"]),
|
||||
(values["HOMING_STEP4"]),
|
||||
)
|
||||
fp.write("DEFINE_HOMING(%s)\n" % sstr)
|
||||
skipToHomingEnd = True
|
||||
continue
|
||||
|
||||
if skipToHomingEnd:
|
||||
m = reEndHoming.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToHomingEnd = False
|
||||
continue
|
||||
|
||||
m = reDefine.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v[1] == False:
|
||||
fp.write("//")
|
||||
fp.write(defineValueFormat % (t[0], v[0]))
|
||||
else:
|
||||
if t[0] == "CANNED_CYCLE":
|
||||
# Known to be absent in the GUI. Worse, this value is replaced
|
||||
# by the one in the metadata file.
|
||||
#
|
||||
# TODO: make value reading above recognize wether this value is
|
||||
# commented out or not. Reading the value its self works
|
||||
# already. Hint: it's the rule using reDefQS, reDefQSm, etc.
|
||||
#
|
||||
# TODO: add a multiline text field in the GUI to deal with this.
|
||||
#
|
||||
# TODO: write this value out properly. In /* comments */, if
|
||||
# disabled.
|
||||
#
|
||||
# TODO: currently, the lines beyond the ones with the #define are
|
||||
# treated like arbitrary comments. Having the former TODOs
|
||||
# done, this will lead to duplicates.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Value key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
m = reDefBoolBL.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v == "" or v == False:
|
||||
fp.write("//")
|
||||
fp.write(defineBoolFormat % t[0])
|
||||
else:
|
||||
print("Boolean key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
m = reDefine.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 2 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v[1] == False:
|
||||
fp.write("//")
|
||||
fp.write(defineValueFormat % (t[0], v[0]))
|
||||
else:
|
||||
if t[0] == 'CANNED_CYCLE':
|
||||
# Known to be absent in the GUI. Worse, this value is replaced
|
||||
# by the one in the metadata file.
|
||||
#
|
||||
# TODO: make value reading above recognize wether this value is
|
||||
# commented out or not. Reading the value its self works
|
||||
# already. Hint: it's the rule using reDefQS, reDefQSm, etc.
|
||||
#
|
||||
# TODO: add a multiline text field in the GUI to deal with this.
|
||||
#
|
||||
# TODO: write this value out properly. In /* comments */, if
|
||||
# disabled.
|
||||
#
|
||||
# TODO: currently, the lines beyond the ones with the #define are
|
||||
# treated like arbitrary comments. Having the former TODOs
|
||||
# done, this will lead to duplicates.
|
||||
fp.write(ln)
|
||||
else:
|
||||
print("Value key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
fp.close()
|
||||
|
||||
m = reDefBoolBL.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1 and t[0] in values.keys():
|
||||
v = values[t[0]]
|
||||
self.cfgValues[t[0]] = v
|
||||
if v == "" or v == False:
|
||||
fp.write("//")
|
||||
fp.write(defineBoolFormat % t[0])
|
||||
else:
|
||||
print("Boolean key " + t[0] + " not found in GUI.")
|
||||
|
||||
continue
|
||||
|
||||
fp.write(ln)
|
||||
|
||||
fp.close()
|
||||
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,14 +1,22 @@
|
|||
|
||||
import os
|
||||
import wx
|
||||
import re
|
||||
|
||||
from sys import platform
|
||||
from configtool.decoration import Decoration
|
||||
from configtool.data import (defineValueFormat, defineBoolFormat,
|
||||
reHelpTextStart, reHelpTextEnd,
|
||||
reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reDefQSm2, reDefBool, reDefBoolBL)
|
||||
from configtool.data import (
|
||||
defineValueFormat,
|
||||
defineBoolFormat,
|
||||
reHelpTextStart,
|
||||
reHelpTextEnd,
|
||||
reDefine,
|
||||
reDefineBL,
|
||||
reDefQS,
|
||||
reDefQSm,
|
||||
reDefQSm2,
|
||||
reDefBool,
|
||||
reDefBoolBL,
|
||||
)
|
||||
from configtool.mechanicalpage import MechanicalPage
|
||||
from configtool.accelerationpage import AccelerationPage
|
||||
from configtool.miscellaneouspage import MiscellaneousPage
|
||||
|
|
@ -17,249 +25,277 @@ from configtool.printer import Printer
|
|||
|
||||
|
||||
class PrinterPanel(wx.Panel):
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
|
||||
self.deco = Decoration()
|
||||
self.protFileLoaded = False
|
||||
self.deco = Decoration()
|
||||
self.protFileLoaded = False
|
||||
|
||||
self.settings = settings
|
||||
self.settings = settings
|
||||
|
||||
self.printer = Printer(self.settings)
|
||||
self.printer = Printer(self.settings)
|
||||
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground)
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21),
|
||||
style = wx.BK_DEFAULT)
|
||||
self.nb.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.nb.SetFont(self.settings.font)
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size=(21, 21), style=wx.BK_DEFAULT)
|
||||
self.nb.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.nb.SetFont(self.settings.font)
|
||||
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
|
||||
self.pgMech = self.registerPage(MechanicalPage, "Mechanical")
|
||||
self.pgAcc = self.registerPage(AccelerationPage, "Acceleration")
|
||||
self.pgMiscellaneous = self.registerPage(MiscellaneousPage,
|
||||
"Miscellaneous")
|
||||
self.pgMech = self.registerPage(MechanicalPage, "Mechanical")
|
||||
self.pgAcc = self.registerPage(AccelerationPage, "Acceleration")
|
||||
self.pgMiscellaneous = self.registerPage(MiscellaneousPage, "Miscellaneous")
|
||||
|
||||
sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5)
|
||||
sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5)
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.Fit()
|
||||
self.SetSizer(sz)
|
||||
self.Fit()
|
||||
|
||||
def registerPage(self, klass, label, *args, **kwargs):
|
||||
page = klass(self, self.nb, len(self.pages), *args,
|
||||
font = self.settings.font, **kwargs)
|
||||
self.nb.AddPage(page, label)
|
||||
self.pages.append(page)
|
||||
self.titles.append(label)
|
||||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
return page
|
||||
def registerPage(self, klass, label, *args, **kwargs):
|
||||
page = klass(
|
||||
self, self.nb, len(self.pages), *args, font=self.settings.font, **kwargs
|
||||
)
|
||||
self.nb.AddPage(page, label)
|
||||
self.pages.append(page)
|
||||
self.titles.append(label)
|
||||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
return page
|
||||
|
||||
def assertModified(self, pg, flag = True):
|
||||
self.pageModified[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
def assertModified(self, pg, flag=True):
|
||||
self.pageModified[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
||||
def isModified(self):
|
||||
return (True in self.pageModified)
|
||||
def isModified(self):
|
||||
return True in self.pageModified
|
||||
|
||||
def isValid(self):
|
||||
return not (False in self.pageValid)
|
||||
def isValid(self):
|
||||
return not (False in self.pageValid)
|
||||
|
||||
def hasData(self):
|
||||
return self.printer.hasData()
|
||||
def hasData(self):
|
||||
return self.printer.hasData()
|
||||
|
||||
def getFileName(self):
|
||||
return self.printer.configFile
|
||||
def getFileName(self):
|
||||
return self.printer.configFile
|
||||
|
||||
def assertValid(self, pg, flag = True):
|
||||
self.pageValid[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
def assertValid(self, pg, flag=True):
|
||||
self.pageValid[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
||||
if False in self.pageValid:
|
||||
self.parent.enableSavePrinter(False, False)
|
||||
else:
|
||||
self.parent.enableSavePrinter(not self.protFileLoaded, True)
|
||||
if False in self.pageValid:
|
||||
self.parent.enableSavePrinter(False, False)
|
||||
else:
|
||||
self.parent.enableSavePrinter(not self.protFileLoaded, True)
|
||||
|
||||
def modifyTab(self, pg):
|
||||
if self.pageModified[pg] and not self.pageValid[pg]:
|
||||
pfx = "?* "
|
||||
elif self.pageModified[pg]:
|
||||
pfx = "* "
|
||||
elif not self.pageValid[pg]:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
def modifyTab(self, pg):
|
||||
if self.pageModified[pg] and not self.pageValid[pg]:
|
||||
pfx = "?* "
|
||||
elif self.pageModified[pg]:
|
||||
pfx = "* "
|
||||
elif not self.pageValid[pg]:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setPrinterTabDecor(pfx)
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setPrinterTabDecor(pfx)
|
||||
|
||||
def setHeaters(self, ht):
|
||||
return self.pgMiscellaneous.setHeaters(ht)
|
||||
def setHeaters(self, ht):
|
||||
return self.pgMiscellaneous.setHeaters(ht)
|
||||
|
||||
def onClose(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
def onClose(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
|
||||
self.Destroy()
|
||||
self.Destroy()
|
||||
|
||||
def confirmLoseChanges(self, msg):
|
||||
if True not in self.pageModified:
|
||||
return True
|
||||
def confirmLoseChanges(self, msg):
|
||||
if True not in self.pageModified:
|
||||
return True
|
||||
|
||||
dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your printer "
|
||||
"configuration that will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your printer "
|
||||
"configuration that will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def onLoadConfig(self, evt):
|
||||
if not self.confirmLoseChanges("load a new printer configuration"):
|
||||
return
|
||||
def onLoadConfig(self, evt):
|
||||
if not self.confirmLoseChanges("load a new printer configuration"):
|
||||
return
|
||||
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Printer configuration (printer.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Printer configuration (printer.*.h)|printer.*.h"
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Printer configuration (printer.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Printer configuration (printer.*.h)|printer.*.h"
|
||||
|
||||
dlg = wx.FileDialog(self, message = "Choose a printer config file",
|
||||
defaultDir = self.dir, defaultFile = "",
|
||||
wildcard = wildcard, style = wx.FD_OPEN | wx.FD_CHANGE_DIR)
|
||||
dlg = wx.FileDialog(
|
||||
self,
|
||||
message="Choose a printer config file",
|
||||
defaultDir=self.dir,
|
||||
defaultFile="",
|
||||
wildcard=wildcard,
|
||||
style=wx.FD_OPEN | wx.FD_CHANGE_DIR,
|
||||
)
|
||||
|
||||
path = None
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
path = None
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
path = dlg.GetPath()
|
||||
|
||||
dlg.Destroy()
|
||||
if path is None:
|
||||
return
|
||||
dlg.Destroy()
|
||||
if path is None:
|
||||
return
|
||||
|
||||
self.dir = os.path.dirname(path)
|
||||
rc, efn = self.loadConfigFile(path)
|
||||
self.dir = os.path.dirname(path)
|
||||
rc, efn = self.loadConfigFile(path)
|
||||
|
||||
if not rc:
|
||||
dlg = wx.MessageDialog(self, "Unable to process file %s." % efn,
|
||||
"File error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
if not rc:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Unable to process file %s." % efn,
|
||||
"File error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
|
||||
def loadConfigFile(self, fn):
|
||||
ok, file = self.printer.loadConfigFile(fn)
|
||||
if not ok:
|
||||
return ok, file
|
||||
def loadConfigFile(self, fn):
|
||||
ok, file = self.printer.loadConfigFile(fn)
|
||||
if not ok:
|
||||
return ok, file
|
||||
|
||||
if os.path.basename(fn) in protectedFiles:
|
||||
self.parent.enableSavePrinter(False, True)
|
||||
self.protFileLoaded = True
|
||||
else:
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSavePrinter(True, True)
|
||||
self.parent.setPrinterTabFile(os.path.basename(fn))
|
||||
if os.path.basename(fn) in protectedFiles:
|
||||
self.parent.enableSavePrinter(False, True)
|
||||
self.protFileLoaded = True
|
||||
else:
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSavePrinter(True, True)
|
||||
self.parent.setPrinterTabFile(os.path.basename(fn))
|
||||
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.printer.cfgValues)
|
||||
pg.setHelpText(self.printer.helpText)
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.printer.cfgValues)
|
||||
pg.setHelpText(self.printer.helpText)
|
||||
|
||||
k = 'DC_EXTRUDER'
|
||||
if k in self.printer.cfgValues.keys() and self.printer.cfgValues[k][1] == True:
|
||||
self.pgMiscellaneous.setOriginalHeater(self.printer.cfgValues[k][0])
|
||||
else:
|
||||
self.pgMiscellaneous.setOriginalHeater(None)
|
||||
k = "DC_EXTRUDER"
|
||||
if k in self.printer.cfgValues.keys() and self.printer.cfgValues[k][1] == True:
|
||||
self.pgMiscellaneous.setOriginalHeater(self.printer.cfgValues[k][0])
|
||||
else:
|
||||
self.pgMiscellaneous.setOriginalHeater(None)
|
||||
|
||||
return True, None
|
||||
return True, None
|
||||
|
||||
def onSaveConfig(self, evt):
|
||||
path = self.getFileName()
|
||||
return self.saveConfigFile(path)
|
||||
def onSaveConfig(self, evt):
|
||||
path = self.getFileName()
|
||||
return self.saveConfigFile(path)
|
||||
|
||||
def onSaveConfigAs(self, evt):
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Printer configuration (printer.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Printer configuration (printer.*.h)|printer.*.h"
|
||||
def onSaveConfigAs(self, evt):
|
||||
if platform.startswith("darwin"):
|
||||
# Mac OS X appears to be a bit limited on wildcards.
|
||||
wildcard = "Printer configuration (printer.*.h)|*.h"
|
||||
else:
|
||||
wildcard = "Printer configuration (printer.*.h)|printer.*.h"
|
||||
|
||||
dlg = wx.FileDialog(self, message = "Save as ...", defaultDir = self.dir,
|
||||
defaultFile = "", wildcard = wildcard,
|
||||
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
|
||||
dlg = wx.FileDialog(
|
||||
self,
|
||||
message="Save as ...",
|
||||
defaultDir=self.dir,
|
||||
defaultFile="",
|
||||
wildcard=wildcard,
|
||||
style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT,
|
||||
)
|
||||
|
||||
val = dlg.ShowModal()
|
||||
val = dlg.ShowModal()
|
||||
|
||||
if val != wx.ID_OK:
|
||||
dlg.Destroy()
|
||||
return
|
||||
if val != wx.ID_OK:
|
||||
dlg.Destroy()
|
||||
return
|
||||
|
||||
path = dlg.GetPath()
|
||||
dlg.Destroy()
|
||||
path = dlg.GetPath()
|
||||
dlg.Destroy()
|
||||
|
||||
rc = self.saveConfigFile(path)
|
||||
if rc:
|
||||
self.parent.setPrinterTabFile(os.path.basename(path))
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSavePrinter(True, True)
|
||||
return rc
|
||||
rc = self.saveConfigFile(path)
|
||||
if rc:
|
||||
self.parent.setPrinterTabFile(os.path.basename(path))
|
||||
self.protFileLoaded = False
|
||||
self.parent.enableSavePrinter(True, True)
|
||||
return rc
|
||||
|
||||
def saveConfigFile(self, path):
|
||||
if os.path.basename(path) in protectedFiles:
|
||||
dlg = wx.MessageDialog(self, "It's not allowed to overwrite files "
|
||||
"distributed by Teacup. Choose another name.",
|
||||
"Protected file error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
def saveConfigFile(self, path):
|
||||
if os.path.basename(path) in protectedFiles:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"It's not allowed to overwrite files "
|
||||
"distributed by Teacup. Choose another name.",
|
||||
"Protected file error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
if not os.path.basename(path).startswith("printer."):
|
||||
dlg = wx.MessageDialog(self, "Illegal file name: %s.\n"
|
||||
"File name must begin with \"printer.\"" % path,
|
||||
"Illegal file name", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
if not os.path.basename(path).startswith("printer."):
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Illegal file name: %s.\n"
|
||||
'File name must begin with "printer."' % path,
|
||||
"Illegal file name",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
values = {}
|
||||
for pg in self.pages:
|
||||
v1 = pg.getValues()
|
||||
for k in v1.keys():
|
||||
values[k] = v1[k]
|
||||
values = {}
|
||||
for pg in self.pages:
|
||||
v1 = pg.getValues()
|
||||
for k in v1.keys():
|
||||
values[k] = v1[k]
|
||||
|
||||
ext = os.path.splitext(os.path.basename(path))[1]
|
||||
self.dir = os.path.dirname(path)
|
||||
ext = os.path.splitext(os.path.basename(path))[1]
|
||||
self.dir = os.path.dirname(path)
|
||||
|
||||
if ext == "":
|
||||
path += ".h"
|
||||
if ext == "":
|
||||
path += ".h"
|
||||
|
||||
try:
|
||||
self.printer.saveConfigFile(path, values)
|
||||
except:
|
||||
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
|
||||
"File error", wx.OK + wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
try:
|
||||
self.printer.saveConfigFile(path, values)
|
||||
except:
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Unable to write to file %s." % path,
|
||||
"File error",
|
||||
wx.OK + wx.ICON_ERROR,
|
||||
)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
|
||||
protectedFiles = [
|
||||
"board.3drag.h",
|
||||
"board.gen3.h",
|
||||
"board.gen6.h",
|
||||
"board.gen7-arm.h",
|
||||
"board.gen7-v1.1-v1.3.h",
|
||||
"board.gen7-v1.4.h",
|
||||
"board.nanoheart-v1.0.h",
|
||||
"board.ramps-v1.2.h",
|
||||
"board.ramps-v1.3.h",
|
||||
"board.rumba.h",
|
||||
"board.sanguinololu-v1.1.h",
|
||||
"board.sanguinololu-v1.2.h",
|
||||
"board.sanguish.h",
|
||||
"board.teensy-v2.0.h",
|
||||
"board.teensy++-v2.0.h",
|
||||
"printer.mendel.h",
|
||||
"printer.wolfstrap.h"
|
||||
"board.3drag.h",
|
||||
"board.gen3.h",
|
||||
"board.gen6.h",
|
||||
"board.gen7-arm.h",
|
||||
"board.gen7-v1.1-v1.3.h",
|
||||
"board.gen7-v1.4.h",
|
||||
"board.nanoheart-v1.0.h",
|
||||
"board.ramps-v1.2.h",
|
||||
"board.ramps-v1.3.h",
|
||||
"board.rumba.h",
|
||||
"board.sanguinololu-v1.1.h",
|
||||
"board.sanguinololu-v1.2.h",
|
||||
"board.sanguish.h",
|
||||
"board.teensy-v2.0.h",
|
||||
"board.teensy++-v2.0.h",
|
||||
"printer.mendel.h",
|
||||
"printer.wolfstrap.h",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,86 +1,88 @@
|
|||
|
||||
import wx
|
||||
|
||||
|
||||
class SensorList(wx.ListCtrl):
|
||||
def __init__(self, parent, font):
|
||||
self.parent = parent
|
||||
self.currentItem = None
|
||||
wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
|
||||
size = (105 + 105 + 55 + 280 + 4, 100),
|
||||
style = wx.LC_REPORT | wx.LC_VIRTUAL |
|
||||
wx.LC_HRULES | wx.LC_VRULES)
|
||||
def __init__(self, parent, font):
|
||||
self.parent = parent
|
||||
self.currentItem = None
|
||||
wx.ListCtrl.__init__(
|
||||
self,
|
||||
parent,
|
||||
wx.ID_ANY,
|
||||
size=(105 + 105 + 55 + 280 + 4, 100),
|
||||
style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES | wx.LC_VRULES,
|
||||
)
|
||||
|
||||
self.SetFont(font)
|
||||
self.SetFont(font)
|
||||
|
||||
self.valid = []
|
||||
self.sensorList = []
|
||||
self.valid = []
|
||||
self.sensorList = []
|
||||
|
||||
self.InsertColumn(0, "Name")
|
||||
self.InsertColumn(1, "Sensor Type")
|
||||
self.InsertColumn(2, "Pin")
|
||||
self.InsertColumn(3, "Additional")
|
||||
self.SetColumnWidth(0, 105)
|
||||
self.SetColumnWidth(1, 105)
|
||||
self.SetColumnWidth(2, 55)
|
||||
self.SetColumnWidth(3, 280)
|
||||
self.InsertColumn(0, "Name")
|
||||
self.InsertColumn(1, "Sensor Type")
|
||||
self.InsertColumn(2, "Pin")
|
||||
self.InsertColumn(3, "Additional")
|
||||
self.SetColumnWidth(0, 105)
|
||||
self.SetColumnWidth(1, 105)
|
||||
self.SetColumnWidth(2, 55)
|
||||
self.SetColumnWidth(3, 280)
|
||||
|
||||
self.SetItemCount(0)
|
||||
self.SetItemCount(0)
|
||||
|
||||
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
|
||||
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
|
||||
|
||||
def updateList(self, sensorList):
|
||||
self.sensorList = sensorList
|
||||
self.valid = [True] * len(sensorList)
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
i = self.GetFirstSelected()
|
||||
while i != -1:
|
||||
self.Select(i, False)
|
||||
i = self.GetFirstSelected()
|
||||
def updateList(self, sensorList):
|
||||
self.sensorList = sensorList
|
||||
self.valid = [True] * len(sensorList)
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
i = self.GetFirstSelected()
|
||||
while i != -1:
|
||||
self.Select(i, False)
|
||||
i = self.GetFirstSelected()
|
||||
|
||||
self.SetItemCount(len(sensorList))
|
||||
self.SetItemCount(len(sensorList))
|
||||
|
||||
def setRowValidity(self, i, flag = False):
|
||||
if i < 0 or i >= len(self.sensorList):
|
||||
return
|
||||
def setRowValidity(self, i, flag=False):
|
||||
if i < 0 or i >= len(self.sensorList):
|
||||
return
|
||||
|
||||
self.valid[i] = flag
|
||||
self.Refresh()
|
||||
self.valid[i] = flag
|
||||
self.Refresh()
|
||||
|
||||
def setTableValidity(self, flag = False):
|
||||
for i in range(len(self.sensorList)):
|
||||
self.setRowValidity(i, flag)
|
||||
def setTableValidity(self, flag=False):
|
||||
for i in range(len(self.sensorList)):
|
||||
self.setRowValidity(i, flag)
|
||||
|
||||
def OnItemSelected(self, event):
|
||||
self.currentItem = event.m_itemIndex
|
||||
self.parent.setItemSelected(self.currentItem)
|
||||
def OnItemSelected(self, event):
|
||||
self.currentItem = event.m_itemIndex
|
||||
self.parent.setItemSelected(self.currentItem)
|
||||
|
||||
def OnItemDeselected(self, event):
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
def OnItemDeselected(self, event):
|
||||
self.currentItem = None
|
||||
self.parent.setItemSelected(None)
|
||||
|
||||
def getColumnText(self, index, col):
|
||||
item = self.GetItem(index, col)
|
||||
return item.GetText()
|
||||
def getColumnText(self, index, col):
|
||||
item = self.GetItem(index, col)
|
||||
return item.GetText()
|
||||
|
||||
def OnGetItemText(self, item, col):
|
||||
if item < 0 or item >= len(self.sensorList):
|
||||
return "Error - no sensors"
|
||||
def OnGetItemText(self, item, col):
|
||||
if item < 0 or item >= len(self.sensorList):
|
||||
return "Error - no sensors"
|
||||
|
||||
s = self.sensorList[item]
|
||||
s = self.sensorList[item]
|
||||
|
||||
if col == 0:
|
||||
return s[0]
|
||||
elif col == 1:
|
||||
return s[1]
|
||||
elif col == 2:
|
||||
return s[2]
|
||||
elif len(s) == 3:
|
||||
return ""
|
||||
else:
|
||||
if s[3] is None:
|
||||
return ""
|
||||
else:
|
||||
return "[%s]" % (", ".join(s[3]))
|
||||
if col == 0:
|
||||
return s[0]
|
||||
elif col == 1:
|
||||
return s[1]
|
||||
elif col == 2:
|
||||
return s[2]
|
||||
elif len(s) == 3:
|
||||
return ""
|
||||
else:
|
||||
if s[3] is None:
|
||||
return ""
|
||||
else:
|
||||
return "[%s]" % (", ".join(s[3]))
|
||||
|
|
|
|||
|
|
@ -8,191 +8,208 @@ from .addsensordlg import AddSensorDlg
|
|||
|
||||
|
||||
class SensorsPage(wx.Panel, Page):
|
||||
def __init__(self, parent, nb, idPg, heatersPage, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.heatersPage = heatersPage
|
||||
self.font = font
|
||||
self.id = idPg
|
||||
def __init__(self, parent, nb, idPg, heatersPage, font):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
Page.__init__(self, font)
|
||||
self.parent = parent
|
||||
self.heatersPage = heatersPage
|
||||
self.font = font
|
||||
self.id = idPg
|
||||
|
||||
self.sensorTypeKeys = {'TT_MAX6675': 'TEMP_MAX6675',
|
||||
'TT_THERMISTOR': 'TEMP_THERMISTOR',
|
||||
'TT_AD595': 'TEMP_AD595', 'TT_PT100': 'TEMP_PT100',
|
||||
'TT_INTERCOM': 'TEMP_INTERCOM',
|
||||
'TT_MCP3008': 'TEMP_MCP3008'}
|
||||
self.labels = {'TEMP_MAX6675': "MAX6675", 'TEMP_THERMISTOR': "Thermistor",
|
||||
'TEMP_AD595': "AD595", 'TEMP_PT100': "PT100",
|
||||
'TEMP_INTERCOM': "Intercom",
|
||||
'TEMP_MCP3008': 'MCP3008',
|
||||
'MCP3008_SELECT_PIN': "MCP3008 CS Pin:"}
|
||||
self.sensorTypeKeys = {
|
||||
"TT_MAX6675": "TEMP_MAX6675",
|
||||
"TT_THERMISTOR": "TEMP_THERMISTOR",
|
||||
"TT_AD595": "TEMP_AD595",
|
||||
"TT_PT100": "TEMP_PT100",
|
||||
"TT_INTERCOM": "TEMP_INTERCOM",
|
||||
"TT_MCP3008": "TEMP_MCP3008",
|
||||
}
|
||||
self.labels = {
|
||||
"TEMP_MAX6675": "MAX6675",
|
||||
"TEMP_THERMISTOR": "Thermistor",
|
||||
"TEMP_AD595": "AD595",
|
||||
"TEMP_PT100": "PT100",
|
||||
"TEMP_INTERCOM": "Intercom",
|
||||
"TEMP_MCP3008": "MCP3008",
|
||||
"MCP3008_SELECT_PIN": "MCP3008 CS Pin:",
|
||||
}
|
||||
|
||||
self.validPins = pinNames
|
||||
labelWidth = 120
|
||||
self.validPins = pinNames
|
||||
labelWidth = 120
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos = (0, 0))
|
||||
sz = wx.GridBagSizer()
|
||||
sz.Add((10, 10), pos=(0, 0))
|
||||
|
||||
self.sensors = []
|
||||
self.sensors = []
|
||||
|
||||
self.lb = SensorList(self, font)
|
||||
sz.Add(self.lb, pos = (1, 1))
|
||||
sz.Add((20, 20), pos = (1, 2))
|
||||
self.lb = SensorList(self, font)
|
||||
sz.Add(self.lb, pos=(1, 1))
|
||||
sz.Add((20, 20), pos=(1, 2))
|
||||
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size = BSIZESMALL)
|
||||
self.bAdd.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bAdd.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
|
||||
self.bAdd.Enable(False)
|
||||
self.bAdd.SetToolTip("Add a sensor to the configuration.")
|
||||
bsz = wx.BoxSizer(wx.VERTICAL)
|
||||
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size=BSIZESMALL)
|
||||
self.bAdd.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bAdd.SetFont(font)
|
||||
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
|
||||
self.bAdd.Enable(False)
|
||||
self.bAdd.SetToolTip("Add a sensor to the configuration.")
|
||||
|
||||
bsz.Add(self.bAdd)
|
||||
bsz.Add(self.bAdd)
|
||||
|
||||
bsz.Add((10, 10))
|
||||
self.bModify = wx.Button(self, wx.ID_ANY, "Modify", size = BSIZESMALL)
|
||||
self.bModify.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bModify.SetFont(font)
|
||||
self.bModify.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doModify, self.bModify)
|
||||
bsz.Add(self.bModify)
|
||||
self.bModify.SetToolTip("Modify the selected temperature sensor.")
|
||||
bsz.Add((10, 10))
|
||||
self.bModify = wx.Button(self, wx.ID_ANY, "Modify", size=BSIZESMALL)
|
||||
self.bModify.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bModify.SetFont(font)
|
||||
self.bModify.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doModify, self.bModify)
|
||||
bsz.Add(self.bModify)
|
||||
self.bModify.SetToolTip("Modify the selected temperature sensor.")
|
||||
|
||||
bsz.Add((10, 10))
|
||||
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size = BSIZESMALL)
|
||||
self.bDelete.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bDelete.SetFont(font)
|
||||
self.bDelete.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
|
||||
bsz.Add(self.bDelete)
|
||||
self.bDelete.SetToolTip("Remove the selected temperature sensor "
|
||||
"from the configuration.")
|
||||
bsz.Add((10, 10))
|
||||
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size=BSIZESMALL)
|
||||
self.bDelete.SetBackgroundColour(self.deco.getBackgroundColour())
|
||||
self.bDelete.SetFont(font)
|
||||
self.bDelete.Enable(False)
|
||||
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
|
||||
bsz.Add(self.bDelete)
|
||||
self.bDelete.SetToolTip(
|
||||
"Remove the selected temperature sensor " "from the configuration."
|
||||
)
|
||||
|
||||
sz.Add(bsz, pos = (1, 3))
|
||||
sz.Add(bsz, pos=(1, 3))
|
||||
|
||||
k = "MCP3008_SELECT_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos = (2, 1))
|
||||
k = "MCP3008_SELECT_PIN"
|
||||
tc = self.addPinChoice(k, labelWidth)
|
||||
sz.Add(tc, pos=(2, 1))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def setItemSelected(self, n):
|
||||
self.selection = n
|
||||
if n is None:
|
||||
self.bDelete.Enable(False)
|
||||
self.bModify.Enable(False)
|
||||
else:
|
||||
self.bDelete.Enable(True)
|
||||
self.bModify.Enable(True)
|
||||
def setItemSelected(self, n):
|
||||
self.selection = n
|
||||
if n is None:
|
||||
self.bDelete.Enable(False)
|
||||
self.bModify.Enable(False)
|
||||
else:
|
||||
self.bDelete.Enable(True)
|
||||
self.bModify.Enable(True)
|
||||
|
||||
def doAdd(self, evt):
|
||||
nm = []
|
||||
for s in self.sensors:
|
||||
nm.append(s[0])
|
||||
def doAdd(self, evt):
|
||||
nm = []
|
||||
for s in self.sensors:
|
||||
nm.append(s[0])
|
||||
|
||||
dlg = AddSensorDlg(self, nm, self.validPins, self.heatersPage, self.font)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
tt = dlg.getValues()
|
||||
dlg = AddSensorDlg(self, nm, self.validPins, self.heatersPage, self.font)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
tt = dlg.getValues()
|
||||
|
||||
dlg.Destroy()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
|
||||
self.sensors.append(tt)
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
self.sensors.append(tt)
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
|
||||
def doModify(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
nm = []
|
||||
for s in self.sensors:
|
||||
nm.append(s[0])
|
||||
def doModify(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
nm = []
|
||||
for s in self.sensors:
|
||||
nm.append(s[0])
|
||||
|
||||
s = self.sensors[self.selection]
|
||||
if s[3] is None:
|
||||
params = []
|
||||
else:
|
||||
params = s[3]
|
||||
s = self.sensors[self.selection]
|
||||
if s[3] is None:
|
||||
params = []
|
||||
else:
|
||||
params = s[3]
|
||||
|
||||
dlg = AddSensorDlg(self, nm, self.validPins, self.heatersPage, self.font,
|
||||
name = s[0], stype = s[1], pin = s[2],
|
||||
params = params, modify = True)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
tt = dlg.getValues()
|
||||
dlg = AddSensorDlg(
|
||||
self,
|
||||
nm,
|
||||
self.validPins,
|
||||
self.heatersPage,
|
||||
self.font,
|
||||
name=s[0],
|
||||
stype=s[1],
|
||||
pin=s[2],
|
||||
params=params,
|
||||
modify=True,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
if rc == wx.ID_OK:
|
||||
tt = dlg.getValues()
|
||||
|
||||
dlg.Destroy()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
if rc != wx.ID_OK:
|
||||
return
|
||||
|
||||
self.assertModified(True)
|
||||
self.assertModified(True)
|
||||
|
||||
self.sensors[self.selection] = tt
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
self.sensors[self.selection] = tt
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
|
||||
def doDelete(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
def doDelete(self, evt):
|
||||
if self.selection is None:
|
||||
return
|
||||
|
||||
self.assertModified(True)
|
||||
self.assertModified(True)
|
||||
|
||||
del self.sensors[self.selection]
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
del self.sensors[self.selection]
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
self.assertModified(True)
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
def insertValues(self, cfgValues):
|
||||
Page.insertValues(self, cfgValues)
|
||||
|
||||
self.bAdd.Enable(True)
|
||||
self.bAdd.Enable(True)
|
||||
|
||||
def setSensors(self, sensors):
|
||||
self.sensors = sensors
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
def setSensors(self, sensors):
|
||||
self.sensors = sensors
|
||||
self.lb.updateList(self.sensors)
|
||||
self.validateTable()
|
||||
|
||||
def setCandidatePins(self, plist):
|
||||
if not plist or len(plist) == 0:
|
||||
self.validPins = pinNames
|
||||
else:
|
||||
self.validPins = plist
|
||||
def setCandidatePins(self, plist):
|
||||
if not plist or len(plist) == 0:
|
||||
self.validPins = pinNames
|
||||
else:
|
||||
self.validPins = plist
|
||||
|
||||
self.validateTable()
|
||||
self.validateTable()
|
||||
|
||||
def validateTable(self):
|
||||
self.lb.setTableValidity(True)
|
||||
self.setFieldValidity('SENSORLIST', True)
|
||||
for i in range(len(self.sensors)):
|
||||
if self.sensors[i][2] not in self.validPins:
|
||||
self.lb.setRowValidity(i, False)
|
||||
self.setFieldValidity('SENSORLIST', False)
|
||||
def validateTable(self):
|
||||
self.lb.setTableValidity(True)
|
||||
self.setFieldValidity("SENSORLIST", True)
|
||||
for i in range(len(self.sensors)):
|
||||
if self.sensors[i][2] not in self.validPins:
|
||||
self.lb.setRowValidity(i, False)
|
||||
self.setFieldValidity("SENSORLIST", False)
|
||||
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
def setHelpText(self, ht):
|
||||
Page.setHelpText(self, ht)
|
||||
|
||||
k = 'DEFINE_TEMP_SENSOR'
|
||||
if k in ht.keys():
|
||||
self.bAdd.SetToolTip(ht[k])
|
||||
k = "DEFINE_TEMP_SENSOR"
|
||||
if k in ht.keys():
|
||||
self.bAdd.SetToolTip(ht[k])
|
||||
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
def getValues(self):
|
||||
result = Page.getValues(self)
|
||||
|
||||
values = {}
|
||||
for k in self.sensorTypeKeys.values():
|
||||
values[k] = False
|
||||
values = {}
|
||||
for k in self.sensorTypeKeys.values():
|
||||
values[k] = False
|
||||
|
||||
for s in self.sensors:
|
||||
values[self.sensorTypeKeys[s[1]]] = True
|
||||
for s in self.sensors:
|
||||
values[self.sensorTypeKeys[s[1]]] = True
|
||||
|
||||
for v in values.keys():
|
||||
result[v] = values[v]
|
||||
for v in values.keys():
|
||||
result[v] = values[v]
|
||||
|
||||
return result
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -9,121 +9,122 @@ DEFAULT_INIFILE = "configtool.default.ini"
|
|||
|
||||
|
||||
class Settings:
|
||||
def __init__(self, app, folder, ini=None):
|
||||
self.app = app
|
||||
self.folder = folder
|
||||
self.inifile = os.path.join(folder, INIFILE)
|
||||
self.section = "configtool"
|
||||
def __init__(self, app, folder, ini=None):
|
||||
self.app = app
|
||||
self.folder = folder
|
||||
self.inifile = os.path.join(folder, INIFILE)
|
||||
self.section = "configtool"
|
||||
|
||||
self.arduinodir = ""
|
||||
self.cflags = ""
|
||||
self.ldflags = ""
|
||||
self.objcopyflags = ""
|
||||
self.programmer = "wiring"
|
||||
self.programflags = ""
|
||||
self.port = "/dev/ttyACM0"
|
||||
self.uploadspeed = 38400
|
||||
self.arduinodir = ""
|
||||
self.cflags = ""
|
||||
self.ldflags = ""
|
||||
self.objcopyflags = ""
|
||||
self.programmer = "wiring"
|
||||
self.programflags = ""
|
||||
self.port = "/dev/ttyACM0"
|
||||
self.uploadspeed = 38400
|
||||
|
||||
self.t0 = 25;
|
||||
self.r1 = 0;
|
||||
self.numTemps = 25
|
||||
self.maxAdc = 1023
|
||||
self.minAdc = 1
|
||||
self.t0 = 25
|
||||
self.r1 = 0
|
||||
self.numTemps = 25
|
||||
self.maxAdc = 1023
|
||||
self.minAdc = 1
|
||||
|
||||
# Runtime settings
|
||||
self.verbose = 0
|
||||
# Runtime settings
|
||||
self.verbose = 0
|
||||
|
||||
self.cfg = ConfigParser.ConfigParser()
|
||||
self.cfg.optionxform = str
|
||||
self.cfg = ConfigParser.ConfigParser()
|
||||
self.cfg.optionxform = str
|
||||
|
||||
self.loaded = self.readConfig(ini)
|
||||
self.loaded = self.readConfig(ini)
|
||||
|
||||
def readConfig(self, ini):
|
||||
if ini:
|
||||
if not self.cfg.read(ini):
|
||||
return False
|
||||
else:
|
||||
if not self.cfg.read(self.inifile):
|
||||
if not self.cfg.read(os.path.join(self.folder, DEFAULT_INIFILE)):
|
||||
print ("Neither of settings files %s or %s exist. Using default values."
|
||||
% (INIFILE, DEFAULT_INIFILE))
|
||||
return False
|
||||
|
||||
if self.cfg.has_section(self.section):
|
||||
for opt, value in self.cfg.items(self.section):
|
||||
value = value.replace('\n', ' ')
|
||||
if opt == "arduinodir":
|
||||
self.arduinodir = value
|
||||
elif opt == "cflags":
|
||||
self.cflags = value
|
||||
elif opt == "ldflags":
|
||||
self.ldflags = value
|
||||
elif opt == "programmer":
|
||||
self.programmer = value
|
||||
elif opt == "port":
|
||||
self.port = value
|
||||
elif opt == "objcopyflags":
|
||||
self.objcopyflags = value
|
||||
elif opt == "programflags":
|
||||
self.programflags = value
|
||||
elif opt == "t0":
|
||||
self.t0 = value
|
||||
elif opt == "r1":
|
||||
self.r1 = value
|
||||
elif opt == "numtemps":
|
||||
self.numTemps = value
|
||||
elif opt == "maxadc":
|
||||
self.maxAdc = value
|
||||
elif opt == "minadc":
|
||||
self.minAdc = value
|
||||
elif opt == "uploadspeed":
|
||||
self.uploadspeed = value
|
||||
def readConfig(self, ini):
|
||||
if ini:
|
||||
if not self.cfg.read(ini):
|
||||
return False
|
||||
else:
|
||||
print("Unknown %s option: %s - ignoring." % (self.section, opt))
|
||||
else:
|
||||
print("Missing %s section - assuming defaults." % self.section)
|
||||
return False
|
||||
if not self.cfg.read(self.inifile):
|
||||
if not self.cfg.read(os.path.join(self.folder, DEFAULT_INIFILE)):
|
||||
print(
|
||||
"Neither of settings files %s or %s exist. Using default values."
|
||||
% (INIFILE, DEFAULT_INIFILE)
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
if self.cfg.has_section(self.section):
|
||||
for opt, value in self.cfg.items(self.section):
|
||||
value = value.replace("\n", " ")
|
||||
if opt == "arduinodir":
|
||||
self.arduinodir = value
|
||||
elif opt == "cflags":
|
||||
self.cflags = value
|
||||
elif opt == "ldflags":
|
||||
self.ldflags = value
|
||||
elif opt == "programmer":
|
||||
self.programmer = value
|
||||
elif opt == "port":
|
||||
self.port = value
|
||||
elif opt == "objcopyflags":
|
||||
self.objcopyflags = value
|
||||
elif opt == "programflags":
|
||||
self.programflags = value
|
||||
elif opt == "t0":
|
||||
self.t0 = value
|
||||
elif opt == "r1":
|
||||
self.r1 = value
|
||||
elif opt == "numtemps":
|
||||
self.numTemps = value
|
||||
elif opt == "maxadc":
|
||||
self.maxAdc = value
|
||||
elif opt == "minadc":
|
||||
self.minAdc = value
|
||||
elif opt == "uploadspeed":
|
||||
self.uploadspeed = value
|
||||
else:
|
||||
print("Unknown %s option: %s - ignoring." % (self.section, opt))
|
||||
else:
|
||||
print("Missing %s section - assuming defaults." % self.section)
|
||||
return False
|
||||
|
||||
def getValues(self):
|
||||
return {
|
||||
"arduinodir": str(self.arduinodir),
|
||||
"cflags": str(self.cflags),
|
||||
"ldflags": str(self.ldflags),
|
||||
"objcopyflags": str(self.objcopyflags),
|
||||
"programmer": str(self.programmer),
|
||||
"port": str(self.port),
|
||||
"t0": str(self.t0),
|
||||
"r1": str(self.r1),
|
||||
"numtemps": str(self.numTemps),
|
||||
"maxadc": str(self.maxAdc),
|
||||
"minadc": str(self.minAdc),
|
||||
"uploadspeed": str(self.uploadspeed)
|
||||
}
|
||||
return True
|
||||
|
||||
def saveSettings(self, inifile = None):
|
||||
if not inifile:
|
||||
inifile = self.inifile
|
||||
def getValues(self):
|
||||
return {
|
||||
"arduinodir": str(self.arduinodir),
|
||||
"cflags": str(self.cflags),
|
||||
"ldflags": str(self.ldflags),
|
||||
"objcopyflags": str(self.objcopyflags),
|
||||
"programmer": str(self.programmer),
|
||||
"port": str(self.port),
|
||||
"t0": str(self.t0),
|
||||
"r1": str(self.r1),
|
||||
"numtemps": str(self.numTemps),
|
||||
"maxadc": str(self.maxAdc),
|
||||
"minadc": str(self.minAdc),
|
||||
"uploadspeed": str(self.uploadspeed),
|
||||
}
|
||||
|
||||
self.section = "configtool"
|
||||
try:
|
||||
self.cfg.add_section(self.section)
|
||||
except ConfigParser.DuplicateSectionError:
|
||||
pass
|
||||
def saveSettings(self, inifile=None):
|
||||
if not inifile:
|
||||
inifile = self.inifile
|
||||
|
||||
values = self.getValues()
|
||||
for k in values.keys():
|
||||
self.cfg.set(self.section, k, values[k])
|
||||
self.section = "configtool"
|
||||
try:
|
||||
self.cfg.add_section(self.section)
|
||||
except ConfigParser.DuplicateSectionError:
|
||||
pass
|
||||
|
||||
try:
|
||||
cfp = open(inifile, 'wb')
|
||||
except:
|
||||
print("Unable to open settings file %s for writing." % inifile)
|
||||
return False
|
||||
values = self.getValues()
|
||||
for k in values.keys():
|
||||
self.cfg.set(self.section, k, values[k])
|
||||
|
||||
self.cfg.write(cfp)
|
||||
cfp.close()
|
||||
try:
|
||||
cfp = open(inifile, "wb")
|
||||
except:
|
||||
print("Unable to open settings file %s for writing." % inifile)
|
||||
return False
|
||||
|
||||
return True
|
||||
self.cfg.write(cfp)
|
||||
cfp.close()
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
import wx
|
||||
from configtool.data import BSIZESMALL, offsetTcLabel
|
||||
|
||||
ARDUINODIR = 0
|
||||
CFLAGS = 1
|
||||
LDFLAGS = 2
|
||||
OBJCOPYFLAGS= 3
|
||||
OBJCOPYFLAGS = 3
|
||||
PROGRAMMER = 4
|
||||
PROGRAMFLAGS = 5
|
||||
PORT = 6
|
||||
|
|
@ -18,168 +17,183 @@ R1 = 12
|
|||
|
||||
|
||||
class SettingsDlg(wx.Dialog):
|
||||
def __init__(self, parent, settings):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Modify settings",
|
||||
size = (500, 300))
|
||||
self.SetFont(settings.font)
|
||||
self.settings = settings
|
||||
def __init__(self, parent, settings):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Modify settings", size=(500, 300))
|
||||
self.SetFont(settings.font)
|
||||
self.settings = settings
|
||||
|
||||
self.modified = False
|
||||
self.modified = False
|
||||
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
|
||||
htArdDir = "Path to the Arduino IDE folder. Configtool will figure the " \
|
||||
"details on where to find avr-gcc and avrdude inside there." \
|
||||
"\n\nIf empty, the system wide installed tools will be used."
|
||||
htCFlags = "Flags passed into the avr-gcc compiler. These flags can " \
|
||||
"have 3 different variables embedded within them:" \
|
||||
"\n\n %F_CPU% will be replaced by the value of the CPU " \
|
||||
"Clock Rate." \
|
||||
"\n\n %CPU% will be replaced by the value of the CPU. " \
|
||||
"\n\n %ALNAME% is the name of the source file being " \
|
||||
"compiled with the .c extension replaced by .al.\n\n" \
|
||||
"Note: the flag -save-temps=obj does not appear to be a " \
|
||||
"valid flag for some compiler versions. Omit the \"=obj\", " \
|
||||
"omit the flag entirely, or simply ignore the related warnings."
|
||||
htLDFlags = "Flags passed to avr-gcc to be passed on to the linker."
|
||||
htObjCopy = "Flags passed to avr-objcopy."
|
||||
htProgrammer = "The programmer type - passed to avrdude."
|
||||
htProgramFlags = "Extra flags passed to avrdude."
|
||||
htPort = "The port to which the controller is connected. Typically a " \
|
||||
"path starting with /dev/... on Linux or Mac OS X, or some " \
|
||||
"COM... on Windows."
|
||||
htSpeed = "The baud rate with which to communicate with the bootloader."
|
||||
htNumTemps = "The number of entries generated for the thermistor tables. " \
|
||||
"Higher numbers slightly increase temperature reading " \
|
||||
"accuracy, but also cost binary size. Default is 25."
|
||||
htMinAdc = "The minimum ADC value returned by the thermistor. Typically 0."
|
||||
htMaxAdc = "The maximum ADC value returned by the thermistor. " \
|
||||
"Typically 1023 (maximum of 10-bit ADCs)."
|
||||
htT0 = "The T0 value used for thermistor table calculation. Typically 25."
|
||||
htR1 = "The R1 value used for thermistor table calculation. Typically 0."
|
||||
htArdDir = (
|
||||
"Path to the Arduino IDE folder. Configtool will figure the "
|
||||
"details on where to find avr-gcc and avrdude inside there."
|
||||
"\n\nIf empty, the system wide installed tools will be used."
|
||||
)
|
||||
htCFlags = (
|
||||
"Flags passed into the avr-gcc compiler. These flags can "
|
||||
"have 3 different variables embedded within them:"
|
||||
"\n\n %F_CPU% will be replaced by the value of the CPU "
|
||||
"Clock Rate."
|
||||
"\n\n %CPU% will be replaced by the value of the CPU. "
|
||||
"\n\n %ALNAME% is the name of the source file being "
|
||||
"compiled with the .c extension replaced by .al.\n\n"
|
||||
"Note: the flag -save-temps=obj does not appear to be a "
|
||||
'valid flag for some compiler versions. Omit the "=obj", '
|
||||
"omit the flag entirely, or simply ignore the related warnings."
|
||||
)
|
||||
htLDFlags = "Flags passed to avr-gcc to be passed on to the linker."
|
||||
htObjCopy = "Flags passed to avr-objcopy."
|
||||
htProgrammer = "The programmer type - passed to avrdude."
|
||||
htProgramFlags = "Extra flags passed to avrdude."
|
||||
htPort = (
|
||||
"The port to which the controller is connected. Typically a "
|
||||
"path starting with /dev/... on Linux or Mac OS X, or some "
|
||||
"COM... on Windows."
|
||||
)
|
||||
htSpeed = "The baud rate with which to communicate with the bootloader."
|
||||
htNumTemps = (
|
||||
"The number of entries generated for the thermistor tables. "
|
||||
"Higher numbers slightly increase temperature reading "
|
||||
"accuracy, but also cost binary size. Default is 25."
|
||||
)
|
||||
htMinAdc = "The minimum ADC value returned by the thermistor. Typically 0."
|
||||
htMaxAdc = (
|
||||
"The maximum ADC value returned by the thermistor. "
|
||||
"Typically 1023 (maximum of 10-bit ADCs)."
|
||||
)
|
||||
htT0 = "The T0 value used for thermistor table calculation. Typically 25."
|
||||
htR1 = "The R1 value used for thermistor table calculation. Typically 0."
|
||||
|
||||
# This table MUST be in the same order as the constants defined at
|
||||
# the top of this file.
|
||||
self.fields = [["Arduino Directory", settings.arduinodir, htArdDir],
|
||||
["C Compiler Flags", settings.cflags, htCFlags],
|
||||
["LD Flags", settings.ldflags, htLDFlags],
|
||||
["Object Copy Flags", settings.objcopyflags, htObjCopy],
|
||||
["AVR Programmer", settings.programmer, htProgrammer],
|
||||
["AVR Upload Flags", settings.programflags, htProgramFlags],
|
||||
["Port", settings.port, htPort],
|
||||
["Upload Speed", settings.uploadspeed, htSpeed],
|
||||
["Number of Temps", settings.numTemps, htNumTemps],
|
||||
["Minimum ADC value", settings.minAdc, htMinAdc],
|
||||
["Maximum ADC value", settings.maxAdc, htMaxAdc],
|
||||
["T0", settings.t0, htT0],
|
||||
["R1", settings.r1, htR1]]
|
||||
# This table MUST be in the same order as the constants defined at
|
||||
# the top of this file.
|
||||
self.fields = [
|
||||
["Arduino Directory", settings.arduinodir, htArdDir],
|
||||
["C Compiler Flags", settings.cflags, htCFlags],
|
||||
["LD Flags", settings.ldflags, htLDFlags],
|
||||
["Object Copy Flags", settings.objcopyflags, htObjCopy],
|
||||
["AVR Programmer", settings.programmer, htProgrammer],
|
||||
["AVR Upload Flags", settings.programflags, htProgramFlags],
|
||||
["Port", settings.port, htPort],
|
||||
["Upload Speed", settings.uploadspeed, htSpeed],
|
||||
["Number of Temps", settings.numTemps, htNumTemps],
|
||||
["Minimum ADC value", settings.minAdc, htMinAdc],
|
||||
["Maximum ADC value", settings.maxAdc, htMaxAdc],
|
||||
["T0", settings.t0, htT0],
|
||||
["R1", settings.r1, htR1],
|
||||
]
|
||||
|
||||
self.teList = []
|
||||
self.teList = []
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
labelWidth = 140
|
||||
for f in self.fields:
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
t = wx.StaticText(self, wx.ID_ANY, f[0], size = (labelWidth, -1),
|
||||
style = wx.ALIGN_RIGHT)
|
||||
t.SetFont(settings.font)
|
||||
lsz.Add(t, 1, wx.TOP, offsetTcLabel)
|
||||
labelWidth = 140
|
||||
for f in self.fields:
|
||||
lsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
t = wx.StaticText(
|
||||
self, wx.ID_ANY, f[0], size=(labelWidth, -1), style=wx.ALIGN_RIGHT
|
||||
)
|
||||
t.SetFont(settings.font)
|
||||
lsz.Add(t, 1, wx.TOP, offsetTcLabel)
|
||||
|
||||
lsz.Add((8, 8))
|
||||
lsz.Add((8, 8))
|
||||
|
||||
te = wx.TextCtrl(self, wx.ID_ANY, f[1], size = (600, -1))
|
||||
te.Bind(wx.EVT_TEXT, self.onTextCtrl)
|
||||
te.SetToolTip(f[2])
|
||||
lsz.Add(te)
|
||||
self.teList.append(te)
|
||||
te = wx.TextCtrl(self, wx.ID_ANY, f[1], size=(600, -1))
|
||||
te.Bind(wx.EVT_TEXT, self.onTextCtrl)
|
||||
te.SetToolTip(f[2])
|
||||
lsz.Add(te)
|
||||
self.teList.append(te)
|
||||
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(lsz)
|
||||
sz.Add((10, 10))
|
||||
|
||||
sz.Add((20, 20))
|
||||
sz.Add((20, 20))
|
||||
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Save", size = BSIZESMALL)
|
||||
b.SetFont(settings.font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onSave, b)
|
||||
bsz.Add(b)
|
||||
self.bSave = b
|
||||
bsz.Add((5, 5))
|
||||
bsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
b = wx.Button(self, wx.ID_ANY, "Save", size=BSIZESMALL)
|
||||
b.SetFont(settings.font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onSave, b)
|
||||
bsz.Add(b)
|
||||
self.bSave = b
|
||||
bsz.Add((5, 5))
|
||||
|
||||
b = wx.Button(self, wx.ID_ANY, "Exit", size = BSIZESMALL)
|
||||
b.SetFont(settings.font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onExit, b)
|
||||
bsz.Add(b)
|
||||
self.bExit = b
|
||||
b = wx.Button(self, wx.ID_ANY, "Exit", size=BSIZESMALL)
|
||||
b.SetFont(settings.font)
|
||||
self.Bind(wx.EVT_BUTTON, self.onExit, b)
|
||||
bsz.Add(b)
|
||||
self.bExit = b
|
||||
|
||||
sz.Add(bsz, 1, wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
sz.Add(bsz, 1, wx.ALIGN_CENTER_HORIZONTAL)
|
||||
sz.Add((10, 10))
|
||||
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
hsz.Add(sz)
|
||||
hsz.Add((10, 10))
|
||||
|
||||
self.SetSizer(hsz)
|
||||
self.setModified(False)
|
||||
self.SetSizer(hsz)
|
||||
self.setModified(False)
|
||||
|
||||
self.Fit()
|
||||
self.Fit()
|
||||
|
||||
def setModified(self, flag):
|
||||
self.modified = flag
|
||||
if flag:
|
||||
self.bSave.Enable(True)
|
||||
self.bExit.SetLabel("Cancel")
|
||||
else:
|
||||
self.bSave.Enable(False)
|
||||
self.bExit.SetLabel("Exit")
|
||||
def setModified(self, flag):
|
||||
self.modified = flag
|
||||
if flag:
|
||||
self.bSave.Enable(True)
|
||||
self.bExit.SetLabel("Cancel")
|
||||
else:
|
||||
self.bSave.Enable(False)
|
||||
self.bExit.SetLabel("Exit")
|
||||
|
||||
def onTextCtrl(self, evt):
|
||||
self.setModified(True)
|
||||
evt.Skip()
|
||||
def onTextCtrl(self, evt):
|
||||
self.setModified(True)
|
||||
evt.Skip()
|
||||
|
||||
def onSave(self, evt):
|
||||
self.saveValues()
|
||||
self.EndModal(wx.ID_OK)
|
||||
def onSave(self, evt):
|
||||
self.saveValues()
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
def saveValues(self):
|
||||
self.settings.arduinodir = self.teList[ARDUINODIR].GetValue()
|
||||
self.settings.cflags = self.teList[CFLAGS].GetValue()
|
||||
self.settings.ldflags = self.teList[LDFLAGS].GetValue()
|
||||
self.settings.objcopyflags = self.teList[OBJCOPYFLAGS].GetValue()
|
||||
self.settings.programmer = self.teList[PROGRAMMER].GetValue()
|
||||
self.settings.programflags = self.teList[PROGRAMFLAGS].GetValue()
|
||||
self.settings.port = self.teList[PORT].GetValue()
|
||||
self.settings.uploadspeed = self.teList[UPLOADSPEED].GetValue()
|
||||
self.settings.numTemps = self.teList[NUMTEMPS].GetValue()
|
||||
self.settings.minAdc = self.teList[MINADC].GetValue()
|
||||
self.settings.maxAdc = self.teList[MAXADC].GetValue()
|
||||
self.settings.t0 = self.teList[T0].GetValue()
|
||||
self.settings.r1 = self.teList[R1].GetValue()
|
||||
def saveValues(self):
|
||||
self.settings.arduinodir = self.teList[ARDUINODIR].GetValue()
|
||||
self.settings.cflags = self.teList[CFLAGS].GetValue()
|
||||
self.settings.ldflags = self.teList[LDFLAGS].GetValue()
|
||||
self.settings.objcopyflags = self.teList[OBJCOPYFLAGS].GetValue()
|
||||
self.settings.programmer = self.teList[PROGRAMMER].GetValue()
|
||||
self.settings.programflags = self.teList[PROGRAMFLAGS].GetValue()
|
||||
self.settings.port = self.teList[PORT].GetValue()
|
||||
self.settings.uploadspeed = self.teList[UPLOADSPEED].GetValue()
|
||||
self.settings.numTemps = self.teList[NUMTEMPS].GetValue()
|
||||
self.settings.minAdc = self.teList[MINADC].GetValue()
|
||||
self.settings.maxAdc = self.teList[MAXADC].GetValue()
|
||||
self.settings.t0 = self.teList[T0].GetValue()
|
||||
self.settings.r1 = self.teList[R1].GetValue()
|
||||
|
||||
self.settings.saveSettings()
|
||||
self.settings.saveSettings()
|
||||
|
||||
def onExit(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
self.EndModal(wx.ID_EXIT)
|
||||
def onExit(self, evt):
|
||||
if not self.confirmLoseChanges("exit"):
|
||||
return
|
||||
self.EndModal(wx.ID_EXIT)
|
||||
|
||||
def confirmLoseChanges(self, msg):
|
||||
if not self.modified:
|
||||
return True
|
||||
def confirmLoseChanges(self, msg):
|
||||
if not self.modified:
|
||||
return True
|
||||
|
||||
dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your settings that "
|
||||
"will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
dlg = wx.MessageDialog(
|
||||
self,
|
||||
"Are you sure you want to " + msg + "?\n"
|
||||
"There are changes to your settings that "
|
||||
"will be lost.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION,
|
||||
)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
if rc != wx.ID_YES:
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -5,95 +5,100 @@ import sys
|
|||
|
||||
|
||||
class SHThermistor:
|
||||
def __init__(self, rp, t0, r0, t1, r1, t2, r2):
|
||||
self.rp = rp
|
||||
def __init__(self, rp, t0, r0, t1, r1, t2, r2):
|
||||
self.rp = rp
|
||||
|
||||
self.paramsOK = True
|
||||
try:
|
||||
T0 = t0 + 273.15; T1 = t1 + 273.15; T2 = t2 + 273.15
|
||||
a0 = log(r0); a1 = log(r1); a2 = log(r2)
|
||||
z = a0 - a1
|
||||
y = a0 - a2
|
||||
x = 1 / T0 - 1 / T1
|
||||
w = 1 / T0 - 1 / T2
|
||||
v = a0 ** 3 - a1 ** 3
|
||||
u = a0 ** 3 - a2 ** 3
|
||||
self.paramsOK = True
|
||||
try:
|
||||
T0 = t0 + 273.15
|
||||
T1 = t1 + 273.15
|
||||
T2 = t2 + 273.15
|
||||
a0 = log(r0)
|
||||
a1 = log(r1)
|
||||
a2 = log(r2)
|
||||
z = a0 - a1
|
||||
y = a0 - a2
|
||||
x = 1 / T0 - 1 / T1
|
||||
w = 1 / T0 - 1 / T2
|
||||
v = a0 ** 3 - a1 ** 3
|
||||
u = a0 ** 3 - a2 ** 3
|
||||
|
||||
self.C = (x - z * w / y) / (v - z * u / y)
|
||||
self.B = (x - self.C * v) / z
|
||||
self.A = 1 / T0 - self.C * a0 ** 3 - self.B * a0
|
||||
except:
|
||||
self.paramsOK = False
|
||||
self.C = (x - z * w / y) / (v - z * u / y)
|
||||
self.B = (x - self.C * v) / z
|
||||
self.A = 1 / T0 - self.C * a0 ** 3 - self.B * a0
|
||||
except:
|
||||
self.paramsOK = False
|
||||
|
||||
def setting(self, t):
|
||||
if not self.paramsOK:
|
||||
return None, None
|
||||
def setting(self, t):
|
||||
if not self.paramsOK:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
T = t + 273.15
|
||||
y = (self.A - 1/T) / self.C
|
||||
x = ((self.B / (3 * self.C)) ** 3 + (y ** 2) / 4) ** 0.5
|
||||
r = exp((x - y / 2) ** (1.0/3) - (x + y / 2) ** (1.0/3))
|
||||
return self.adc(r), r
|
||||
except:
|
||||
return None, None
|
||||
try:
|
||||
T = t + 273.15
|
||||
y = (self.A - 1 / T) / self.C
|
||||
x = ((self.B / (3 * self.C)) ** 3 + (y ** 2) / 4) ** 0.5
|
||||
r = exp((x - y / 2) ** (1.0 / 3) - (x + y / 2) ** (1.0 / 3))
|
||||
return self.adc(r), r
|
||||
except:
|
||||
return None, None
|
||||
|
||||
def temp(self, adc):
|
||||
r = self.adcInv(adc)
|
||||
t = (1.0 / (self.A + self.B * log(r) + self.C * (log(r) ** 3))) - 273.15;
|
||||
return t
|
||||
def temp(self, adc):
|
||||
r = self.adcInv(adc)
|
||||
t = (1.0 / (self.A + self.B * log(r) + self.C * (log(r) ** 3))) - 273.15
|
||||
return t
|
||||
|
||||
def adc(self, r):
|
||||
return 1023.0 * r / (r + self.rp)
|
||||
def adc(self, r):
|
||||
return 1023.0 * r / (r + self.rp)
|
||||
|
||||
def adcInv(self, adc):
|
||||
return (self.rp * adc) / (1023.0 - adc)
|
||||
|
||||
def adcInv(self, adc):
|
||||
return (self.rp * adc)/(1023.0 - adc)
|
||||
|
||||
class BetaThermistor:
|
||||
def __init__(self, r0, t0, beta, r1, r2, vadc):
|
||||
self.paramsOK = True
|
||||
def __init__(self, r0, t0, beta, r1, r2, vadc):
|
||||
self.paramsOK = True
|
||||
|
||||
try:
|
||||
self.r0 = r0
|
||||
self.t0 = t0 + 273.15
|
||||
self.beta = beta
|
||||
self.vadc = vadc
|
||||
self.k = r0 * exp(-beta / self.t0)
|
||||
try:
|
||||
self.r0 = r0
|
||||
self.t0 = t0 + 273.15
|
||||
self.beta = beta
|
||||
self.vadc = vadc
|
||||
self.k = r0 * exp(-beta / self.t0)
|
||||
|
||||
if r1 > 0:
|
||||
self.vs = r1 * self.vadc / (r1 + r2)
|
||||
self.rs = r1 * r2 / (r1 + r2)
|
||||
else:
|
||||
self.vs = self.vadc
|
||||
self.rs = r2
|
||||
except:
|
||||
self.paramsOK = False
|
||||
if r1 > 0:
|
||||
self.vs = r1 * self.vadc / (r1 + r2)
|
||||
self.rs = r1 * r2 / (r1 + r2)
|
||||
else:
|
||||
self.vs = self.vadc
|
||||
self.rs = r2
|
||||
except:
|
||||
self.paramsOK = False
|
||||
|
||||
def temp(self, adc):
|
||||
v = adc * self.vadc / 1024
|
||||
if (self.vs - v):
|
||||
r = self.rs * v / (self.vs - v)
|
||||
else:
|
||||
r = self.r0 * 10
|
||||
try:
|
||||
return (self.beta / log(r / self.k)) - 273.15
|
||||
except:
|
||||
print("// error for ADC = {adc}, {v}, {r}".format(adc = adc, v = v, r = r))
|
||||
return None
|
||||
def temp(self, adc):
|
||||
v = adc * self.vadc / 1024
|
||||
if self.vs - v:
|
||||
r = self.rs * v / (self.vs - v)
|
||||
else:
|
||||
r = self.r0 * 10
|
||||
try:
|
||||
return (self.beta / log(r / self.k)) - 273.15
|
||||
except:
|
||||
print("// error for ADC = {adc}, {v}, {r}".format(adc=adc, v=v, r=r))
|
||||
return None
|
||||
|
||||
def resistance(self, t):
|
||||
return self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0))
|
||||
def resistance(self, t):
|
||||
return self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0))
|
||||
|
||||
def setting(self, t):
|
||||
if not self.paramsOK:
|
||||
return None, None
|
||||
def setting(self, t):
|
||||
if not self.paramsOK:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
r = self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0))
|
||||
v = self.vs * r / (self.rs + r)
|
||||
return round(v / self.vadc * 1024), r
|
||||
except:
|
||||
return None, None
|
||||
try:
|
||||
r = self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0))
|
||||
v = self.vs * r / (self.rs + r)
|
||||
return round(v / self.vadc * 1024), r
|
||||
except:
|
||||
return None, None
|
||||
|
||||
def adcInv(self, adc):
|
||||
return (adc * self.vadc)/1024.0
|
||||
def adcInv(self, adc):
|
||||
return (adc * self.vadc) / 1024.0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
# Define thermistor presets. These can either be defined to use the
|
||||
# beta argorithm by specifying 4 parameters:
|
||||
# R0, beta, Rp, Vadc
|
||||
|
|
@ -7,12 +6,12 @@
|
|||
# Rp, T0, R0, T1, R1, T2, R2
|
||||
#
|
||||
thermistorPresets = {
|
||||
"RS 10K": ['10000', '3480', '1600', '5.0'],
|
||||
"RRRF 10K": ['10000', '3964', '1600', '5.0'],
|
||||
"ATC Semitec 104GT-2": ['100000', '4267', '4700', '5.0'],
|
||||
"EPCOS 100K (B57560G1104F)": ['100000', '4092', '4700', '5.0'],
|
||||
"EPCOS 100K (B5754061104)": ['100000', '4066', '4700', '5.0'],
|
||||
"EPCOS 100K (B57560G104F)": ['100000', '4036', '4700', '5.0'],
|
||||
"Honeywell 100K": ['100000', '3974', '4700', '5.0'],
|
||||
"RRRF 100K": ['100000', '3960', '4700', '5.0'],
|
||||
"RS 10K": ["10000", "3480", "1600", "5.0"],
|
||||
"RRRF 10K": ["10000", "3964", "1600", "5.0"],
|
||||
"ATC Semitec 104GT-2": ["100000", "4267", "4700", "5.0"],
|
||||
"EPCOS 100K (B57560G1104F)": ["100000", "4092", "4700", "5.0"],
|
||||
"EPCOS 100K (B5754061104)": ["100000", "4066", "4700", "5.0"],
|
||||
"EPCOS 100K (B57560G104F)": ["100000", "4036", "4700", "5.0"],
|
||||
"Honeywell 100K": ["100000", "3974", "4700", "5.0"],
|
||||
"RRRF 100K": ["100000", "3960", "4700", "5.0"],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,233 +5,275 @@ from .thermistor import SHThermistor, BetaThermistor
|
|||
|
||||
|
||||
class ThermistorTableFile:
|
||||
def __init__(self, folder):
|
||||
self.error = False
|
||||
fn = os.path.join(folder, "thermistortable.h")
|
||||
try:
|
||||
self.fp = open(fn, 'wb')
|
||||
except:
|
||||
self.error = True
|
||||
def __init__(self, folder):
|
||||
self.error = False
|
||||
fn = os.path.join(folder, "thermistortable.h")
|
||||
try:
|
||||
self.fp = open(fn, "wb")
|
||||
except:
|
||||
self.error = True
|
||||
|
||||
def close(self):
|
||||
self.fp.close()
|
||||
def close(self):
|
||||
self.fp.close()
|
||||
|
||||
def output(self, text):
|
||||
self.fp.write(text + "\n")
|
||||
|
||||
def output(self, text):
|
||||
self.fp.write(text + "\n")
|
||||
|
||||
def paramsEqual(p1, p2):
|
||||
for i in range(len(p1)):
|
||||
if p1[i] != p2[i]:
|
||||
return False
|
||||
for i in range(len(p1)):
|
||||
if p1[i] != p2[i]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def generateTempTables(sensors, settings):
|
||||
ofp = ThermistorTableFile(settings.folder)
|
||||
if ofp.error:
|
||||
return False
|
||||
|
||||
N = int(settings.numTemps)
|
||||
|
||||
tl = []
|
||||
for sensor in sensors:
|
||||
if sensor[3] is not None:
|
||||
found = False
|
||||
for t in tl:
|
||||
if paramsEqual(t[0], sensor[3]):
|
||||
t[1].append(sensor[0].upper())
|
||||
found = True
|
||||
if not found:
|
||||
tl.append((sensor[3], [sensor[0].upper()]))
|
||||
|
||||
ofp.output("");
|
||||
ofp.output("/**");
|
||||
ofp.output(" This file was autogenerated when saving a board with");
|
||||
ofp.output(" Teacup's Configtool. You can edit it, but the next board");
|
||||
ofp.output(" save operation in Configtool will overwrite it without");
|
||||
ofp.output(" asking.");
|
||||
ofp.output("*/");
|
||||
ofp.output("");
|
||||
|
||||
ofp.output("#define NUMTABLES %d" % len(tl))
|
||||
ofp.output("#define NUMTEMPS %d" % N)
|
||||
ofp.output("");
|
||||
|
||||
for i in range(len(tl)):
|
||||
for n in tl[i][1]:
|
||||
ofp.output("#define THERMISTOR_%s %d" % (n, i))
|
||||
ofp.output("");
|
||||
|
||||
if len(tl) == 0 or N == 0:
|
||||
ofp.close();
|
||||
return True
|
||||
|
||||
ofp.output("const uint16_t PROGMEM temptable[NUMTABLES][NUMTEMPS][3] = {")
|
||||
|
||||
tcount = 0
|
||||
for tn in tl:
|
||||
tcount += 1
|
||||
finalTable = tcount == len(tl)
|
||||
if len(tn[0]) == 4:
|
||||
BetaTable(ofp, tn[0], tn[1], settings, finalTable)
|
||||
elif len(tn[0]) == 7:
|
||||
SteinhartHartTable(ofp, tn[0], tn[1], settings, finalTable)
|
||||
else:
|
||||
pass
|
||||
def generateTempTables(sensors, settings):
|
||||
ofp = ThermistorTableFile(settings.folder)
|
||||
if ofp.error:
|
||||
return False
|
||||
|
||||
N = int(settings.numTemps)
|
||||
|
||||
tl = []
|
||||
for sensor in sensors:
|
||||
if sensor[3] is not None:
|
||||
found = False
|
||||
for t in tl:
|
||||
if paramsEqual(t[0], sensor[3]):
|
||||
t[1].append(sensor[0].upper())
|
||||
found = True
|
||||
if not found:
|
||||
tl.append((sensor[3], [sensor[0].upper()]))
|
||||
|
||||
ofp.output("")
|
||||
ofp.output("/**")
|
||||
ofp.output(" This file was autogenerated when saving a board with")
|
||||
ofp.output(" Teacup's Configtool. You can edit it, but the next board")
|
||||
ofp.output(" save operation in Configtool will overwrite it without")
|
||||
ofp.output(" asking.")
|
||||
ofp.output("*/")
|
||||
ofp.output("")
|
||||
|
||||
ofp.output("#define NUMTABLES %d" % len(tl))
|
||||
ofp.output("#define NUMTEMPS %d" % N)
|
||||
ofp.output("")
|
||||
|
||||
for i in range(len(tl)):
|
||||
for n in tl[i][1]:
|
||||
ofp.output("#define THERMISTOR_%s %d" % (n, i))
|
||||
ofp.output("")
|
||||
|
||||
if len(tl) == 0 or N == 0:
|
||||
ofp.close()
|
||||
return True
|
||||
|
||||
ofp.output("const uint16_t PROGMEM temptable[NUMTABLES][NUMTEMPS][3] = {")
|
||||
|
||||
tcount = 0
|
||||
for tn in tl:
|
||||
tcount += 1
|
||||
finalTable = tcount == len(tl)
|
||||
if len(tn[0]) == 4:
|
||||
BetaTable(ofp, tn[0], tn[1], settings, finalTable)
|
||||
elif len(tn[0]) == 7:
|
||||
SteinhartHartTable(ofp, tn[0], tn[1], settings, finalTable)
|
||||
else:
|
||||
pass
|
||||
|
||||
ofp.output("};")
|
||||
ofp.close()
|
||||
return True
|
||||
|
||||
ofp.output("};")
|
||||
ofp.close()
|
||||
return True
|
||||
|
||||
def BetaTable(ofp, params, names, settings, finalTable):
|
||||
r0 = params[0]
|
||||
beta = params[1]
|
||||
r2 = params[2]
|
||||
vadc = float(params[3])
|
||||
ofp.output(" // %s temp table using Beta algorithm with parameters:" %
|
||||
(", ".join(names)))
|
||||
ofp.output((" // R0 = %s, T0 = %s, R1 = %s, R2 = %s, beta = %s, "
|
||||
"maxadc = %s") % (r0, settings.t0, settings.r1, r2,
|
||||
beta, settings.maxAdc))
|
||||
ofp.output(" {")
|
||||
r0 = params[0]
|
||||
beta = params[1]
|
||||
r2 = params[2]
|
||||
vadc = float(params[3])
|
||||
ofp.output(
|
||||
" // %s temp table using Beta algorithm with parameters:" % (", ".join(names))
|
||||
)
|
||||
ofp.output(
|
||||
(" // R0 = %s, T0 = %s, R1 = %s, R2 = %s, beta = %s, " "maxadc = %s")
|
||||
% (r0, settings.t0, settings.r1, r2, beta, settings.maxAdc)
|
||||
)
|
||||
ofp.output(" {")
|
||||
|
||||
thrm = BetaThermistor(int(r0), int(settings.t0), int(beta), int(settings.r1),
|
||||
int(r2), vadc)
|
||||
thrm = BetaThermistor(
|
||||
int(r0), int(settings.t0), int(beta), int(settings.r1), int(r2), vadc
|
||||
)
|
||||
|
||||
hiadc = thrm.setting(0)[0]
|
||||
N = int(settings.numTemps)
|
||||
hiadc = thrm.setting(0)[0]
|
||||
N = int(settings.numTemps)
|
||||
|
||||
samples = optimizeTempTable(thrm, N, hiadc)
|
||||
samples = optimizeTempTable(thrm, N, hiadc)
|
||||
|
||||
prev = samples[0]
|
||||
for i in samples:
|
||||
t = thrm.temp(i)
|
||||
if t is None:
|
||||
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
|
||||
continue
|
||||
prev = samples[0]
|
||||
for i in samples:
|
||||
t = thrm.temp(i)
|
||||
if t is None:
|
||||
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
|
||||
continue
|
||||
|
||||
v = thrm.adcInv(i)
|
||||
r = thrm.resistance(t)
|
||||
v = thrm.adcInv(i)
|
||||
r = thrm.resistance(t)
|
||||
|
||||
vTherm = i * vadc / 1024
|
||||
ptherm = vTherm * vTherm / r
|
||||
vTherm = i * vadc / 1024
|
||||
ptherm = vTherm * vTherm / r
|
||||
|
||||
if i == max(samples):
|
||||
c = " "
|
||||
if i == max(samples):
|
||||
c = " "
|
||||
else:
|
||||
c = ","
|
||||
|
||||
delta = (t - thrm.temp(prev)) / (prev - i) if i != prev else 0
|
||||
ostr = (
|
||||
" {%4s, %5s, %5s}%s // %4d C, %6.0f ohms, %0.3f V,"
|
||||
" %0.2f mW, m = %6.3f"
|
||||
) % (
|
||||
i,
|
||||
int(t * 4),
|
||||
int(delta * 4 * 256),
|
||||
c,
|
||||
int(t),
|
||||
int(round(r)),
|
||||
vTherm,
|
||||
ptherm * 1000,
|
||||
delta,
|
||||
)
|
||||
ofp.output(ostr)
|
||||
prev = i
|
||||
|
||||
if finalTable:
|
||||
ofp.output(" }")
|
||||
else:
|
||||
c = ","
|
||||
ofp.output(" },")
|
||||
|
||||
delta = (t - thrm.temp(prev)) / (prev - i) if i != prev else 0
|
||||
ostr = (" {%4s, %5s, %5s}%s // %4d C, %6.0f ohms, %0.3f V,"
|
||||
" %0.2f mW, m = %6.3f") % (i, int(t * 4), int(delta * 4 * 256), c,
|
||||
int(t), int(round(r)), vTherm, ptherm * 1000, delta)
|
||||
ofp.output(ostr)
|
||||
prev = i
|
||||
|
||||
if finalTable:
|
||||
ofp.output(" }")
|
||||
else:
|
||||
ofp.output(" },")
|
||||
|
||||
def SteinhartHartTable(ofp, params, names, settings, finalTable):
|
||||
ofp.output((" // %s temp table using Steinhart-Hart algorithm with "
|
||||
"parameters:") % (", ".join(names)))
|
||||
ofp.output((" // Rp = %s, T0 = %s, R0 = %s, T1 = %s, R1 = %s, "
|
||||
"T2 = %s, R2 = %s") %
|
||||
(params[0], params[1], params[2], params[3], params[4], params[5],
|
||||
params[6]))
|
||||
ofp.output(" {")
|
||||
ofp.output(
|
||||
(" // %s temp table using Steinhart-Hart algorithm with " "parameters:")
|
||||
% (", ".join(names))
|
||||
)
|
||||
ofp.output(
|
||||
(" // Rp = %s, T0 = %s, R0 = %s, T1 = %s, R1 = %s, " "T2 = %s, R2 = %s")
|
||||
% (params[0], params[1], params[2], params[3], params[4], params[5], params[6])
|
||||
)
|
||||
ofp.output(" {")
|
||||
|
||||
thrm = SHThermistor(int(params[0]), float(params[1]), int(params[2]),
|
||||
float(params[3]), int(params[4]), float(params[5]),
|
||||
int(params[6]))
|
||||
thrm = SHThermistor(
|
||||
int(params[0]),
|
||||
float(params[1]),
|
||||
int(params[2]),
|
||||
float(params[3]),
|
||||
int(params[4]),
|
||||
float(params[5]),
|
||||
int(params[6]),
|
||||
)
|
||||
|
||||
hiadc = thrm.setting(0)[0]
|
||||
N = int(settings.numTemps)
|
||||
hiadc = thrm.setting(0)[0]
|
||||
N = int(settings.numTemps)
|
||||
|
||||
samples = optimizeTempTable(thrm, N, hiadc)
|
||||
samples = optimizeTempTable(thrm, N, hiadc)
|
||||
|
||||
prev = samples[0]
|
||||
for i in samples:
|
||||
t = thrm.temp(i)
|
||||
if t is None:
|
||||
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
|
||||
continue
|
||||
prev = samples[0]
|
||||
for i in samples:
|
||||
t = thrm.temp(i)
|
||||
if t is None:
|
||||
ofp.output("// ERROR CALCULATING THERMISTOR VALUES AT ADC %d" % i)
|
||||
continue
|
||||
|
||||
r = int(thrm.adcInv(i))
|
||||
r = int(thrm.adcInv(i))
|
||||
|
||||
if i == max(samples):
|
||||
c = " "
|
||||
if i == max(samples):
|
||||
c = " "
|
||||
else:
|
||||
c = ","
|
||||
|
||||
delta = (t - thrm.temp(prev)) / (prev - i) if i != prev else 0
|
||||
ofp.output(
|
||||
" {%4d, %5d, %5d}%s // %4d C, %6d ohms, m = %6.3f"
|
||||
% (i, int(t * 4), int(delta * 4 * 256), c, int(t), int(round(r)), delta)
|
||||
)
|
||||
prev = i
|
||||
|
||||
if finalTable:
|
||||
ofp.output(" }")
|
||||
else:
|
||||
c = ","
|
||||
ofp.output(" },")
|
||||
|
||||
delta = (t - thrm.temp(prev)) / (prev - i) if i != prev else 0
|
||||
ofp.output(" {%4d, %5d, %5d}%s // %4d C, %6d ohms, m = %6.3f" %
|
||||
(i, int(t * 4), int(delta * 4 * 256), c, int(t), int(round(r)),
|
||||
delta))
|
||||
prev = i
|
||||
|
||||
if finalTable:
|
||||
ofp.output(" }")
|
||||
else:
|
||||
ofp.output(" },")
|
||||
|
||||
def optimizeTempTable(thrm, length, hiadc):
|
||||
|
||||
# This is a variation of the Ramer-Douglas-Peucker algorithm, see
|
||||
# https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
|
||||
#
|
||||
# It works like this:
|
||||
#
|
||||
# - Calculate all (1024) ideal values.
|
||||
# - Keep only the ones in the interesting range (0..500C).
|
||||
# - Insert the two extremes into our sample list.
|
||||
# - Calculate the linear approximation of the remaining values.
|
||||
# - Insert the correct value for the "most-wrong" estimation into our
|
||||
# sample list.
|
||||
# - Repeat until "N" values are chosen as requested.
|
||||
# This is a variation of the Ramer-Douglas-Peucker algorithm, see
|
||||
# https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
|
||||
#
|
||||
# It works like this:
|
||||
#
|
||||
# - Calculate all (1024) ideal values.
|
||||
# - Keep only the ones in the interesting range (0..500C).
|
||||
# - Insert the two extremes into our sample list.
|
||||
# - Calculate the linear approximation of the remaining values.
|
||||
# - Insert the correct value for the "most-wrong" estimation into our
|
||||
# sample list.
|
||||
# - Repeat until "N" values are chosen as requested.
|
||||
|
||||
# Calculate actual temps for all ADC values.
|
||||
actual = dict([(x, thrm.temp(1.0 * x)) for x in range(1, int(hiadc + 1))])
|
||||
# Calculate actual temps for all ADC values.
|
||||
actual = dict([(x, thrm.temp(1.0 * x)) for x in range(1, int(hiadc + 1))])
|
||||
|
||||
# Limit ADC range to 0C to 500C.
|
||||
MIN_TEMP = 0
|
||||
MAX_TEMP = 500
|
||||
actual = dict([(adc, actual[adc]) for adc in actual
|
||||
if actual[adc] <= MAX_TEMP and actual[adc] >= MIN_TEMP])
|
||||
# Limit ADC range to 0C to 500C.
|
||||
MIN_TEMP = 0
|
||||
MAX_TEMP = 500
|
||||
actual = dict(
|
||||
[
|
||||
(adc, actual[adc])
|
||||
for adc in actual
|
||||
if actual[adc] <= MAX_TEMP and actual[adc] >= MIN_TEMP
|
||||
]
|
||||
)
|
||||
|
||||
# Build a lookup table starting with the extremes.
|
||||
A = min(actual)
|
||||
B = max(actual)
|
||||
lookup = dict([(x, actual[x]) for x in [A, B]])
|
||||
error = dict({})
|
||||
while len(lookup) < length:
|
||||
error.update(dict([(x, abs(actual[x] - LinearTableEstimate(lookup, x)))
|
||||
for x in range(A + 1, B)]))
|
||||
# Build a lookup table starting with the extremes.
|
||||
A = min(actual)
|
||||
B = max(actual)
|
||||
lookup = dict([(x, actual[x]) for x in [A, B]])
|
||||
error = dict({})
|
||||
while len(lookup) < length:
|
||||
error.update(
|
||||
dict(
|
||||
[
|
||||
(x, abs(actual[x] - LinearTableEstimate(lookup, x)))
|
||||
for x in range(A + 1, B)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# Correct the most-wrong lookup value.
|
||||
next = max(error, key = error.get)
|
||||
lookup[next] = actual[next]
|
||||
# Correct the most-wrong lookup value.
|
||||
next = max(error, key=error.get)
|
||||
lookup[next] = actual[next]
|
||||
|
||||
# Prepare to update the error range.
|
||||
A = before(lookup, next)
|
||||
B = after(lookup, next)
|
||||
# Prepare to update the error range.
|
||||
A = before(lookup, next)
|
||||
B = after(lookup, next)
|
||||
|
||||
return sorted(lookup)
|
||||
|
||||
return sorted(lookup)
|
||||
|
||||
def after(lookup, value):
|
||||
return min([x for x in lookup.keys() if x > value])
|
||||
return min([x for x in lookup.keys() if x > value])
|
||||
|
||||
|
||||
def before(lookup, value):
|
||||
return max([x for x in lookup.keys() if x < value])
|
||||
return max([x for x in lookup.keys() if x < value])
|
||||
|
||||
|
||||
def LinearTableEstimate(lookup, value):
|
||||
if value in lookup:
|
||||
return lookup[value]
|
||||
if value in lookup:
|
||||
return lookup[value]
|
||||
|
||||
# Estimate result with linear estimation algorithm.
|
||||
x0 = before(lookup, value)
|
||||
x1 = after(lookup, value)
|
||||
y0 = lookup[x0]
|
||||
y1 = lookup[x1]
|
||||
return ((value - x0) * y1 + (x1 - value) * y0) / (x1 - x0)
|
||||
# Estimate result with linear estimation algorithm.
|
||||
x0 = before(lookup, value)
|
||||
x1 = after(lookup, value)
|
||||
y0 = lookup[x0]
|
||||
y1 = lookup[x1]
|
||||
return ((value - x0) * y1 + (x1 - value) * y0) / (x1 - x0)
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@
|
|||
# on a microcontroller
|
||||
# based on: http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html
|
||||
# Modified Thu 10 Feb 2011 02:02:28 PM MST jgilmore for 5D_on_arduino firmware
|
||||
# temps are now in 14.2 fixed point notation (i.e. measured in quarter-degrees)
|
||||
# temps are not permitted to be negative (BUG:may result in numtemps fewer than requested)
|
||||
# bugfix: --num-temps command line option works.
|
||||
# 2012-11-08, DaveX: Modified to add --vcc=, --min_adc=, --mult and to print per-ADC comments
|
||||
# temps are now in 14.2 fixed point notation (i.e. measured in quarter-degrees)
|
||||
# temps are not permitted to be negative (BUG:may result in numtemps fewer than requested)
|
||||
# bugfix: --num-temps command line option works.
|
||||
# 2012-11-08, DaveX: Modified to add --vcc=, --min_adc=, --mult and to print per-ADC comments
|
||||
|
||||
"""Thermistor Value Lookup Table Generator
|
||||
|
||||
Generates lookup to temperature values for use in a microcontroller in C format based on:
|
||||
Generates lookup to temperature values for use in a microcontroller in C format based on:
|
||||
http://hydraraptor.blogspot.com/2007/10/measuring-temperature-easy-way.html
|
||||
|
||||
The main use is for Arduino programs that read data from the circuit board described here:
|
||||
|
|
@ -21,15 +21,15 @@ The main use is for Arduino programs that read data from the circuit board descr
|
|||
Usage: python createTemperatureLookup.py [options]
|
||||
|
||||
Options:
|
||||
-h, --help show this help
|
||||
--r0=... thermistor rating where # is the ohm rating of the thermistor at t0 (eg: 10K = 10000)
|
||||
--t0=... thermistor temp rating where # is the temperature in Celsuis to get r0 (from your datasheet)
|
||||
--beta=... thermistor beta rating. see http://reprap.org/bin/view/Main/MeasuringThermistorBeta
|
||||
--r1=... R1 rating where # is the ohm rating of R1 (eg: 10K = 10000)
|
||||
--r2=... R2 rating where # is the ohm rating of R2 (eg: 10K = 10000)
|
||||
--num-temps=... the number of temperature points to calculate (default: 20)
|
||||
--max-adc=... the max ADC reading to use. if you use R1, it limits the top value for the thermistor circuit, and thus the possible range of ADC values
|
||||
--min-adc=... the minimum ADC reading to use.
|
||||
-h, --help show this help
|
||||
--r0=... thermistor rating where # is the ohm rating of the thermistor at t0 (eg: 10K = 10000)
|
||||
--t0=... thermistor temp rating where # is the temperature in Celsuis to get r0 (from your datasheet)
|
||||
--beta=... thermistor beta rating. see http://reprap.org/bin/view/Main/MeasuringThermistorBeta
|
||||
--r1=... R1 rating where # is the ohm rating of R1 (eg: 10K = 10000)
|
||||
--r2=... R2 rating where # is the ohm rating of R2 (eg: 10K = 10000)
|
||||
--num-temps=... the number of temperature points to calculate (default: 20)
|
||||
--max-adc=... the max ADC reading to use. if you use R1, it limits the top value for the thermistor circuit, and thus the possible range of ADC values
|
||||
--min-adc=... the minimum ADC reading to use.
|
||||
--vadc=... ADC reference voltage (high leg of R2) same as Vcc
|
||||
--vcc=... Voltage divider supply (high leg of R2) Unused
|
||||
--table Format data as one of an array of tables
|
||||
|
|
@ -43,171 +43,246 @@ from math import *
|
|||
import sys
|
||||
import getopt
|
||||
|
||||
|
||||
class Thermistor:
|
||||
"Class to do the thermistor maths"
|
||||
def __init__(self, r0, t0, beta, r1, r2,vcc,vadc):
|
||||
self.r0 = r0 # stated resistance, e.g. 10K
|
||||
self.t0 = t0 + 273.15 # temperature at stated resistance, e.g. 25C
|
||||
self.beta = beta # stated beta, e.g. 3500
|
||||
self.vadc = vadc # ADC reference
|
||||
self.vcc = vcc # supply voltage to potential divider
|
||||
self.k = r0 * exp(-beta / self.t0) # constant part of calculation
|
||||
"Class to do the thermistor maths"
|
||||
|
||||
if r1 > 0:
|
||||
self.vs = r1 * self.vadc / (r1 + r2) # effective bias voltage
|
||||
self.rs = r1 * r2 / (r1 + r2) # effective bias impedance
|
||||
else:
|
||||
self.vs = self.vadc # effective bias voltage
|
||||
self.rs = r2 # effective bias impedance
|
||||
def __init__(self, r0, t0, beta, r1, r2, vcc, vadc):
|
||||
self.r0 = r0 # stated resistance, e.g. 10K
|
||||
self.t0 = t0 + 273.15 # temperature at stated resistance, e.g. 25C
|
||||
self.beta = beta # stated beta, e.g. 3500
|
||||
self.vadc = vadc # ADC reference
|
||||
self.vcc = vcc # supply voltage to potential divider
|
||||
self.k = r0 * exp(-beta / self.t0) # constant part of calculation
|
||||
|
||||
def temp(self,adc):
|
||||
"Convert ADC reading into a temperature in Celcius"
|
||||
v = adc * self.vadc / 1024 # convert the 10 bit ADC value to a voltage
|
||||
if (self.vs - v): # can be zero due to accuracy limitations
|
||||
r = self.rs * v / (self.vs - v) # resistance of thermistor
|
||||
else:
|
||||
r = self.r0 * 10 # dummy value
|
||||
try:
|
||||
return (self.beta / log(r / self.k)) - 273.15 # temperature
|
||||
except:
|
||||
print("// error for ADC={adc}, {v},{r}".format(adc=adc, v=v,r=r))
|
||||
return 0
|
||||
if r1 > 0:
|
||||
self.vs = r1 * self.vadc / (r1 + r2) # effective bias voltage
|
||||
self.rs = r1 * r2 / (r1 + r2) # effective bias impedance
|
||||
else:
|
||||
self.vs = self.vadc # effective bias voltage
|
||||
self.rs = r2 # effective bias impedance
|
||||
|
||||
def resistance(self, t):
|
||||
"Convert a temperature into a thermistor resistance"
|
||||
return self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0)) # resistance of the thermistor
|
||||
def temp(self, adc):
|
||||
"Convert ADC reading into a temperature in Celcius"
|
||||
v = adc * self.vadc / 1024 # convert the 10 bit ADC value to a voltage
|
||||
if self.vs - v: # can be zero due to accuracy limitations
|
||||
r = self.rs * v / (self.vs - v) # resistance of thermistor
|
||||
else:
|
||||
r = self.r0 * 10 # dummy value
|
||||
try:
|
||||
return (self.beta / log(r / self.k)) - 273.15 # temperature
|
||||
except:
|
||||
print("// error for ADC={adc}, {v},{r}".format(adc=adc, v=v, r=r))
|
||||
return 0
|
||||
|
||||
def resistance(self, t):
|
||||
"Convert a temperature into a thermistor resistance"
|
||||
return self.r0 * exp(
|
||||
self.beta * (1 / (t + 273.15) - 1 / self.t0)
|
||||
) # resistance of the thermistor
|
||||
|
||||
def setting(self, t):
|
||||
"Convert a temperature into a ADC value"
|
||||
r = self.r0 * exp(
|
||||
self.beta * (1 / (t + 273.15) - 1 / self.t0)
|
||||
) # resistance of the thermistor
|
||||
v = self.vs * r / (self.rs + r) # the voltage at the potential divider
|
||||
return round(v / self.vadc * 1024) # the ADC reading
|
||||
|
||||
def setting(self, t):
|
||||
"Convert a temperature into a ADC value"
|
||||
r = self.r0 * exp(self.beta * (1 / (t + 273.15) - 1 / self.t0)) # resistance of the thermistor
|
||||
v = self.vs * r / (self.rs + r) # the voltage at the potential divider
|
||||
return round(v / self.vadc * 1024) # the ADC reading
|
||||
|
||||
def main(argv):
|
||||
|
||||
r0 = 10000;
|
||||
t0 = 25;
|
||||
beta = 3947;
|
||||
r1 = 680;
|
||||
r2 = 1600;
|
||||
num_temps = int(20);
|
||||
max_adc = int(1023);
|
||||
min_adc = int(1);
|
||||
vadc=5.0
|
||||
vcc=5.0
|
||||
mult=4
|
||||
table=False
|
||||
r0 = 10000
|
||||
t0 = 25
|
||||
beta = 3947
|
||||
r1 = 680
|
||||
r2 = 1600
|
||||
num_temps = int(20)
|
||||
max_adc = int(1023)
|
||||
min_adc = int(1)
|
||||
vadc = 5.0
|
||||
vcc = 5.0
|
||||
mult = 4
|
||||
table = False
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "h", ["help", "r0=", "t0=", "beta=", "r1=",
|
||||
"r2=", "max-adc=", "min-adc=",
|
||||
"num-temps=", "vcc=", "vadc=",
|
||||
"multiplier=", "table"])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
argv,
|
||||
"h",
|
||||
[
|
||||
"help",
|
||||
"r0=",
|
||||
"t0=",
|
||||
"beta=",
|
||||
"r1=",
|
||||
"r2=",
|
||||
"max-adc=",
|
||||
"min-adc=",
|
||||
"num-temps=",
|
||||
"vcc=",
|
||||
"vadc=",
|
||||
"multiplier=",
|
||||
"table",
|
||||
],
|
||||
)
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
sys.exit(2)
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif opt == "--r0":
|
||||
r0 = int(arg)
|
||||
elif opt == "--t0":
|
||||
t0 = int(arg)
|
||||
elif opt == "--beta":
|
||||
beta = int(arg)
|
||||
elif opt == "--r1":
|
||||
r1 = int(arg)
|
||||
elif opt == "--r2":
|
||||
r2 = int(arg)
|
||||
elif opt == "--max-adc":
|
||||
max_adc = int(arg)
|
||||
elif opt == "--min-adc":
|
||||
min_adc = int(arg)
|
||||
elif opt == "--num-temps":
|
||||
num_temps = int(arg)
|
||||
elif opt == "--vadc":
|
||||
vadc = float(arg)
|
||||
elif opt == "--vcc":
|
||||
vcc = float(arg)
|
||||
elif opt == "--multiplier":
|
||||
mult = float(arg)
|
||||
elif opt == "--table":
|
||||
table = True
|
||||
if r1:
|
||||
max_adc = int(1023. * r1 / (r1 + r2))
|
||||
else:
|
||||
max_adc = 1023
|
||||
for opt, arg in opts:
|
||||
if opt in ("-h", "--help"):
|
||||
usage()
|
||||
sys.exit()
|
||||
elif opt == "--r0":
|
||||
r0 = int(arg)
|
||||
elif opt == "--t0":
|
||||
t0 = int(arg)
|
||||
elif opt == "--beta":
|
||||
beta = int(arg)
|
||||
elif opt == "--r1":
|
||||
r1 = int(arg)
|
||||
elif opt == "--r2":
|
||||
r2 = int(arg)
|
||||
elif opt == "--max-adc":
|
||||
max_adc = int(arg)
|
||||
elif opt == "--min-adc":
|
||||
min_adc = int(arg)
|
||||
elif opt == "--num-temps":
|
||||
num_temps = int(arg)
|
||||
elif opt == "--vadc":
|
||||
vadc = float(arg)
|
||||
elif opt == "--vcc":
|
||||
vcc = float(arg)
|
||||
elif opt == "--multiplier":
|
||||
mult = float(arg)
|
||||
elif opt == "--table":
|
||||
table = True
|
||||
if r1:
|
||||
max_adc = int(1023.0 * r1 / (r1 + r2))
|
||||
else:
|
||||
max_adc = 1023
|
||||
|
||||
increment = int((max_adc-min_adc)/(num_temps-1));
|
||||
t = Thermistor(r0, t0, beta, r1, r2, vcc, vadc)
|
||||
increment = int((max_adc - min_adc) / (num_temps - 1))
|
||||
t = Thermistor(r0, t0, beta, r1, r2, vcc, vadc)
|
||||
|
||||
adcs = range(min_adc, max_adc, increment);
|
||||
adcs.append(max_adc)
|
||||
# adcs = [1, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 110, 130, 150, 190, 220, 250, 300]
|
||||
adcs = range(min_adc, max_adc, increment)
|
||||
adcs.append(max_adc)
|
||||
# adcs = [1, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100, 110, 130, 150, 190, 220, 250, 300]
|
||||
|
||||
#Chop of negative temperatures (as we're using a unsigned 16-bit value for temp)
|
||||
for i in range(0,len(adcs)):
|
||||
if int(t.temp(adcs[i])*mult) < 0:
|
||||
adcs=adcs[0:i+1]
|
||||
#Replace this with the ADC reading for 0C
|
||||
adcs[i]=int(t.setting(0))
|
||||
#If the closes ADC reading to 0C is negative, convert to next highest ADC reading
|
||||
if int(t.temp(adcs[i])*mult)<0:
|
||||
adcs[i] -=1
|
||||
break
|
||||
print("// Thermistor lookup table for RepRap Temperature Sensor Boards (http://reprap.org/wiki/Temperature_Sensor_2_0)")
|
||||
print("// Made with createTemperatureLookup.py (https://github.com/traumflug/Teacup_Firmware/blob/master/createTemperatureLookup.py)")
|
||||
print("// (patched per https://github.com/drf5n/Teacup_Firmware/blob/Gen7/createTemperatureLookup.py)")
|
||||
print("// default thermistor lookup table")
|
||||
print("// You may be able to improve the accuracy of this table in various ways.")
|
||||
print("// 1. Measure the actual resistance of the resistor. It's \"nominally\" 4.7K, but that's ± 5%.")
|
||||
print("// 2. Measure the actual beta of your thermistor:http://reprap.org/wiki/MeasuringThermistorBeta")
|
||||
print("// 3. Generate more table entries than you need, then trim down the ones in uninteresting ranges.")
|
||||
print("// In either case you'll have to regenerate this table, which requires python, which is difficult to install on windows.")
|
||||
print("// Since you'll have to do some testing to determine the correct temperature for your application anyway, you")
|
||||
print("// may decide that the effort isn't worth it. Who cares if it's reporting the \"right\" temperature as long as it's")
|
||||
print("// keeping the temperature steady enough to print, right?")
|
||||
print("// Temp*%s table from https://github.com/drf5n/Teacup_Firmware/blob/Gen7/createTemperatureLookup.py" %mult)
|
||||
print("// ./createTemperatureLookup.py --r0=%s --t0=%s --r1=%s --r2=%s --beta=%s --max-adc=%s --min-adc=%s --multiplier=%s --vadc=%s" % (
|
||||
r0, t0, r1, r2, beta, max_adc, min_adc, mult, vadc))
|
||||
print("// r0: %s" % (r0))
|
||||
print("// t0: %s" % (t0))
|
||||
print("// r1: %s (parallel with rTherm)" % (r1))
|
||||
print("// r2: %s (series with rTherm)" % (r2))
|
||||
print("// beta: %s" % (beta))
|
||||
print("// min adc: %s at %s V" % (min_adc, min_adc*t.vadc/1024))
|
||||
print("// max adc: %s at %s V" % (max_adc, max_adc*t.vadc/1024))
|
||||
print("// ADC counts from {min} to {max} by {x}".format(min=min_adc, max=max_adc, x=increment))
|
||||
if table == True:
|
||||
print("// #define NUMTABLES 1 // These three lines open the temptable[NUMTABLES]... array")
|
||||
print("// #define NUMTEMPS %s // ... " % (len(adcs)))
|
||||
print("// uint16_t temptable[NUMTABLES][NUMTEMPS][2] PROGMEM = { // ...")
|
||||
print("{ //" + " Table 0 chunk for B={b}, R0={r0}, R1={r1}, R2={r2}, Vref={v}".format(par="{",b=beta,r0=r0,r1=r1,r2=r2,v=vadc))
|
||||
else:
|
||||
print("#define NUMTEMPS %s " % (len(adcs)))
|
||||
print("const uint16_t temptable[NUMTEMPS][2] PROGMEM = {")
|
||||
print("// {ADC, temp*%s }, // temp Rtherm Vtherm resolution power" % (mult))
|
||||
# Chop of negative temperatures (as we're using a unsigned 16-bit value for temp)
|
||||
for i in range(0, len(adcs)):
|
||||
if int(t.temp(adcs[i]) * mult) < 0:
|
||||
adcs = adcs[0 : i + 1]
|
||||
# Replace this with the ADC reading for 0C
|
||||
adcs[i] = int(t.setting(0))
|
||||
# If the closes ADC reading to 0C is negative, convert to next highest ADC reading
|
||||
if int(t.temp(adcs[i]) * mult) < 0:
|
||||
adcs[i] -= 1
|
||||
break
|
||||
print(
|
||||
"// Thermistor lookup table for RepRap Temperature Sensor Boards (http://reprap.org/wiki/Temperature_Sensor_2_0)"
|
||||
)
|
||||
print(
|
||||
"// Made with createTemperatureLookup.py (https://github.com/traumflug/Teacup_Firmware/blob/master/createTemperatureLookup.py)"
|
||||
)
|
||||
print(
|
||||
"// (patched per https://github.com/drf5n/Teacup_Firmware/blob/Gen7/createTemperatureLookup.py)"
|
||||
)
|
||||
print("// default thermistor lookup table")
|
||||
print("// You may be able to improve the accuracy of this table in various ways.")
|
||||
print(
|
||||
"// 1. Measure the actual resistance of the resistor. It's \"nominally\" 4.7K, but that's ± 5%."
|
||||
)
|
||||
print(
|
||||
"// 2. Measure the actual beta of your thermistor:http://reprap.org/wiki/MeasuringThermistorBeta"
|
||||
)
|
||||
print(
|
||||
"// 3. Generate more table entries than you need, then trim down the ones in uninteresting ranges."
|
||||
)
|
||||
print(
|
||||
"// In either case you'll have to regenerate this table, which requires python, which is difficult to install on windows."
|
||||
)
|
||||
print(
|
||||
"// Since you'll have to do some testing to determine the correct temperature for your application anyway, you"
|
||||
)
|
||||
print(
|
||||
"// may decide that the effort isn't worth it. Who cares if it's reporting the \"right\" temperature as long as it's"
|
||||
)
|
||||
print("// keeping the temperature steady enough to print, right?")
|
||||
print(
|
||||
"// Temp*%s table from https://github.com/drf5n/Teacup_Firmware/blob/Gen7/createTemperatureLookup.py"
|
||||
% mult
|
||||
)
|
||||
print(
|
||||
"// ./createTemperatureLookup.py --r0=%s --t0=%s --r1=%s --r2=%s --beta=%s --max-adc=%s --min-adc=%s --multiplier=%s --vadc=%s"
|
||||
% (r0, t0, r1, r2, beta, max_adc, min_adc, mult, vadc)
|
||||
)
|
||||
print("// r0: %s" % (r0))
|
||||
print("// t0: %s" % (t0))
|
||||
print("// r1: %s (parallel with rTherm)" % (r1))
|
||||
print("// r2: %s (series with rTherm)" % (r2))
|
||||
print("// beta: %s" % (beta))
|
||||
print("// min adc: %s at %s V" % (min_adc, min_adc * t.vadc / 1024))
|
||||
print("// max adc: %s at %s V" % (max_adc, max_adc * t.vadc / 1024))
|
||||
print(
|
||||
"// ADC counts from {min} to {max} by {x}".format(
|
||||
min=min_adc, max=max_adc, x=increment
|
||||
)
|
||||
)
|
||||
if table == True:
|
||||
print(
|
||||
"// #define NUMTABLES 1 // These three lines open the temptable[NUMTABLES]... array"
|
||||
)
|
||||
print("// #define NUMTEMPS %s // ... " % (len(adcs)))
|
||||
print("// uint16_t temptable[NUMTABLES][NUMTEMPS][2] PROGMEM = { // ...")
|
||||
print(
|
||||
"{ //"
|
||||
+ " Table 0 chunk for B={b}, R0={r0}, R1={r1}, R2={r2}, Vref={v}".format(
|
||||
par="{", b=beta, r0=r0, r1=r1, r2=r2, v=vadc
|
||||
)
|
||||
)
|
||||
else:
|
||||
print("#define NUMTEMPS %s " % (len(adcs)))
|
||||
print("const uint16_t temptable[NUMTEMPS][2] PROGMEM = {")
|
||||
print(
|
||||
"// {ADC, temp*%s }, // temp Rtherm Vtherm resolution power"
|
||||
% (mult)
|
||||
)
|
||||
|
||||
counter = 0
|
||||
for adc in adcs:
|
||||
counter = counter + 1
|
||||
degC = t.temp(adc)
|
||||
resistance = t.resistance(t.temp(adc))
|
||||
vTherm = adc * t.vadc / 1024
|
||||
ptherm = vTherm * vTherm / resistance
|
||||
resolution = (
|
||||
t.temp(adc - 1) - t.temp(adc) if adc > 1 else t.temp(adc) - t.temp(adc + 1)
|
||||
)
|
||||
sep = "," if counter != len(adcs) else " "
|
||||
print(
|
||||
" {%4s, %6s}%s // %7.2f C, %7.0f Ohm, %0.3f V, %0.2f C/count, %0.2fmW"
|
||||
% (
|
||||
adc,
|
||||
int(t.temp(adc) * mult),
|
||||
sep,
|
||||
degC,
|
||||
resistance,
|
||||
vTherm,
|
||||
resolution,
|
||||
ptherm * 1000,
|
||||
)
|
||||
)
|
||||
if table == False:
|
||||
print("};")
|
||||
else:
|
||||
print("}, // remove comma for last table chunk")
|
||||
print("// }; // Closure for the temptable[NUMTABLES] array")
|
||||
|
||||
counter = 0
|
||||
for adc in adcs:
|
||||
counter = counter +1
|
||||
degC=t.temp(adc)
|
||||
resistance=t.resistance(t.temp(adc))
|
||||
vTherm= adc*t.vadc/1024
|
||||
ptherm= vTherm*vTherm/resistance
|
||||
resolution = ( t.temp(adc-1)-t.temp(adc) if adc>1 else t.temp(adc) -t.temp(adc+1))
|
||||
sep = (',' if counter != len(adcs) else ' ')
|
||||
print(" {%4s, %6s}%s // %7.2f C, %7.0f Ohm, %0.3f V, %0.2f C/count, %0.2fmW" % (adc, int(t.temp(adc)*mult), sep,degC, resistance,vTherm,resolution,ptherm*1000))
|
||||
if table == False:
|
||||
print("};")
|
||||
else:
|
||||
print('}, // remove comma for last table chunk')
|
||||
print("// }; // Closure for the temptable[NUMTABLES] array")
|
||||
|
||||
def usage():
|
||||
print(__doc__)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
main(sys.argv[1:])
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ doc = open("gcode_doc.txt", "wt")
|
|||
for line in f.readlines():
|
||||
m = re_comment.match(line)
|
||||
if m:
|
||||
doc.write(m.group(1) + "\n")
|
||||
doc.write(m.group(1) + "\n")
|
||||
f.close()
|
||||
doc.close()
|
||||
|
|
|
|||
|
|
@ -9,100 +9,102 @@
|
|||
|
||||
# Translate a point relative to some origin
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
def translate(point, origin):
|
||||
return tuple([a-b for a,b in zip(point, origin)])
|
||||
return tuple([a - b for a, b in zip(point, origin)])
|
||||
|
||||
|
||||
# Given two points in 3d space, define a vector
|
||||
def vector(p1, p2):
|
||||
return tuple([b-a for a,b in zip(p1,p2)])
|
||||
return tuple([b - a for a, b in zip(p1, p2)])
|
||||
|
||||
|
||||
# Given two vectors in a plane, find the normal vector
|
||||
def normal(u, v):
|
||||
# A normal vector is the cross-product of two coplanar vectors
|
||||
return tuple([
|
||||
u[1]*v[2] - u[2]*v[1],
|
||||
u[2]*v[0] - u[0]*v[2],
|
||||
u[0]*v[1] - u[1]*v[0]
|
||||
])
|
||||
# A normal vector is the cross-product of two coplanar vectors
|
||||
return tuple(
|
||||
[
|
||||
u[1] * v[2] - u[2] * v[1],
|
||||
u[2] * v[0] - u[0] * v[2],
|
||||
u[0] * v[1] - u[1] * v[0],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def plane_from_three_points(P, Q, R):
|
||||
u = vector(P, Q)
|
||||
v = vector(P, R)
|
||||
n = normal(u, v)
|
||||
u = vector(P, Q)
|
||||
v = vector(P, R)
|
||||
n = normal(u, v)
|
||||
|
||||
# Find the coefficients
|
||||
(A,B,C) = n
|
||||
# Find the coefficients
|
||||
(A, B, C) = n
|
||||
|
||||
# The equation of the plane is thus Ax+By+Cz+K=0.
|
||||
# Solve for K to get the final coefficient
|
||||
(x,y,z) = P
|
||||
K = -(A*x + B*y + C*z)
|
||||
# The equation of the plane is thus Ax+By+Cz+K=0.
|
||||
# Solve for K to get the final coefficient
|
||||
(x, y, z) = P
|
||||
K = -(A * x + B * y + C * z)
|
||||
|
||||
return (A, B, C, K)
|
||||
|
||||
return (A, B, C, K)
|
||||
|
||||
# find the Z offset for any x,y
|
||||
# z = -(Ax + By + K) / C
|
||||
def calcz(x, y, plane, translation=(0,0,0)):
|
||||
(A,B,C,K) = plane
|
||||
def calcz(x, y, plane, translation=(0, 0, 0)):
|
||||
(A, B, C, K) = plane
|
||||
(tx, ty, tz) = translation
|
||||
return -(A*(x-tx) + B*(y-ty) + K) / C + tz
|
||||
return -(A * (x - tx) + B * (y - ty) + K) / C + tz
|
||||
|
||||
|
||||
# Verify a point is on this plane
|
||||
def validate(plane, point):
|
||||
(A, B, C, K) = plane
|
||||
(x, y, z) = point
|
||||
return z == calcz(x, y, plane)
|
||||
(A, B, C, K) = plane
|
||||
(x, y, z) = point
|
||||
return z == calcz(x, y, plane)
|
||||
|
||||
|
||||
def verify_plane(points):
|
||||
print(' ', '\n '.join([str(p) for p in points]))
|
||||
print(" ", "\n ".join([str(p) for p in points]))
|
||||
|
||||
plane = plane_from_three_points( *points)
|
||||
print('Plane coordinates: ', plane)
|
||||
plane = plane_from_three_points(*points)
|
||||
print("Plane coordinates: ", plane)
|
||||
|
||||
if plane[2] == 0:
|
||||
print(' Error: points are colinear')
|
||||
return
|
||||
|
||||
valid = True
|
||||
for p in points:
|
||||
if not validate(plane, p):
|
||||
print("Failed: sample point not on plane, ", p)
|
||||
valid = False
|
||||
print("Validation:", "Failed" if not valid else "Passed")
|
||||
if plane[2] == 0:
|
||||
print(" Error: points are colinear")
|
||||
return
|
||||
|
||||
valid = True
|
||||
for p in points:
|
||||
if not validate(plane, p):
|
||||
print("Failed: sample point not on plane, ", p)
|
||||
valid = False
|
||||
print("Validation:", "Failed" if not valid else "Passed")
|
||||
|
||||
|
||||
samples = [
|
||||
# canonical example
|
||||
[ (1,-2,0), (4,-2,-2), (4,1,4) ],
|
||||
|
||||
# three colinear points (infinite planes)
|
||||
[ (2,2,2), (4,4,4), (10,10,10) ],
|
||||
|
||||
# Extreme tilt example in mm
|
||||
[ (57,123,-5), (200,0,35), (0,207,2) ],
|
||||
|
||||
# Some more examples in um
|
||||
[ (0, 0, 1300), (200000, 200000, 3500), (0, 150000, -1000) ],
|
||||
[ (20000, 20000, -300), (220000, 120000, -1700), (120000, 220000, -700) ],
|
||||
|
||||
# some example in tenths of mm
|
||||
[ (200, 200, -300), (2200, 1200, -1700), (1200, 2200, -700) ],
|
||||
|
||||
[ (20000, 20000 , -300 ), (220000, 120000 , -1700 ), (120000, 220000 , -700 ) ],
|
||||
[ (200, 200, -300 ), (2200, 1200, -1700 ), (1200, 2200, -700 ) ]
|
||||
# canonical example
|
||||
[(1, -2, 0), (4, -2, -2), (4, 1, 4)],
|
||||
# three colinear points (infinite planes)
|
||||
[(2, 2, 2), (4, 4, 4), (10, 10, 10)],
|
||||
# Extreme tilt example in mm
|
||||
[(57, 123, -5), (200, 0, 35), (0, 207, 2)],
|
||||
# Some more examples in um
|
||||
[(0, 0, 1300), (200000, 200000, 3500), (0, 150000, -1000)],
|
||||
[(20000, 20000, -300), (220000, 120000, -1700), (120000, 220000, -700)],
|
||||
# some example in tenths of mm
|
||||
[(200, 200, -300), (2200, 1200, -1700), (1200, 2200, -700)],
|
||||
[(20000, 20000, -300), (220000, 120000, -1700), (120000, 220000, -700)],
|
||||
[(200, 200, -300), (2200, 1200, -1700), (1200, 2200, -700)],
|
||||
]
|
||||
|
||||
for points in samples:
|
||||
verify_plane(points)
|
||||
verify_plane(points)
|
||||
|
||||
print("====[Translated]=========")
|
||||
# Translate plane to origin at P (simplifies by removing K coefficient)
|
||||
# A*x' + B*y' + C*z' = 0
|
||||
P = points[0]
|
||||
T = translate((0,0,0), P)
|
||||
xpoints = [translate(p, P) for p in points]
|
||||
verify_plane(xpoints)
|
||||
print("=========================\n")
|
||||
print("====[Translated]=========")
|
||||
# Translate plane to origin at P (simplifies by removing K coefficient)
|
||||
# A*x' + B*y' + C*z' = 0
|
||||
P = points[0]
|
||||
T = translate((0, 0, 0), P)
|
||||
xpoints = [translate(p, P) for p in points]
|
||||
verify_plane(xpoints)
|
||||
print("=========================\n")
|
||||
|
|
|
|||
|
|
@ -9,30 +9,32 @@ diff_list = list()
|
|||
|
||||
pseudo_print = list()
|
||||
|
||||
#define STEPS_PER_M_X 40000
|
||||
#define STEPS_PER_M_Y 40000
|
||||
#define STEPS_PER_M_Z 320000
|
||||
# define STEPS_PER_M_X 40000
|
||||
# define STEPS_PER_M_Y 40000
|
||||
# define STEPS_PER_M_Z 320000
|
||||
|
||||
|
||||
def parse_stepper_position(line):
|
||||
s_line = line.split()
|
||||
|
||||
X = float(s_line[1]) / 40. # X-axis
|
||||
Y = float(s_line[2]) / 40. # Y-axis
|
||||
Z = float(s_line[3]) / 320. # Z-axis
|
||||
|
||||
X = float(s_line[1]) / 40.0 # X-axis
|
||||
Y = float(s_line[2]) / 40.0 # Y-axis
|
||||
Z = float(s_line[3]) / 320.0 # Z-axis
|
||||
|
||||
return X, Y, Z
|
||||
|
||||
|
||||
|
||||
def parse_m114_position(line):
|
||||
s_line = line.split(',')
|
||||
|
||||
s_line = line.split(",")
|
||||
|
||||
X = float(s_line[0][4:])
|
||||
Y = float(s_line[1][2:])
|
||||
Z = float(s_line[2][2:])
|
||||
|
||||
|
||||
return X, Y, Z
|
||||
|
||||
with open(in_file, 'r') as file:
|
||||
|
||||
with open(in_file, "r") as file:
|
||||
start_with_line = 50
|
||||
|
||||
found_m114 = False
|
||||
|
|
@ -43,22 +45,22 @@ with open(in_file, 'r') as file:
|
|||
found_m114 = False
|
||||
x1, y1, z1 = parse_m114_position(line)
|
||||
x = x2 - x1
|
||||
diff_list.append('{}\t\t\t{}\t\t\t{}\t\t\t{}\n'.format(i, x1, x2, x))
|
||||
pseudo_print.append('{}\t\t\t{}\t\t\t{}\n'.format(x2, y2, z2))
|
||||
diff_list.append("{}\t\t\t{}\t\t\t{}\t\t\t{}\n".format(i, x1, x2, x))
|
||||
pseudo_print.append("{}\t\t\t{}\t\t\t{}\n".format(x2, y2, z2))
|
||||
|
||||
if line[0] == '#':
|
||||
if line[2:6] == 'M114':
|
||||
if line[0] == "#":
|
||||
if line[2:6] == "M114":
|
||||
found_m114 = True
|
||||
# find the line with stepping positions before the M114
|
||||
# print(linecache.getline(in_file, i))
|
||||
for x in range(i - 1, i-20, -1):
|
||||
for x in range(i - 1, i - 20, -1):
|
||||
pre_m114_line = linecache.getline(in_file, x)
|
||||
if len(pre_m114_line.split()) == 21:
|
||||
break
|
||||
x2, y2, z2 = parse_stepper_position(pre_m114_line)
|
||||
|
||||
with open(out_file, 'w') as file:
|
||||
with open(out_file, "w") as file:
|
||||
file.writelines(diff_list)
|
||||
|
||||
with open(pp_file, 'w') as file:
|
||||
with open(pp_file, "w") as file:
|
||||
file.writelines(pseudo_print)
|
||||
|
|
|
|||
Loading…
Reference in New Issue