Configtool: refactor boardpanel for MVC.
Move model functionality out of boardpanel.py into a new class, Board, so we can more easily add commandline driven tests in the future.
This commit is contained in:
parent
c80b4d4d28
commit
d3062ca1dd
|
|
@ -0,0 +1,460 @@
|
||||||
|
|
||||||
|
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,
|
||||||
|
reTempTable4, reTempTable7)
|
||||||
|
|
||||||
|
class Board:
|
||||||
|
def __init__(self):
|
||||||
|
self.configFile = None
|
||||||
|
|
||||||
|
self.cfgValues = {}
|
||||||
|
self.heaters = []
|
||||||
|
self.sensors = []
|
||||||
|
self.candHeatPins = []
|
||||||
|
self.candThermPins = []
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
return vF_CPU, vCPU
|
||||||
|
|
||||||
|
def hasData(self):
|
||||||
|
return (self.configFile != None)
|
||||||
|
|
||||||
|
def getFileName(self):
|
||||||
|
return self.configFile
|
||||||
|
|
||||||
|
def loadConfigFile(self, cfgDir, fn):
|
||||||
|
cfgFn = os.path.join(cfgDir, "board.generic.h")
|
||||||
|
try:
|
||||||
|
self.cfgBuffer = list(open(cfgFn))
|
||||||
|
except:
|
||||||
|
return False, cfgFn
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.userBuffer = list(open(fn))
|
||||||
|
except:
|
||||||
|
return False, fn
|
||||||
|
|
||||||
|
self.configFile = fn
|
||||||
|
|
||||||
|
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 = {}
|
||||||
|
|
||||||
|
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 = ""
|
||||||
|
|
||||||
|
self.parseDefineName(ln)
|
||||||
|
self.parseDefineValue(ln)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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 reHelpTextStart.match(ln):
|
||||||
|
gatheringHelpText = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ln.rstrip().endswith("\\"):
|
||||||
|
prevLines += ln.rstrip()[:-1]
|
||||||
|
continue
|
||||||
|
|
||||||
|
if prevLines != "":
|
||||||
|
ln = prevLines + ln
|
||||||
|
prevLines = ""
|
||||||
|
|
||||||
|
if self.parseCandidateValues(ln):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self.parseDefineValue(ln):
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Parsing done. All parsed stuff is now in these arrays and dicts.
|
||||||
|
# Uncomment for debugging.
|
||||||
|
#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 and booleans.
|
||||||
|
#print self.cfgNames # Names found in the generic file.
|
||||||
|
#print self.helpText
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return True, None
|
||||||
|
|
||||||
|
def parseDefineName(self, ln):
|
||||||
|
m = reDefBool.search(ln)
|
||||||
|
if m:
|
||||||
|
t = m.groups()
|
||||||
|
if len(t) == 1:
|
||||||
|
self.cfgNames.append(t[0])
|
||||||
|
return True
|
||||||
|
|
||||||
|
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 = reHeater4.search(s)
|
||||||
|
if m:
|
||||||
|
t = m.groups()
|
||||||
|
if len(t) == 4:
|
||||||
|
return list(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')
|
||||||
|
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):
|
||||||
|
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\n")
|
||||||
|
for s in self.heaters:
|
||||||
|
sstr = "%-10s%-9s%-8s%s" % ((s[0] + ","), (s[1] + ","),
|
||||||
|
(s[2] + ","), s[3])
|
||||||
|
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:
|
||||||
|
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
|
||||||
|
|
||||||
|
fp.write(ln)
|
||||||
|
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
@ -24,22 +24,20 @@ from configtool.cpupage import CpuPage
|
||||||
from configtool.protectedfiles import protectedFiles
|
from configtool.protectedfiles import protectedFiles
|
||||||
from configtool.thermistortablefile import generateTempTables
|
from configtool.thermistortablefile import generateTempTables
|
||||||
|
|
||||||
|
from configtool.board import Board
|
||||||
|
|
||||||
class BoardPanel(wx.Panel):
|
class BoardPanel(wx.Panel):
|
||||||
def __init__(self, parent, nb, settings):
|
def __init__(self, parent, nb, settings):
|
||||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.settings = settings
|
|
||||||
self.protFileLoaded = False
|
|
||||||
|
|
||||||
self.deco = Decoration()
|
self.deco = Decoration()
|
||||||
self.configFile = None
|
self.protFileLoaded = False
|
||||||
|
|
||||||
|
self.settings = settings
|
||||||
|
|
||||||
|
self.board = Board()
|
||||||
|
|
||||||
self.cfgValues = {}
|
|
||||||
self.heaters = []
|
|
||||||
self.sensors = []
|
|
||||||
self.candHeatPins = []
|
|
||||||
self.candThermPins = []
|
|
||||||
self.dir = os.path.join(self.settings.folder, "config")
|
self.dir = os.path.join(self.settings.folder, "config")
|
||||||
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
self.cfgDir = os.path.join(self.settings.folder, "configtool")
|
||||||
|
|
||||||
|
|
@ -82,15 +80,7 @@ class BoardPanel(wx.Panel):
|
||||||
return page
|
return page
|
||||||
|
|
||||||
def getCPUInfo(self):
|
def getCPUInfo(self):
|
||||||
vF_CPU = None
|
return self.board.getCPUInfo()
|
||||||
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]
|
|
||||||
|
|
||||||
return vF_CPU, vCPU
|
|
||||||
|
|
||||||
def assertModified(self, pg, flag = True):
|
def assertModified(self, pg, flag = True):
|
||||||
self.pageModified[pg] = flag
|
self.pageModified[pg] = flag
|
||||||
|
|
@ -103,10 +93,10 @@ class BoardPanel(wx.Panel):
|
||||||
return not (False in self.pageValid)
|
return not (False in self.pageValid)
|
||||||
|
|
||||||
def hasData(self):
|
def hasData(self):
|
||||||
return (self.configFile != None)
|
return self.board.hasData()
|
||||||
|
|
||||||
def getFileName(self):
|
def getFileName(self):
|
||||||
return self.configFile
|
return self.board.getFileName()
|
||||||
|
|
||||||
def assertValid(self, pg, flag = True):
|
def assertValid(self, pg, flag = True):
|
||||||
self.pageValid[pg] = flag
|
self.pageValid[pg] = flag
|
||||||
|
|
@ -197,155 +187,9 @@ class BoardPanel(wx.Panel):
|
||||||
return
|
return
|
||||||
|
|
||||||
def loadConfigFile(self, fn):
|
def loadConfigFile(self, fn):
|
||||||
cfgFn = os.path.join(self.cfgDir, "board.generic.h")
|
ok, file = self.board.loadConfigFile(self.cfgDir, fn)
|
||||||
try:
|
if not ok:
|
||||||
self.cfgBuffer = list(open(cfgFn))
|
return ok, file
|
||||||
except:
|
|
||||||
return False, cfgFn
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.userBuffer = list(open(fn))
|
|
||||||
except:
|
|
||||||
return False, fn
|
|
||||||
|
|
||||||
self.configFile = fn
|
|
||||||
|
|
||||||
self.processors = []
|
|
||||||
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 = {}
|
|
||||||
|
|
||||||
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 = ""
|
|
||||||
|
|
||||||
self.parseDefineName(ln)
|
|
||||||
self.parseDefineValue(ln)
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# 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 reHelpTextStart.match(ln):
|
|
||||||
gatheringHelpText = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ln.rstrip().endswith("\\"):
|
|
||||||
prevLines += ln.rstrip()[:-1]
|
|
||||||
continue
|
|
||||||
|
|
||||||
if prevLines != "":
|
|
||||||
ln = prevLines + ln
|
|
||||||
prevLines = ""
|
|
||||||
|
|
||||||
if self.parseCandidateValues(ln):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.parseDefineValue(ln):
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
# Parsing done. All parsed stuff is now in these arrays and dicts.
|
|
||||||
# Uncomment for debugging.
|
|
||||||
#print self.processors
|
|
||||||
#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 and booleans.
|
|
||||||
#print self.cfgNames # Names found in the generic file.
|
|
||||||
#print self.helpText
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if os.path.basename(fn) in protectedFiles:
|
if os.path.basename(fn) in protectedFiles:
|
||||||
self.parent.enableSaveBoard(False, True)
|
self.parent.enableSaveBoard(False, True)
|
||||||
|
|
@ -355,153 +199,22 @@ class BoardPanel(wx.Panel):
|
||||||
self.parent.enableSaveBoard(True, True)
|
self.parent.enableSaveBoard(True, True)
|
||||||
|
|
||||||
self.parent.setBoardTabFile(os.path.basename(fn))
|
self.parent.setBoardTabFile(os.path.basename(fn))
|
||||||
self.pgHeaters.setCandidatePins(self.candHeatPins)
|
self.pgHeaters.setCandidatePins(self.board.candHeatPins)
|
||||||
self.pgSensors.setCandidatePins(self.candThermPins)
|
self.pgSensors.setCandidatePins(self.board.candThermPins)
|
||||||
self.pgCpu.setCandidateProcessors(self.candProcessors)
|
self.pgCpu.setCandidateProcessors(self.board.candProcessors)
|
||||||
self.pgCpu.setCandidateClocks(self.candClocks)
|
self.pgCpu.setCandidateClocks(self.board.candClocks)
|
||||||
|
|
||||||
for pg in self.pages:
|
for pg in self.pages:
|
||||||
pg.insertValues(self.cfgValues)
|
pg.insertValues(self.board.cfgValues)
|
||||||
pg.setHelpText(self.helpText)
|
pg.setHelpText(self.board.helpText)
|
||||||
|
|
||||||
self.pgSensors.setSensors(self.sensors)
|
self.pgSensors.setSensors(self.board.sensors)
|
||||||
self.pgHeaters.setHeaters(self.heaters)
|
self.pgHeaters.setHeaters(self.board.heaters)
|
||||||
|
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
def parseDefineName(self, ln):
|
|
||||||
m = reDefBool.search(ln)
|
|
||||||
if m:
|
|
||||||
t = m.groups()
|
|
||||||
if len(t) == 1:
|
|
||||||
self.cfgNames.append(t[0])
|
|
||||||
return True
|
|
||||||
|
|
||||||
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 = reHeater4.search(s)
|
|
||||||
if m:
|
|
||||||
t = m.groups()
|
|
||||||
if len(t) == 4:
|
|
||||||
return list(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')
|
|
||||||
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 onSaveConfig(self, evt):
|
def onSaveConfig(self, evt):
|
||||||
path = self.configFile
|
path = self.getFileName()
|
||||||
return self.saveConfigFile(path)
|
return self.saveConfigFile(path)
|
||||||
|
|
||||||
def onSaveConfigAs(self, evt):
|
def onSaveConfigAs(self, evt):
|
||||||
|
|
@ -544,6 +257,12 @@ class BoardPanel(wx.Panel):
|
||||||
dlg.Destroy()
|
dlg.Destroy()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
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]
|
ext = os.path.splitext(os.path.basename(path))[1]
|
||||||
self.dir = os.path.dirname(path)
|
self.dir = os.path.dirname(path)
|
||||||
|
|
||||||
|
|
@ -551,7 +270,7 @@ class BoardPanel(wx.Panel):
|
||||||
path += ".h"
|
path += ".h"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fp = file(path, 'w')
|
self.board.saveConfigFile(path, values)
|
||||||
except:
|
except:
|
||||||
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
|
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
|
||||||
"File error", wx.OK + wx.ICON_ERROR)
|
"File error", wx.OK + wx.ICON_ERROR)
|
||||||
|
|
@ -559,148 +278,10 @@ class BoardPanel(wx.Panel):
|
||||||
dlg.Destroy()
|
dlg.Destroy()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.configFile = path
|
|
||||||
|
|
||||||
values = {}
|
|
||||||
|
|
||||||
for pg in self.pages:
|
|
||||||
v1 = pg.getValues()
|
|
||||||
for k in v1.keys():
|
|
||||||
values[k] = v1[k]
|
|
||||||
|
|
||||||
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\n")
|
|
||||||
for s in self.heaters:
|
|
||||||
sstr = "%-10s%-9s%-8s%s" % ((s[0] + ","), (s[1] + ","),
|
|
||||||
(s[2] + ","), s[3])
|
|
||||||
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:
|
|
||||||
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
|
|
||||||
|
|
||||||
fp.write(ln)
|
|
||||||
|
|
||||||
fp.close()
|
|
||||||
return self.generateTempTables()
|
return self.generateTempTables()
|
||||||
|
|
||||||
def generateTempTables(self):
|
def generateTempTables(self):
|
||||||
if not generateTempTables(self.sensors, self.settings):
|
if not generateTempTables(self.board.sensors, self.settings):
|
||||||
dlg = wx.MessageDialog(self, "Error writing to file thermistortable.h.",
|
dlg = wx.MessageDialog(self, "Error writing to file thermistortable.h.",
|
||||||
"File error", wx.OK + wx.ICON_ERROR)
|
"File error", wx.OK + wx.ICON_ERROR)
|
||||||
dlg.ShowModal()
|
dlg.ShowModal()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue