Teacup_Firmware/config.py

2417 lines
68 KiB
Python

#!/bin/env python
import os
import wx
import re
import time
VERSION = "0.1"
try:
from agw import customtreectrl as CT
except ImportError:
import wx.lib.agw.customtreectrl as CT
from config_helptext import helpText
supportedCPUs = ['ATmega168', 'ATmega328P', 'ATmega644P', 'ATmega644PA',
'ATmega1280', 'ATmega1284P', 'ATmega2560', 'AT90USB1286']
BSIZE = (90, 60)
BSIZESMALL = (90, 30)
reDefine = re.compile("\s*#define\s+(\S+)\s+(\S+)")
reDefQS = re.compile("\s*#define\s+(\S+)\s+(\"[^\"]*\")")
reDefTS = re.compile("\s*(DEFINE_TEMP_SENSOR\\([^)]*\\))")
reDefHT = re.compile("\s*(DEFINE_HEATER\\([^)]*\\))")
reDefBool = re.compile("\s*#define\s+(\S+)\s+")
reIncArduino = re.compile("\s*#include\s+\"arduino.h\"")
reSensor3 = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
reSensor4 = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
reHeater = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
reInteger = re.compile("^\d+$")
reFloat = re.compile("^\d+(\.\d+)?$")
rePin = re.compile("^[AD]IO\d+$")
reAVR = re.compile("__AVR_(\w+)__")
defineValueFormat = "#define %-30.30s %s\n"
defineBoolFormat = "#define %s\n"
defineHeaterFormat = "#define HEATER_%s HEATER_%s\n"
defineULFormat = "#define %-30.30s %sUL\n"
defineDCExtruderFormat = "#define %-30.30s HEATER_%s\n"
class Page:
def __init__(self):
self.modified = False
self.valid = True
self.fieldValid = {}
self.textControls = {}
self.checkBoxes = {}
self.radioButtons = {}
self.choices = {}
def addTextCtrl(self, name, labelWidth, ht, validator):
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
lsz.Add(st)
tc = wx.TextCtrl(self, wx.ID_ANY, "", style = wx.TE_RIGHT, name = name)
self.fieldValid[name] = True
tc.Bind(wx.EVT_TEXT, validator)
self.textControls[name] = tc
lsz.Add(tc)
if ht:
hts = ht
else:
if name in helpText.keys():
hts = helpText[name]
else:
hts = ""
tc.SetToolTipString(hts)
return lsz
def addCheckBox(self, name, ht, validator):
if name in self.labels.keys():
lbl = self.labels[name]
else:
lbl = name
cb = wx.CheckBox(self, wx.ID_ANY, lbl)
cb.Bind(wx.EVT_CHECKBOX, validator)
self.checkBoxes[name] = cb
if ht:
hts = ht
else:
if name in helpText.keys():
hts = helpText[name]
else:
hts = ""
cb.SetToolTipString(hts)
return cb
def addRadioButton(self, name, style, ht, validator):
rb = wx.RadioButton(self, wx.ID_ANY, self.labels[name], style = style)
self.Bind(wx.EVT_RADIOBUTTON, validator, rb)
self.radioButtons[name] = rb
if ht:
hts = ht
else:
if name in helpText.keys():
hts = helpText[name]
else:
hts = ""
rb.SetToolTipString(hts)
return rb
def addChoice(self, name, choices, selection, labelWidth, ht, validator):
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
lsz.Add(st)
ch = wx.Choice(self, wx.ID_ANY, choices = choices, name = name)
ch.Bind(wx.EVT_CHOICE, validator)
ch.SetSelection(selection)
lsz.Add(ch)
self.choices[name] = ch
if ht:
hts = ht
else:
if name in helpText.keys():
hts = helpText[name]
else:
hts = ""
ch.SetToolTipString(hts)
return lsz
def setChoice(self, name, cfgValues, choices, default):
if name in cfgValues.keys():
bv = cfgValues[name]
else:
bv = self.defaultClock
try:
s = choices.index(bv)
except:
try:
s = choices.index(default)
except:
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 validatePin(self, tc):
name = tc.GetName()
w = tc.GetValue().strip()
if w == "":
valid = True
else:
m = reInteger.match(w)
if m:
valid = True
else:
if self.includeArduino:
m = rePin.match(w)
if m:
valid = True
else:
valid = False
else:
valid = False
self.setFieldValidity(name, valid)
if valid:
tc.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
else:
tc.SetBackgroundColour("pink")
tc.Refresh()
def onCheckBox(self, evt):
self.assertModified(True)
evt.Skip()
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
class MechanicalPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.id = idPg
self.parent = parent
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.msrKeys = ['SEARCH_FEEDRATE_X', 'SEARCH_FEEDRATE_Y',
'SEARCH_FEEDRATE_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.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"}
labelWidth = 40;
sz = wx.GridBagSizer()
sz.AddSpacer((10, 10), pos = (0, 0))
b = wx.StaticBox(self, wx.ID_ANY, "Steps Per Meter")
kh = 'STEPS_PER_M'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.spmKeys:
tc = self.addTextCtrl(k, labelWidth, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 1))
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Feedrate")
kh = 'MAXIMUM_FEEDRATE'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.mfrKeys:
tc = self.addTextCtrl(k, labelWidth, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 5))
b = wx.StaticBox(self, wx.ID_ANY, "Search Feedrate")
kh = 'SEARCH_FEEDRATE'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.msrKeys:
tc = self.addTextCtrl(k, labelWidth, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 7))
b = wx.StaticBox(self, wx.ID_ANY, "Endstop Clearance")
kh = 'ENDSTOP_CLEARANCE'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.eclKeys:
tc = self.addTextCtrl(k, labelWidth, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (3, 1))
b = wx.StaticBox(self, wx.ID_ANY, "Travel Limits")
kh = 'MINMAX'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.minmaxKeys:
tc = self.addTextCtrl(k, labelWidth, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (3, 3))
cb = self.addCheckBox('E_ABSOLUTE', None, self.onCheckBox)
sz.Add(cb, pos = (3, 7), flag = wx.ALIGN_CENTER_VERTICAL)
bsz = wx.BoxSizer(wx.VERTICAL)
b = wx.Button(self, wx.ID_ANY, "Calculate\nBelt Driven", size = BSIZE)
b.SetToolTipString("Open the calculator for Axes that are belt-driven")
bsz.Add(b, 1, wx.ALL, 5)
b = wx.Button(self, wx.ID_ANY, "Calculate\nScrew Driven", size = BSIZE)
bsz.Add(b, 1, wx.ALL, 5)
b.SetToolTipString("Open the calculator for Axes that are screw-driven")
sz.Add(bsz, pos = (1, 3))
self.SetSizer(sz)
def insertValues(self, cfgValues):
self.assertValid(True)
for k in self.fieldValid.keys():
self.fieldValid[k] = True
for k in self.textControls.keys():
if k in cfgValues.keys():
self.textControls[k].SetValue(cfgValues[k])
else:
self.textControls[k].SetValue("")
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)
self.assertModified(False)
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 1. MECHANICAL/HARDWARE *\n\
* *\n\
\\***************************************************************************/\n")
for k in self.spmKeys + self.mfrKeys + self.msrKeys + self.eclKeys + \
self.minmaxKeys:
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
k = 'E_ABSOLUTE'
cb = self.checkBoxes[k]
if cb.IsChecked():
fp.write(defineBoolFormat % k)
class AccelerationPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
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.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.AddSpacer((20, 40), pos = (0, 0))
b = wx.StaticBox(self, wx.ID_ANY, "Acceleration Type:")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
style = wx.RB_GROUP
for k in self.accTypeKeys:
rb = self.addRadioButton(k, style, None, self.onAccTypeSelect)
style = 0
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
sbox.AddSpacer((5, 5))
rb = wx.RadioButton(self, wx.ID_ANY, "None", style = style)
rb.SetValue(True)
self.Bind(wx.EVT_RADIOBUTTON, self.onAccTypeSelect, rb)
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 1))
b = wx.StaticBox(self, wx.ID_ANY, "Ramping Parameters:")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
k = 'ACCELERATION'
tc = self.addTextCtrl(k, 80, None, self.onTextCtrlInteger)
self.textControls[k].Enable(False)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
k = 'LOOKAHEAD'
cb = self.addCheckBox(k, None, self.onCheckBox)
self.checkBoxes[k].Enable(False)
sbox.Add(cb, 1, wx.ALIGN_CENTER_HORIZONTAL)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 3))
b = wx.StaticBox(self, wx.ID_ANY, "Maximum Jerk")
kh = 'MAX_JERK'
ht = None
if kh in helpText.keys():
ht = helpText[kh]
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k in self.jerkKeys:
tc = self.addTextCtrl(k, 40, ht, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.AddSpacer((80, 20), pos = (1, 4))
sz.Add(sbox, pos = (1, 5))
self.SetSizer(sz)
def onAccTypeSelect(self, evt):
self.assertModified(True)
rb = evt.GetEventObject()
label = rb.GetLabel()
if label == self.labels['ACCELERATION_RAMPING']:
ena = True
else:
ena = False
self.checkBoxes['LOOKAHEAD'].Enable(ena)
self.textControls['ACCELERATION'].Enable(ena)
evt.Skip()
def insertValues(self, cfgValues):
self.assertValid(True)
for k in self.fieldValid.keys():
self.fieldValid[k] = True
self.checkBoxes['LOOKAHEAD'].Enable(False)
self.textControls['ACCELERATION'].Enable(False)
for k in self.textControls.keys():
if k in cfgValues.keys():
self.textControls[k].SetValue(cfgValues[k])
else:
self.textControls[k].SetValue("")
for tag in ['ACCELERATION_REPRAP', 'ACCELERATION_RAMPING',
'ACCELERATION_TEMPORAL']:
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)
k = 'LOOKAHEAD'
if k in cfgValues.keys() and cfgValues[k]:
self.checkBoxes[k].SetValue(True)
else:
self.checkBoxes[k].SetValue(False)
self.assertModified(False)
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 2. ACCELERATION *\n\
* *\n\
\\***************************************************************************/\n")
for tag in ['ACCELERATION_REPRAP', 'ACCELERATION_RAMPING',
'ACCELERATION_TEMPORAL']:
rb = self.radioButtons[tag]
if rb.GetValue():
fp.write(defineBoolFormat % tag)
k = 'ACCELERATION'
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
k = 'LOOKAHEAD'
cb = self.checkBoxes[k]
if cb.IsChecked():
fp.write(defineBoolFormat % k)
for k in ['MAX_JERK_X', 'MAX_JERK_Y', 'MAX_JERK_Z', 'MAX_JERK_E']:
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
class PinoutsPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.parent = parent
self.id = idPg
self.pinXKeys = [('X_STEP_PIN', 0), ('X_DIR_PIN', 0), ('X_MIN_PIN', 0),
('X_MAX_PIN', 0), ('X_ENABLE_PIN', 0),
('X_INVERT_DIR', 1), ('X_INVERT_MIN', 1),
('X_INVERT_MAX', 1), ('X_INVERT_ENABLE', 1)]
self.pinYKeys = [('Y_STEP_PIN', 0), ('Y_DIR_PIN', 0), ('Y_MIN_PIN', 0),
('Y_MAX_PIN', 0), ('Y_ENABLE_PIN', 0),
('Y_INVERT_DIR', 1), ('Y_INVERT_MIN', 1),
('Y_INVERT_MAX', 1), ('Y_INVERT_ENABLE', 1)]
self.pinZKeys = [('Z_STEP_PIN', 0), ('Z_DIR_PIN', 0), ('Z_MIN_PIN', 0),
('Z_MAX_PIN', 0), ('Z_ENABLE_PIN', 0),
('Z_INVERT_DIR', 1), ('Z_INVERT_MIN', 1),
('Z_INVERT_MAX', 1), ('Z_INVERT_ENABLE', 1)]
self.pinEKeys = [('E_STEP_PIN', 0), ('E_DIR_PIN', 0), ('E_ENABLE_PIN', 0),
('E_INVERT_DIR', 1), ('E_INVERT_ENABLE', 1)]
self.pinMiscKeys = [('USE_INTERNAL_PULLUPS', 1), ('TX_ENABLE_PIN', 0),
('RX_ENABLE_PIN', 0), ('PS_ON_PIN', 0),
('PS_MOSFET_PIN', 0), ('STEPPER_ENABLE_PIN', 0),
('STEPPER_INVERT_ENABLE', 1), ('SD_CARD_DETECT', 0),
('SD_WRITE_PROTECT', 0), ('DEBUG_LED_PIN', 0)]
self.labels = {'INCLUDE_ARDUINO': "Include arduino.h header file",
'USE_INTERNAL_PULLUPS': "Use Internal Pullups",
'TX_ENABLE_PIN': "Tx Enable Pin:",
'RX_ENABLE_PIN': "Rx Enable Pin:",
'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_MOSFET_PIN': "PSU MOSFET Pin:",
'STEPPER_ENABLE_PIN': "Stepper Enable Pin:",
'STEPPER_INVERT_ENABLE': "Stepper Invert Enable",
'SD_CARD_DETECT': "SD Detect Pin:",
'SD_WRITE_PROTECT': "Write Protect Pin:",
'DEBUG_LED_PIN': "Debug LED Pin:"}
labelWidth = 80
labelWidthM = 100
self.includeArduino = False
sz = wx.GridBagSizer()
sz.AddSpacer((10, 10), pos = (0, 0))
b = wx.StaticBox(self, wx.ID_ANY, "X Axis")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k, ctype in self.pinXKeys:
if ctype == 0:
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlPin)
sbox.Add(tc)
else:
cb = self.addCheckBox(k, None, self.onCheckBox)
sbox.Add(cb, 1, wx.LEFT, 30)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 1))
b = wx.StaticBox(self, wx.ID_ANY, "Y Axis")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k, ctype in self.pinYKeys:
if ctype == 0:
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlPin)
sbox.Add(tc)
else:
cb = self.addCheckBox(k, None, self.onCheckBox)
sbox.Add(cb, 1, wx.LEFT, 30)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 3))
b = wx.StaticBox(self, wx.ID_ANY, "Z Axis")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k, ctype in self.pinZKeys:
if ctype == 0:
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlPin)
sbox.Add(tc)
else:
cb = self.addCheckBox(k, None, self.onCheckBox)
sbox.Add(cb, 1, wx.LEFT, 30)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 5))
b = wx.StaticBox(self, wx.ID_ANY, "E Axis")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
for k, ctype in self.pinEKeys:
if ctype == 0:
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlPin)
sbox.Add(tc)
else:
cb = self.addCheckBox(k, None, self.onCheckBox)
sbox.Add(cb, 1, wx.LEFT, 30)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 7))
k = 'USE_INTERNAL_PULLUPS'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (3, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
k = 'TX_ENABLE_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (5, 1))
k = 'RX_ENABLE_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (6, 1))
k = 'PS_ON_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (3, 3))
k = 'PS_MOSFET_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (4, 3))
k = 'STEPPER_ENABLE_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (6, 3))
k = 'STEPPER_INVERT_ENABLE'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (7, 3), flag = wx.ALIGN_CENTER_HORIZONTAL)
k = 'SD_CARD_DETECT'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (3, 5))
k = 'SD_WRITE_PROTECT'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (4, 5))
k = 'DEBUG_LED_PIN'
tc = self.addTextCtrl(k, labelWidthM, None, self.onTextCtrlPin)
sz.Add(tc, pos = (3, 7))
k = 'INCLUDE_ARDUINO'
cb = self.addCheckBox(k, None, self.onCheckBoxArduino)
sz.Add(cb, pos = (5, 7), flag = wx.ALIGN_CENTER_HORIZONTAL)
self.SetSizer(sz)
def revalidatePins(self):
for k in self.textControls.keys():
self.validatePin(self.textControls[k])
self.parent.revalidatePins(self.includeArduino)
def onCheckBoxArduino(self, evt):
self.assertModified(True)
cb = evt.GetEventObject()
self.includeArduino = cb.IsChecked()
self.revalidatePins()
evt.Skip()
def setIncludeArduino(self, flag):
self.includeArduino = flag
def insertValues(self, cfgValues):
self.assertValid(True)
for k in self.fieldValid.keys():
self.fieldValid[k] = True
for k in self.textControls.keys():
if k in cfgValues.keys():
self.textControls[k].SetValue(cfgValues[k])
else:
self.textControls[k].SetValue("")
for k in self.checkBoxes.keys():
if k in cfgValues.keys() and cfgValues[k]:
self.checkBoxes[k].SetValue(True)
elif (k == 'INCLUDE_ARDUINO') and self.includeArduino:
self.checkBoxes[k].SetValue(True)
else:
self.checkBoxes[k].SetValue(False)
self.revalidatePins()
self.assertModified(False)
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 3. PINOUTS *\n\
* *\n\
\\***************************************************************************/\n")
if self.includeArduino:
fp.write("\n#include \"arduino.h\"\n\n")
for k, cttype in self.pinXKeys + self.pinYKeys + self.pinZKeys + \
self.pinEKeys + self.pinMiscKeys:
if cttype == 1:
if self.checkBoxes[k].IsChecked():
fp.write(defineBoolFormat % k)
else:
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
class SensorsPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.parent = parent
self.id = idPg
self.includeArduino = False
self.sensorTypeKeys = ['TEMP_MAX6675', 'TEMP_THERMISTOR', 'TEMP_AD595',
'TEMP_PT100', 'TEMP_INTERCOM']
self.sensorType = {'TEMP_MAX6675': 'TT_MAX6675',
'TEMP_THERMISTOR': 'TT_THERMISTOR',
'TEMP_AD595': 'TT_AD595',
'TEMP_PT100': 'TT_PT100',
'TEMP_INTERCOM': 'TT_INTERCOM'}
self.labels = {'TEMP_HYSTERESIS': "Temperature hysteresis:",
'TEMP_RESIDENCY_TIME': "Temperature residency time:",
'TEMP_EWMA': "Temperature EMWA:",
'TEMP_MAX6675': "MAX6675",
'TEMP_THERMISTOR': "Thermistor",
'TEMP_AD595': 'AD595',
'TEMP_PT100': "PT100", 'TEMP_INTERCOM': "Intercom"}
labelWidth = 160
sz = wx.GridBagSizer()
sz.AddSpacer((30, 30), pos = (0, 0))
self.sensors = []
b = wx.StaticBox(self, wx.ID_ANY, "Sensor Types")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
ht = None
if 'TEMP_TYPES' in helpText.keys():
ht = helpText['TEMP_TYPES']
for k in self.sensorTypeKeys:
cb = self.addCheckBox(k, ht, self.onCheckBoxSensorType)
sbox.Add(cb, 1, wx.LEFT + wx.RIGHT, 10)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (1, 1), span = (5, 1))
k = 'TEMP_HYSTERESIS'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlInteger)
sz.Add(tc, pos = (1, 3))
k = 'TEMP_RESIDENCY_TIME'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlInteger)
sz.Add(tc, pos = (3, 3))
k = 'TEMP_EWMA'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlEWMA)
sz.Add(tc, pos = (5, 3))
self.lb = SensorList(self)
sz.Add(self.lb, pos = (7, 1), span = (1, 3))
bsz = wx.BoxSizer(wx.VERTICAL)
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size = BSIZESMALL)
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
self.bAdd.Enable(False)
if 'ADDSENSOR' in helpText.keys():
self.bAdd.SetToolTipString(helpText['ADDSENSOR'])
bsz.Add(self.bAdd)
bsz.AddSpacer((10, 10))
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size = BSIZESMALL)
self.bDelete.Enable(False)
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
bsz.Add(self.bDelete)
if 'DELSENSOR' in helpText.keys():
self.bDelete.SetToolTipString(helpText['DELSENSOR'])
sz.Add(bsz, pos = (7, 4))
self.SetSizer(sz)
def onCheckBoxSensorType(self, evt):
self.assertModified(True)
ct = 0
for tt in self.sensorTypeKeys:
if self.checkBoxes[tt].IsChecked():
ct += 1
if ct == 0:
self.bAdd.Enable(False)
else:
self.bAdd.Enable(True)
evt.Skip()
def onTextCtrlEWMA(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:
v = float(w)
if v < 0.1 or v > 1.0:
valid = False
else:
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 revalidatePins(self, flag):
self.includeArduino = flag
tableValid = True
for i in range(len(self.sensors)):
pn = self.sensors[i][2]
if pn == "":
valid = False
else:
m = reInteger.match(pn)
if m:
valid = True
else:
if self.includeArduino:
m = rePin.match(pn)
if m:
valid = True
else:
valid = False
else:
valid = False
self.lb.setItemValidity(i, valid)
if not valid:
tableValid = False
self.setFieldValidity('SENSORS', tableValid)
def setItemSelected(self, n):
self.selection = n
if n is None:
self.bDelete.Enable(False)
else:
self.bDelete.Enable(True)
def doAdd(self, evt):
sl = []
for tt in self.sensorTypeKeys:
if self.checkBoxes[tt].IsChecked():
sl.append(self.sensorType[tt])
nm = []
for s in self.sensors:
nm.append(s[0])
dlg = AddSensorDlg(self, nm, sl, self.includeArduino)
rc = dlg.ShowModal()
if rc == wx.ID_OK:
tt = dlg.getValues()
dlg.Destroy()
if rc != wx.ID_OK:
return
self.sensors.append(tt)
self.lb.updateList(self.sensors)
self.limitSensorTypeControls()
def doDelete(self, evt):
if self.selection is None:
return
self.assertModified(True)
del self.sensors[self.selection]
self.lb.updateList(self.sensors)
self.limitSensorTypeControls()
def limitSensorTypeControls(self):
using = {}
for s in self.sensors:
using[s[1]] = True
for k in self.sensorTypeKeys:
self.checkBoxes[k].Enable(True)
for tt in using.keys():
if not tt.startswith("TT_"):
continue
k = "TEMP_" + tt[3:]
if k in self.sensorTypeKeys:
self.checkBoxes[k].Enable(False)
def insertValues(self, cfgValues):
for k in self.textControls.keys():
if k in cfgValues.keys():
self.textControls[k].SetValue(cfgValues[k])
else:
self.textControls[k].SetValue("")
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)
ct = 0
for k in self.sensorTypeKeys:
if self.checkBoxes[k].IsChecked(): ct += 1
self.bAdd.Enable(ct != 0)
self.assertModified(False)
def setSensors(self, sensors):
self.sensors = sensors
self.lb.updateList(self.sensors)
self.revalidatePins(self.includeArduino)
self.limitSensorTypeControls()
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 4. TEMPERATURE SENSORS *\n\
* *\n\
\\***************************************************************************/\n")
for k in self.checkBoxes.keys():
if self.checkBoxes[k].IsChecked():
fp.write(defineBoolFormat % k)
for k in self.textControls.keys():
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
for s in self.sensors:
sstr = ",".join(s)
fp.write("DEFINE_TEMP_SENSOR(" + sstr + ")\n")
class SensorList(wx.ListCtrl):
def __init__(self, parent):
self.parent = parent
self.currentItem = None
wx.ListCtrl.__init__(self, parent, wx.ID_ANY, size = (495 + 4, 100),
style = wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES | wx.LC_VRULES)
self.valid = []
self.InsertColumn(0, "Name")
self.InsertColumn(1, "Sensor Type")
self.InsertColumn(2, "Pin")
self.InsertColumn(3, "Additional")
self.SetColumnWidth(0, 55)
self.SetColumnWidth(1, 105)
self.SetColumnWidth(2, 55)
self.SetColumnWidth(3, 280)
self.SetItemCount(0)
self.attr2 = wx.ListItemAttr()
self.attr2.SetBackgroundColour("light blue")
self.attr3 = wx.ListItemAttr()
self.attr3.SetBackgroundColour("pink")
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()
self.SetItemCount(len(sensorList))
def setItemValidity(self, i, flag = False):
if i < 0 or i >= len(self.sensorList):
return
self.valid[i] = flag
self.Refresh()
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 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"
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:
return s[3]
def OnGetItemAttr(self, item):
if not self.valid[item]:
return self.attr3
if item % 2 == 1:
return self.attr2
else:
return None
class AddSensorDlg(wx.Dialog):
def __init__(self, parent, names, sl, arduinoFlag):
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Add Temperature Sensor",
size = (400, 204))
self.Bind(wx.EVT_CLOSE, self.onCancel)
self.names = names
self.arduinoFlag = arduinoFlag
self.nameValid = False
self.pinValid = False
sz = wx.BoxSizer(wx.VERTICAL)
csz = wx.GridBagSizer()
csz.AddSpacer((10, 10), pos = (0, 0))
b = wx.StaticBox(self, wx.ID_ANY, "Sensor Type:")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
style = wx.RB_GROUP
self.rbs = {}
for k in sl:
rb = wx.RadioButton(self, wx.ID_ANY, k, style = style)
self.rbs[k] = rb
self.Bind(wx.EVT_RADIOBUTTON, self.onSensorType, rb)
if k in helpText.keys():
hts = helpText[k]
else:
hts = ""
rb.SetToolTipString(hts)
style = 0
sbox.Add(rb, 1, wx.LEFT + wx.RIGHT, 16)
sbox.AddSpacer((5, 5))
csz.Add(sbox, pos = (1, 3))
vsz = wx.BoxSizer(wx.VERTICAL)
vsz.AddSpacer((10, 10))
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, "Sensor Name:", size = (80, -1),
style = wx.ALIGN_RIGHT)
lsz.Add(st)
self.tcName = wx.TextCtrl(self, wx.ID_ANY, "")
self.tcName.SetBackgroundColour("pink")
self.tcName.Bind(wx.EVT_TEXT, self.onNameEntry)
lsz.Add(self.tcName)
self.tcName.SetToolTipString("Enter a unique name for this sensor")
vsz.Add(lsz)
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, "Pin:", size = (80, -1),
style = wx.ALIGN_RIGHT)
lsz.Add(st)
self.tcPin = wx.TextCtrl(self, wx.ID_ANY, "", style = wx.TE_RIGHT)
self.tcPin.Bind(wx.EVT_TEXT, self.onPinEntry)
self.tcPin.SetBackgroundColour("pink")
lsz.Add(self.tcPin)
self.tcPin.SetToolTipString("Enter a pin number/name for this sensor")
vsz.Add(lsz)
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, "Additional:", size = (80, -1),
style = wx.ALIGN_RIGHT)
lsz.Add(st)
self.tcAddtl = wx.TextCtrl(self, wx.ID_ANY, "")
self.tcAddtl.Bind(wx.EVT_TEXT, self.onAddtlEntry)
self.selectSensorType(sl[0])
lsz.Add(self.tcAddtl)
self.tcAddtl.SetToolTipString("Enter additional information required by "
"the sensor type")
vsz.Add(lsz)
csz.Add(vsz, pos = (1, 1))
csz.AddSpacer((10, 10), pos = (1, 4))
sz.Add(csz)
sz.AddSpacer((30, 30))
bsz = wx.BoxSizer(wx.HORIZONTAL)
self.bSave = wx.Button(self, wx.ID_ANY, "Save", size = BSIZESMALL)
self.bSave.Bind(wx.EVT_BUTTON, self.onSave)
bsz.Add(self.bSave)
self.bSave.Enable(False)
bsz.AddSpacer(30, 100)
self.bCancel = wx.Button(self, wx.ID_ANY, "Cancel", size = BSIZESMALL)
self.bCancel.Bind(wx.EVT_BUTTON, self.onCancel)
bsz.Add(self.bCancel)
sz.Add(bsz, flag = wx.ALIGN_CENTER_HORIZONTAL)
self.SetSizer(sz)
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()
self.checkDlgValidity()
evt.Skip()
def onPinEntry(self, evt):
tc = evt.GetEventObject()
self.validatePin(tc)
self.checkDlgValidity()
evt.Skip()
def validatePin(self, tc):
w = tc.GetValue().strip()
if w == "":
self.pinValid = False
else:
m = reInteger.match(w)
if m:
self.pinValid = True
else:
if self.arduinoFlag:
m = rePin.match(w)
if m:
self.pinValid = True
else:
self.pinValid = False
else:
self.pinValid = False
if self.pinValid:
tc.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
else:
tc.SetBackgroundColour("pink")
tc.Refresh()
def checkDlgValidity(self):
if self.nameValid and self.pinValid:
self.bSave.Enable(True)
else:
self.bSave.Enable(False)
def onAddtlEntry(self, evt):
evt.Skip()
def selectSensorType(self, lbl):
if lbl == 'TT_THERMISTOR':
self.tcAddtl.Enable(True);
else:
self.tcAddtl.Enable(False);
def onSensorType(self, evt):
rb = evt.GetEventObject()
label = rb.GetLabel()
self.selectSensorType(label)
evt.Skip()
def getValues(self):
nm = self.tcName.GetValue()
pin = self.tcPin.GetValue()
addtl = self.tcAddtl.GetValue()
for k in self.rbs:
if self.rbs[k].GetValue():
stype = k
break
if stype is None:
stype = "??"
if stype in ['TT_THERMISTOR']:
return (nm, stype, pin, addtl)
else:
return (nm, stype, pin)
def onSave(self, evt):
self.EndModal(wx.ID_OK)
def onCancel(self, evt):
self.EndModal(wx.ID_CANCEL)
class HeatersPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.parent = parent
self.id = idPg
self.includeArduino = False
self.labels = {'HEATER_SANITY_CHECK': "Heater Sanity Check"}
sz = wx.GridBagSizer()
sz.AddSpacer((30, 30), pos = (0, 0))
self.heaters = []
k = 'HEATER_SANITY_CHECK'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (3, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
self.lb = HeaterList(self)
sz.Add(self.lb, pos = (1, 1), span = (1, 3))
bsz = wx.BoxSizer(wx.VERTICAL)
self.bAdd = wx.Button(self, wx.ID_ANY, "Add", size = BSIZESMALL)
self.Bind(wx.EVT_BUTTON, self.doAdd, self.bAdd)
if 'ADDHEATER' in helpText.keys():
self.bAdd.SetToolTipString(helpText['ADDHEATER'])
bsz.Add(self.bAdd)
bsz.AddSpacer((10, 10))
self.bDelete = wx.Button(self, wx.ID_ANY, "Delete", size = BSIZESMALL)
self.bDelete.Enable(False)
self.Bind(wx.EVT_BUTTON, self.doDelete, self.bDelete)
bsz.Add(self.bDelete)
if 'DELHEATER' in helpText.keys():
self.bDelete.SetToolTipString(helpText['DELHEATER'])
sz.Add(bsz, pos = (1, 4))
self.SetSizer(sz)
def revalidatePins(self, flag):
self.includeArduino = flag
tableValid = True
for i in range(len(self.heaters)):
pn = self.heaters[i][1]
if pn == "":
valid = False
else:
m = reInteger.match(pn)
if m:
valid = True
else:
if self.includeArduino:
m = rePin.match(pn)
if m:
valid = True
else:
valid = False
else:
valid = False
self.lb.setItemValidity(i, valid)
if not valid:
tableValid = False
self.setFieldValidity('HEATERS', tableValid)
def setItemSelected(self, n):
self.selection = n
if n is None:
self.bDelete.Enable(False)
else:
self.bDelete.Enable(True)
def doAdd(self, evt):
nm = []
for s in self.heaters:
nm.append(s[0])
dlg = AddHeaterDlg(self, nm, self.includeArduino)
rc = dlg.ShowModal()
if rc == wx.ID_OK:
ht = dlg.getValues()
dlg.Destroy()
if rc != wx.ID_OK:
return
self.heaters.append(ht)
self.lb.updateList(self.heaters)
self.revalidatePins(self.includeArduino)
self.parent.setHeaters(self.heaters)
def doDelete(self, evt):
if self.selection is None:
return
self.assertModified(True)
del self.heaters[self.selection]
self.lb.updateList(self.heaters)
self.revalidatePins(self.includeArduino)
self.parent.setHeaters(self.heaters)
def insertValues(self, cfgValues):
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)
self.assertModified(False)
def setHeaters(self, heaters):
self.heaters = heaters
self.lb.updateList(self.heaters)
self.revalidatePins(self.includeArduino)
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 5. HEATERS *\n\
* *\n\
\\***************************************************************************/\n")
for k in self.checkBoxes.keys():
if self.checkBoxes[k].IsChecked():
fp.write(defineBoolFormat % k)
names = []
for s in self.heaters:
names.append(s[0])
sstr = ",".join(s)
fp.write("DEFINE_HEATER(" + sstr + ")\n")
for n in names:
if n != n.upper():
fp.write(defineHeaterFormat % (n.upper(), n))
class HeaterList(wx.ListCtrl):
def __init__(self, parent):
self.parent = parent
self.currentItem = None
wx.ListCtrl.__init__(self, parent, wx.ID_ANY, size = (165 + 4, 100),
style = wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES | wx.LC_VRULES)
self.valid = []
self.InsertColumn(0, "Name")
self.InsertColumn(1, "Pin")
self.InsertColumn(2, "PWM")
self.SetColumnWidth(0, 55)
self.SetColumnWidth(1, 55)
self.SetColumnWidth(2, 55)
self.SetItemCount(0)
self.attr2 = wx.ListItemAttr()
self.attr2.SetBackgroundColour("light blue")
self.attr3 = wx.ListItemAttr()
self.attr3.SetBackgroundColour("pink")
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()
self.SetItemCount(len(heaterList))
def setItemValidity(self, i, flag = False):
if i < 0 or i >= len(self.heaterList):
return
self.valid[i] = flag
self.Refresh()
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 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"
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"
def OnGetItemAttr(self, item):
if not self.valid[item]:
return self.attr3
if item % 2 == 1:
return self.attr2
else:
return None
class AddHeaterDlg(wx.Dialog):
def __init__(self, parent, names, arduinoFlag):
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Add Heater", size = (400, 204))
self.Bind(wx.EVT_CLOSE, self.onCancel)
self.names = names
self.arduinoFlag = arduinoFlag
self.nameValid = False
self.pinValid = False
sz = wx.BoxSizer(wx.VERTICAL)
gsz = wx.GridBagSizer()
gsz.AddSpacer((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)
lsz.Add(st)
self.tcName = wx.TextCtrl(self, wx.ID_ANY, "")
self.tcName.SetBackgroundColour("pink")
self.tcName.Bind(wx.EVT_TEXT, self.onNameEntry)
lsz.Add(self.tcName)
self.tcName.SetToolTipString("Enter a unique name for this heater")
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)
lsz.Add(st)
self.tcPin = wx.TextCtrl(self, wx.ID_ANY, "", style = wx.TE_RIGHT)
self.tcPin.Bind(wx.EVT_TEXT, self.onPinEntry)
self.tcPin.SetBackgroundColour("pink")
lsz.Add(self.tcPin)
self.tcPin.SetToolTipString("Enter a pin number/name for this heater")
gsz.Add(lsz, pos = (3, 1))
self.cbPwm = wx.CheckBox(self, wx.ID_ANY, "PWM")
self.cbPwm.SetToolTipString("Help for PWM")
gsz.AddSpacer((50, 15), pos = (1, 2))
gsz.Add(self.cbPwm, pos = (1, 3))
gsz.AddSpacer((20, 20), pos = (4, 4))
sz.Add(gsz)
sz.AddSpacer((30, 30))
bsz = wx.BoxSizer(wx.HORIZONTAL)
self.bSave = wx.Button(self, wx.ID_ANY, "Save", size = BSIZESMALL)
self.bSave.Bind(wx.EVT_BUTTON, self.onSave)
bsz.Add(self.bSave)
self.bSave.Enable(False)
bsz.AddSpacer(30, 100)
self.bCancel = wx.Button(self, wx.ID_ANY, "Cancel", size = BSIZESMALL)
self.bCancel.Bind(wx.EVT_BUTTON, self.onCancel)
bsz.Add(self.bCancel)
sz.Add(bsz, flag = wx.ALIGN_CENTER_HORIZONTAL)
self.SetSizer(sz)
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()
self.checkDlgValidity()
evt.Skip()
def onPinEntry(self, evt):
tc = evt.GetEventObject()
self.validatePin(tc)
self.checkDlgValidity()
evt.Skip()
def validatePin(self, tc):
w = tc.GetValue().strip()
if w == "":
self.pinValid = False
else:
m = reInteger.match(w)
if m:
self.pinValid = True
else:
if self.arduinoFlag:
m = rePin.match(w)
if m:
self.pinValid = True
else:
self.pinValid = False
else:
self.pinValid = False
if self.pinValid:
tc.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
else:
tc.SetBackgroundColour("pink")
tc.Refresh()
def checkDlgValidity(self):
if self.nameValid and self.pinValid:
self.bSave.Enable(True)
else:
self.bSave.Enable(False)
def getValues(self):
nm = self.tcName.GetValue()
pin = self.tcPin.GetValue()
if self.cbPwm.IsChecked():
pwm = "1"
else:
pwm = "0"
return (nm, pin, pwm)
def onSave(self, evt):
self.EndModal(wx.ID_OK)
def onCancel(self, evt):
self.EndModal(wx.ID_CANCEL)
class CommunicationsPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.parent = parent
self.id = idPg
self.defaultBaud = '115200'
self.bauds = ['19200', '38400', '57600', self.defaultBaud]
self.labels = {'BAUD': "Baud Rate:", 'USB_SERIAL': "USB Serial",
'XONXOFF': "Use XON/XOFF Flow Control"}
sz = wx.GridBagSizer()
sz.AddSpacer((20, 40), pos = (0, 0))
ch = self.addChoice('BAUD', self.bauds, self.bauds.index(self.defaultBaud),
60, None, self.onChoice)
sz.Add(ch, pos = (1, 1))
k = 'USB_SERIAL'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (3, 1))
k = 'XONXOFF'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (5, 1))
self.SetSizer(sz)
def insertValues(self, cfgValues):
self.assertValid(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)
self.setChoice('BAUD', cfgValues, self.bauds, self.defaultBaud)
self.assertModified(False)
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 6. COMMUNICATION *\n\
* *\n\
\\***************************************************************************/\n")
k = 'BAUD'
v = self.choices[k].GetSelection()
if v != "":
fp.write(defineValueFormat % (k, self.bauds[v]))
for k in self.checkBoxes.keys():
cb = self.checkBoxes[k]
if cb.IsChecked():
fp.write(defineBoolFormat % k)
class MiscellaneousPage(wx.Panel, Page):
def __init__(self, parent, nb, idPg):
wx.Panel.__init__(self, nb, wx.ID_ANY)
Page.__init__(self)
self.parent = parent
self.id = idPg
self.labels = {'MOTHERBOARD': "Motherboard", 'F_CPU': "CPU Clock Rate:",
'EECONFIG': "Enable EEPROM Storage",
'DEBUG': "Turn on debugging", 'BANG_BANG': "Enable",
'BANG_BANG_ON': "On PWM level:",
'BANG_BANG_OFF': "Off PWM level:",
'MOVEBUFFER_SIZE': "Move buffer size:",
'DC_EXTRUDER': "Heater:", 'DC_EXTRUDER_PWM': "PWM:",
'USE_WATCHDOG': "Use the watchdog timer",
'REFERENCE': "Analog Reference:",
'STEP_INTERRUPT_INTERRUPTIBLE': "STEP Interrupt",
'TH_COUNT': "Temperature History size:",
'FAST_PWM': "Fast PWM", 'ENDSTOP_STEPS': "Endstop steps:",
'CANNED_CYCLE': "Canned Cycle:"}
self.prefixKeys = ['MOTHERBOARD', 'F_CPU']
self.defaultClock = '16000000'
self.clocks = ['8000000', self.defaultClock, '20000000']
self.heaterNameNone = "<none>"
self.heaterNames = [self.heaterNameNone]
self.processors = []
self.defaultRef = 'REFERENCE_AVCC'
self.references = [self.defaultRef, 'REFERENCE_AREF',
'REFERENCE_1V1', 'REFERENCE_2V56']
sz = wx.GridBagSizer()
sz.AddSpacer((20, 40), pos = (0, 0))
sz.AddSpacer((40, 40), pos = (0, 2))
sz.AddSpacer((40, 40), pos = (0, 4))
sz.AddSpacer((20, 30), pos = (1, 0))
sz.AddSpacer((20, 30), pos = (2, 0))
sz.AddSpacer((20, 30), pos = (3, 0))
sz.AddSpacer((20, 30), pos = (4, 0))
sz.AddSpacer((20, 30), pos = (5, 0))
sz.AddSpacer((20, 30), pos = (6, 0))
labelWidth = 140
k = 'MOTHERBOARD'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (1, 1))
k = 'EECONFIG'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (2, 1))
k = 'DEBUG'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (3, 1))
k = 'USE_WATCHDOG'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (4, 1))
k = 'STEP_INTERRUPT_INTERRUPTIBLE'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (5, 1))
k = 'FAST_PWM'
cb = self.addCheckBox(k, None, self.onCheckBox)
sz.Add(cb, pos = (6, 1))
b = wx.StaticBox(self, wx.ID_ANY, "BANG BANG Bed Control")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
k = 'BANG_BANG'
cb = self.addCheckBox(k, None, self.onCheckBox)
sbox.Add(cb, 1, wx.LEFT, 60)
sbox.AddSpacer((5, 20))
k = 'BANG_BANG_ON'
tc = self.addTextCtrl(k, 80, None, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
k = 'BANG_BANG_OFF'
tc = self.addTextCtrl(k, 80, None, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (7, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
k = 'F_CPU'
ch = self.addChoice(k, self.clocks, self.clocks.index(self.defaultClock),
labelWidth, None, self.onChoice)
sz.Add(ch, pos = (1, 3))
k = 'REFERENCE'
ch = self.addChoice(k, self.references, self.references.index(self.defaultRef),
labelWidth, None, self.onChoice)
sz.Add(ch, pos = (2, 3))
b = wx.StaticBox(self, wx.ID_ANY, "DC Motor Extruder")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((5, 5))
k = 'DC_EXTRUDER'
ch = self.addChoice(k, self.heaterNames, 0, 60, None, self.onChoice)
sbox.Add(ch)
sbox.AddSpacer((5, 5))
k = 'DC_EXTRUDER_PWM'
tc = self.addTextCtrl(k, 60, None, self.onTextCtrlInteger)
sbox.Add(tc)
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (7, 3), flag = wx.ALIGN_CENTER_HORIZONTAL)
k = 'MOVEBUFFER_SIZE'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlInteger)
sz.Add(tc, pos = (1, 5))
k = 'TH_COUNT'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlInteger)
sz.Add(tc, pos = (2, 5))
k = 'ENDSTOP_STEPS'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrlInteger)
sz.Add(tc, pos = (3, 5))
k = 'CANNED_CYCLE'
tc = self.addTextCtrl(k, labelWidth, None, self.onTextCtrl)
sz.Add(tc, pos = (4, 5))
b = wx.StaticBox(self, wx.ID_ANY, "Processor Type(s):")
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
sbox.AddSpacer((125, 5))
ht = "Choose the processor(s) this configuration will work with"
for k in supportedCPUs:
cb = self.addCheckBox(k, ht, self.onCheckBox)
sbox.Add(cb)
sbox.AddSpacer((5, 5))
sbox.AddSpacer((5, 5))
sz.Add(sbox, pos = (6, 5), span = (3, 1), flag = wx.ALIGN_CENTER_HORIZONTAL)
self.SetSizer(sz)
def setHeaters(self, hlist, cfgValues = None):
k = 'DC_EXTRUDER'
if cfgValues and k in cfgValues.keys():
currentChoice = cfgValues[k][len("HEATER_"):]
else:
v = self.choices[k].GetSelection()
currentChoice = self.heaterNames[v]
h = [s[0] for s in hlist]
self.heaterNames = [self.heaterNameNone] + h
self.choices[k].Clear()
for h in self.heaterNames:
self.choices[k].Append(h)
try:
v = self.heaterNames.index(currentChoice)
except:
v = 0
self.choices[k].SetSelection(v)
def setProcessors(self, plist):
self.processors = plist
for p in supportedCPUs:
if p in self.processors:
self.checkBoxes[p].SetValue(True)
else:
self.checkBoxes[p].SetValue(False)
def insertValues(self, cfgValues):
self.assertValid(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.textControls[k].SetValue(cfgValues[k])
else:
self.textControls[k].SetValue("")
self.setChoice('F_CPU', cfgValues, self.clocks, self.defaultClock)
self.setChoice('REFERENCE', cfgValues, self.references, self.defaultRef)
self.assertModified(False)
def savePrefixValues(self, fp):
if len(self.processors) != 0:
nest = 0
for i in self.processors:
fp.write("%s#ifndef __AVR_%s__\n" % (" " * nest, i))
nest += 1
fp.write("%s#error incorrect cpu type in Makefile!\n" % (" " * nest))
for i in self.processors:
nest -= 1
fp.write("%s#endif\n" % (" " * nest))
fp.write("\n\n")
for k in self.checkBoxes.keys():
if k not in self.prefixKeys:
continue
cb = self.checkBoxes[k]
if cb.IsChecked():
fp.write(defineBoolFormat % k)
for k in self.textControls.keys():
if k not in self.prefixKeys:
continue
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
k = 'F_CPU'
v = self.choices[k].GetSelection()
fp.write(defineULFormat % (k, self.clocks[v]))
def saveValues(self, fp):
self.assertModified(False)
fp.write(
"\n/***************************************************************************\\\n\
* *\n\
* 7. MISCELLANEOUS *\n\
* *\n\
\\***************************************************************************/\n")
for k in self.checkBoxes.keys():
if k in self.prefixKeys:
continue
cb = self.checkBoxes[k]
if cb.IsChecked():
fp.write(defineBoolFormat % k)
for k in self.textControls.keys():
if k in self.prefixKeys:
continue
v = self.textControls[k].GetValue()
if v != "":
fp.write(defineValueFormat % (k, v))
k = 'REFERENCE'
v = self.choices[k].GetSelection()
fp.write(defineValueFormat % (k, self.references[v]))
k = 'DC_EXTRUDER'
v = self.choices[k].GetSelection()
if self.heaterNames[v] != self.heaterNameNone:
fp.write(defineDCExtruderFormat % (k, self.heaterNames[v]))
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Teacup Firmware Configurator",
size = (980, 450))
self.Bind(wx.EVT_CLOSE, self.onClose)
self.cfgValues = {}
self.heaters = []
self.dir = "."
panel = wx.Panel(self, -1)
sz = wx.BoxSizer(wx.HORIZONTAL)
bsz = wx.BoxSizer(wx.VERTICAL)
self.bLoadConfig = wx.Button(panel, wx.ID_ANY, "Load\nConfig", size = BSIZE)
panel.Bind(wx.EVT_BUTTON, self.onLoadConfig, self.bLoadConfig)
bsz.Add(self.bLoadConfig)
self.bLoadConfig.SetToolTipString("Choose a configuration file and load its contents")
bsz.AddSpacer((5, 5))
self.bSaveConfig = wx.Button(panel, wx.ID_ANY, "Save\nConfig", size = BSIZE)
panel.Bind(wx.EVT_BUTTON, self.onSaveConfig, self.bSaveConfig)
bsz.Add(self.bSaveConfig)
self.bSaveConfig.SetToolTipString("Save the current configuration into a C header file")
self.nb = wx.Notebook(panel, wx.ID_ANY, size = (21, 21), style = wx.BK_DEFAULT)
self.pages = []
self.titles = []
self.pageModified = []
self.pageValid = []
self.pgMech = MechanicalPage(self, self.nb, len(self.pages))
text = "Mechanical"
self.nb.AddPage(self.pgMech, text)
self.pages.append(self.pgMech)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgAcc = AccelerationPage(self, self.nb, len(self.pages))
text = "Acceleration"
self.nb.AddPage(self.pgAcc, text)
self.pages.append(self.pgAcc)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgPins = PinoutsPage(self, self.nb, len(self.pages))
text = "Pinouts"
self.nb.AddPage(self.pgPins, text)
self.pages.append(self.pgPins)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgSensors = SensorsPage(self, self.nb, len(self.pages))
text = "Temperature Sensors"
self.nb.AddPage(self.pgSensors, text)
self.pages.append(self.pgSensors)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgHeaters = HeatersPage(self, self.nb, len(self.pages))
text = "Heaters"
self.nb.AddPage(self.pgHeaters, text)
self.pages.append(self.pgHeaters)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgCommunications = CommunicationsPage(self, self.nb, len(self.pages))
text = "Communications"
self.nb.AddPage(self.pgCommunications, text)
self.pages.append(self.pgCommunications)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages))
text = "Miscellaneous"
self.nb.AddPage(self.pgMiscellaneous, text)
self.pages.append(self.pgMiscellaneous)
self.titles.append(text)
self.pageModified.append(False)
self.pageValid.append(True)
sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5)
sz.Add(bsz, 0, wx.ALL, 5)
panel.SetSizer(sz)
def buildHeaterPage(self, nb):
pg = wx.Panel(nb, wx.ID_ANY)
return pg
def buildCommPage(self, nb):
pg = wx.Panel(nb, wx.ID_ANY)
return pg
def buildMiscPage(self, nb):
pg = wx.Panel(nb, wx.ID_ANY)
return pg
def assertModified(self, pg, flag = True):
self.pageModified[pg] = flag
self.modifyTab(pg)
def assertValid(self, pg, flag = True):
self.pageValid[pg] = flag
self.modifyTab(pg)
if False in self.pageValid:
self.bSaveConfig.Enable(False)
else:
self.bSaveConfig.Enable(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 = ""
self.nb.SetPageText(pg, pfx + self.titles[pg])
def revalidatePins(self, flag):
self.pgSensors.revalidatePins(flag)
self.pgHeaters.revalidatePins(flag)
def setHeaters(self, hlist):
self.pgMiscellaneous.setHeaters(hlist)
def onClose(self, evt):
if not self.confirmLoseChanges("Exit"):
return
self.Destroy()
def confirmLoseChanges(self, msg):
if True not in self.pageModified:
return True
dlg = wx.MessageDialog(self, "Are you sure you want to " + msg +
"?\nThere are changes 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
return True
def onLoadConfig(self, evt):
if not self.confirmLoseChanges("Load a new Configuration"):
return
wildcard = "C Header files (*.h)|*.h"
dlg = wx.FileDialog(self, message = "Choose a Config file",
defaultDir = self.dir, defaultFile = "",
wildcard = wildcard, style = wx.OPEN | wx.CHANGE_DIR)
path = None
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
dlg.Destroy()
if path is None:
return
self.dir = os.path.dirname(path)
self.loadConfigFile(path)
for pg in self.pages:
pg.insertValues(self.cfgValues)
self.pgSensors.setSensors(self.sensors)
self.pgHeaters.setHeaters(self.heaters)
self.pgMiscellaneous.setHeaters(self.heaters, self.cfgValues)
self.pgMiscellaneous.setProcessors(self.processors)
def loadConfigFile(self, fn):
try:
lst = list(open(fn))
except:
return False
self.pgPins.setIncludeArduino(False)
self.sensors = []
self.heaters = []
self.processors = []
self.cfgValues = {}
self.cfgValues['E_ABSOLUTE'] = False
prevLines = ""
for ln in lst:
if ln.rstrip().endswith("\\"):
prevLines += ln.rstrip()[:-1]
continue
if prevLines != "":
ln = prevLines + ln
prevLines = ""
if ln.lstrip().startswith("//"):
continue
if ln.lstrip().startswith("#if"):
m = re.findall(reAVR, ln)
inv = []
for p in m:
if p in supportedCPUs:
self.processors.append(p)
else:
inv.append(p)
if len(inv) > 0:
if len(inv) == 1:
a = " is"
b = "it"
else:
a = "s are"
b = "them"
dlg = wx.MessageDialog(self,
"The following processor type %s not supported:\n %s\n\
Please add %s to \"supportedCPUs\"" % (a, ", ".join(inv), b),
"Unsupported Processor Type(s)",
wx.OK + wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
continue
if ln.lstrip().startswith("#define"):
m = reDefQS.search(ln)
if m:
t = m.groups()
if len(t) == 2:
self.cfgValues[t[0]] = t[1]
continue
m = reDefine.search(ln)
if m:
t = m.groups()
if len(t) == 2:
self.cfgValues[t[0]] = t[1]
continue
m = reDefBool.search(ln)
if m:
t = m.groups()
if len(t) == 1:
self.cfgValues[t[0]] = True
else:
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
m = reIncArduino.search(ln)
if m:
self.pgPins.setIncludeArduino(True)
return True
def parseSensor(self, s):
m = reSensor4.search(s)
if m:
t = m.groups()
if len(t) == 4:
return t
m = reSensor3.search(s)
if m:
t = m.groups()
if len(t) == 3:
return t
return None
def parseHeater(self, s):
m = reHeater.search(s)
if m:
t = m.groups()
if len(t) == 3:
return t
return None
def onSaveConfig(self, evt):
wildcard = "C Header files (*.h)|*.h"
dlg = wx.FileDialog(self, message = "Save as ...", defaultDir = self.dir,
defaultFile = "", wildcard = wildcard,
style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
val = dlg.ShowModal()
if val != wx.ID_OK:
dlg.Destroy()
return
path = dlg.GetPath()
dlg.Destroy()
ext = os.path.splitext(os.path.basename(path))[1]
self.dir = os.path.dirname(path)
if ext == "":
path += ".h"
fp = file(path, 'w')
timestamp = time.strftime("%Y-%b-%d %H:%M:%S", time.localtime())
fp.write("// Generated by Teacup Configurator version %s - %s\n\n" %
(VERSION, timestamp))
self.pgMiscellaneous.savePrefixValues(fp)
for pg in self.pages:
pg.saveValues(fp)
fp.close()
dlg = wx.MessageDialog(self, "File \"%s\" successfully written" % path,
"Save Successful", wx.OK + wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show(True)
app.MainLoop()